Simple image rotation - java

I am making a game in Java. I made a planet seen from outer space and I want to make it appear like the planet is slowly rotating. But I don't know how to rotate a image. I need a simple command that rotates my image 1 degree around its own center once. Any help?
This is what I want to do:
Image

Take a look at these tutorials:
Java2D: Have Fun With Affine Transform
Coordinate Translations and Rotations: Example Code
Transforming Shapes, Text, and Images

What you are describing is not rotating an image, but changing an image to represent a 3D rotation of the object in the image.
Ideally you wouldn't be working with this as an image but rather as a 3D object with a different camera angle. Then you would simply rotate the camera around the object and display the resulting image to the user.
However if you're set on doing this as an image, then you need to create a different images representing various states of rotation of your planet and have a separate thread that would replace the displayed image with the next one in sequence, at repeated intervals. Search the web for "java image animation" - there are plenty of tutorials on how to do this.
If you want to rotate an image in 2d space, you can use something like this:
Image image = ...
Graphics2D g2d = ...; //
g2d.translate(170, 0); // If needed
g2d.rotate(1); // Rotate the image by 1 radian
//or g2d.rotate(180.0/3.14); to rotate by 1 degree
g2d.drawImage(image, 0, 0, 200, 200, observer);

Related

Drawing images to 4 different points

I have a quadrilateral drawn in Path2D, and I would like for there to be an image on it. More specifically, I am trying to draw an image of my choice to 4 different points on a quadrilateral. In my case, it is a parallelogram. I do not want the image to go over the paralellogram. A better way to see what I am trying to say is to see the screenshot below.
I would like the image to be transformed to fit the green area. Not clipped.
I want the image to be pinned over the green paralellogram. However. I do not want the image to go over into the blue paralellogram, or the white space foe that matter.
So far I have tried
Researching for a way to place images directly onto Path2D.Double() objects. No answer
Rotating the image to fit the paralellogram. Didnt work.
Using AffineTransform in java. Dont get it ;-;
Thanks. I am new to java so do try to be lenient?
One way is to:
create a separate BufferedImage.
Apply a transform to the new image.
Draw your image to that new image.
Use the Shape object for the green area as a clip on the main drawing area
Draw the transformed image onto the main drawing area.
It's been a while since I have done transformations. You may have to set the transformation first and then draw the image after. Transformation has to come first.
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.transform(AffineTransform.getShearInstance(1.0, 0));
g2.drawImage(image, 0, 0, this);
}
Here is a simple example of how transforms work. You will have to spend some time on figuring out what values you need to make it work or if you might need to manually create a transformation matrix yourself.

Adjusting an image to any given quadrilateral

I have a cube which can be rotated in x,y and z direction.I figured out how to draw its wireframe and how to fill the sides with one colour per side.But my attempts to texture the cube failed.All possibilities to adapt an image to non-cubic shapes I have found use an external library but I want to do it in pure java.
Here is what i tried:
Polygon polygon = new Polygon();
polygon.addPoint((int)p[1][x]+200, (int)p[1][y]+200);
polygon.addPoint((int)p[2][x]+200, (int)p[2][y]+200);
polygon.addPoint((int)p[6][x]+200, (int)p[6][y]+200);
polygon.addPoint((int)p[5][x]+200, (int)p[5][y]+200);
g.setClip(polygon);
g.drawImage(tex, (int)p[1][x]+200, (int)p[1][y]+200, null);
g.setClip(new Rectangle(0, 0, this.getWidth(), this.getHeight()));
you have to transform the image, you can shear, rotate, translate etc on your image...
to do so you need an Affine-matrix to transform the image...
once you know how to use the matrix you can also use it to transform your points, it's a very comfortable way
see also the a question on how to shear a bitmap:
btw: nice work, there doing it in pure java!
sorry, when i'm only responding in sending links, but maybe you can be a bit more specific on your ptoblem =)

Graphics2D: How to create consistent padding around an irregular shape?

I'm using Java Graphics2D to generate this map with some sort of tinted red overlay over it. As you can see, the overlay gets cut off along the image boundary on the left side:-
After demo'ing this to my project stakeholders, what they want is for this overlay to clip along the map boundary with some consistent padding around it. The simple reason for this is to give users the idea that the overlay extends outside the map.
So, my initial thought was to perform a "zoom and shift", by creating another larger map that serves as a "cookie cutter", here's my simplified code:-
// polygon of the map
Polygon minnesotaPolygon = ...;
// convert polygon to area
Area minnesotaArea = new Area();
minnesotaArea.add(new Area(minnesotaPolygon));
// this represents the whole image
Area wholeImageArea = new Area(new Rectangle(mapWidth, mapHeight));
// zoom in by 8%
double zoom = 1.08;
// performing "zoom and shift"
Rectangle bound = minnesotaArea.getBounds();
AffineTransform affineTransform = new AffineTransform(g.getTransform());
affineTransform.translate(-((bound.getWidth() * zoom) - bound.getWidth()) / 2,
-((bound.getHeight() * zoom) - bound.getHeight()) / 2);
affineTransform.scale(zoom, zoom);
minnesotaArea.transform(affineTransform);
// using it as a cookie cutter
wholeImageArea.subtract(minnesotaArea);
g.setColor(Color.GREEN);
g.fill(wholeImageArea);
The reason I'm filling the outside part with green is to allow me to see if the cookie cutter is implemented properly. Here's the result:-
As you can see, "zoom and shift" doesn't work in this case. There is absolutely no padding at the bottom right. Then, I realized that this technique will not work for irregular shape, like the map... and it only works on simpler shapes like square, circle, etc.
What I want is to create consistent padding/margin around the map before clipping the rest off. To make sure you understand what I'm saying here, I photoshopped this image below (albeit, poorly done) to explain what I'm trying to accomplish here:-
I'm not sure how to proceed from here, and I hope you guys can give me some guidance on this.
Thanks.
I'll just explain the logic, as I don't have time to write the code myself. The short answer is that you should step through each pixel of the map image and if any pixels in the surrounding area (i.e. a certain distance away) are considered "land" then you register the current pixel as part of the padding area.
For the long answer, here are 9 steps to achieve your goal.
1. Decide on the size of the padding. Let's say 6 pixels.
2. Create an image of the map in monochrome (black is "water", white is "land"). Leave a margin of at least 6 pixels around the edge. This is the input image: (it isn't to scale)
3. Create an image of a circle which is 11 pixels in diameter (11 = 6*2-1). Again, black is empty/transparent, white is solid. This is the hit-area image:
4. Create a third picture which is all black (to start with). Make it the same size as the input image. It will be used as the output image.
5. Iterate each pixel of the input image.
6. At that pixel overlay the hit-area image (only do this virtually, via calculation), so that the center of the hit-area (the white circle) is over the current input image pixel.
7. Now iterate each pixel of the hit-area image.
8. If the any white pixel of the hit-area image intersects a white pixel of the input image then draw a white pixel (where the center of the circle is) into the output image.
9. Go to step 5.
Admittedly, from step 6 onward it isn't so simple, but it should be fairly easy to implement. Hopefully you understand the logic. If my explanation is too confusing (sorry) then I could spend some time and write the full solution (in Javascript, C# or Haskell).

Crop and keep the size of an image android

This is a really hard question to explain in words (well it is for me anyway). I need to be able to take an image (bitmap) and crop the image down to a certain size in the centre of the screen but keeping the size of the image the same. Hopefully the picture below can explain what I mean:
So the image as a whole is cropped down to the square in the middle but is not stretched across the screen and remains in the centre, so basically removing the pointless part of the image but keeping to co-ordinates of the pixels the same.
So let's say you have done your face detection, and have found one face in your image. Your image is 320 x 240, and the face is bound by the rectangle with location 100,40 and width 20 x 30. Now what would you like to do with that information? I'll do my best to help, but you'll probably need to clear up any poor assumptions on my part.
First, you can grab the face and store it into a new bitmap with something like Bitmap.createBitmap():
Bitmap face = Bitmap.createBitmap(largeSource, 100, 40, 20, 30);
This should be done outside of the draw loop, like in onCreate or some other initialization step.
It sounds like you've got some container (ImageView? Custom View with overridden onDraw?) which is housing your large image. And now you want to just draw the face in that container, at its original position? If you've got a custom view, that's as simple as the following in your onDraw:
canvas.drawBitmap(face, 100, 40, facePaint);
If you're using an ImageView instead, I'd suggest going to a custom-drawn view instead, since it sounds like you need some fine-grained drawing control.
Finally, if you've got a bunch of these faces, create a new FaceObj POJO object, which just has a bitmap, x, and y coordinate. As you detect faces, add them to an ArrayList, and then iterate over this in in your onDraw to draw all your faces:
faces.add(new FaceObj(Bitmap.createBitmap(largeSource, 100, 40, 20, 30), 100, 40);
...
foreach(FaceObj f : faces)
canvas.drawBitmap(f.bitmap, f.x, f.y, facePaint);
If I understand you don't really want to crop your image but "hide" any pixels around the square.
There are many ways to do this depending on what you are trying to do. For example you can fill the uninteresting part of the picture with black or make it transparent.
This way the coordinates of your "cropped" picture will remain the same on the screen.
If all you are interested in is the center of the image, then one really easy way to do this is to just add the android:scaleType="center" attribute to your ImageView, and set the ImageView to the crop size you want. If you're wanting it to be positionable, though, that's a different story.
Using Canvas.drawBitmap() you might be able to work to copy a part of the image to a different bitmap, and discard the other. With this particular version of the method, you can send in the array of colors you get with getPixels(), and set an offset, and the width and height that you want to copy. The stride parameter is important though, as it needs to be set to the width of the original image, even if your final image will be smaller, as it's pulling pixels from the original image.

Why does my smudge image algorithm make the image darker?

I'm trying to write a graphical effect where a circle moves around an image smudging the image as it goes (like the way the smudge tool in Gimp or Photoshop would work). The basic algorithm I'm using is:
the circle moves from position A to position B on the bitmap
copy a circle of pixels from position A into a temporary bitmap
draw this circle of pixels from the temporary bitmap to position B using alpha of about 50%.
This works fine and looks like what I would expect, where the image will look like it's getting smudged if the circle moves 1 pixel at a time over the image.
I now want to add some texture to the smudge effect. I have a bitmap that contains a picture of a paint blob. The algorithm from the above is modified to the following so the smudge takes the shape of this paint blob:
as before
replace the temporary bitmap pixels with the paint blob texture then copy the circle of pixels from position A into the temporary bitmap but only keep the pixels that match up against paint blob pixels (i.e. use Porter-Duff "source in destination" mode when drawing the circle into the temporary bitmap).
as before
This almost works and it looks like it's fine initially but gradually the smudging makes the colors in my image darker! If the circle passes over the same area several times, the colors eventually change to black. Any ideas what I could be doing wrong?
I've implemented the above in Android. I happened upon this post about bitmaps in Android (like my paint blob texture) being loaded with "premultiplied alpha", where the author says it caused his images to become darker because of it:
http://www.kittehface.com/2010/06/androidbitmap-and-premultiplied-alpha.html
I suspect I'm suffering from a similar problem but I don't understand what's going on well enough and don't know how to fix it. Does anyone have hints at what might be going on?
Well from first glance the reason the image is getting darker is because #3 in the first three steps. You overlaying a pixel over an existing pixel at 50%. You might want to consider using the mean of the original pixel value and the new pixel value. You might want to research some blurring algorithms.

Categories