Note: This file has moved to notablog.
Note: See the html-ified and greatly enhanced version of this article.lloyd asks: > I need to: > Create an application that would view, zoom, rotate and move > images (firstly gif, png & jpg, later on tiff and all the rest). I _strongly_ suggest you look into SVG and the apache Batik project. All of this gets MUCH easier if you're just building an SVG document that explains how to render the image, and the Batik library or the Adobe SVG plugin take care of rendering it. > I use JPanel in JFrame to view, rotate and scale images using > Graphics2D. I presume you're doing this with AffineTransforms? > How can I move the images inside JPanel if the size of the zoomed > image is much bigger then my window? The size of the "zoomed image" is bigger than your window, but you're only going to render the chunk that fits inside your window, right? Come to think of it, when I was messing with this stuff I don't think I ever needed to zoom the image bigger than the window. > How can I center the images in the window if the size of the > image is smaller then window? This is way too complicated for me to explain it in depth in the time I have, but basically you keep track of your image dimension, window dimension, image rotation, move offset, and and I guess in your case zoom level. Come rendering time, you carry out a sequence of AffineTransforms based on the numbers. I suggest for now you assume symetric images, to simplify the math, and worry about asymetric images later - basically you handle his by calculating the numbers independently for width vs. height. Also, remember that for now we're assuming that this is all in the render step, you're just checking a set of numbers (scaling, etc) that you've been keeping track of. The big gotcha to watch out for is order-of-operations. The one I found to work was: rotate, translate, scale. Do NOT assume you can switch the sequence and it'll still work the same. First you rotate it around it's center coordinate, i.e. myAffineTransform.rotate(degrees, originalHeight/2, originalWidth/2)) Do this first, because you just plain don't want to deal with the grief of rotating an off-centered image and then figuring out the right set of offsets to translate it back to center. By doing this first, you keep it simple. Then you figure out how much you'll need to offset it. This is where you have to stop and think carefully about things like, how big the image is, how big you plan to scale it, how big the space you plan to draw it in is, etc. It's not that it takes any genius or twisty math, but it's easy to forget a step. In this example, since we're assuming square images and square windows, it's easy, but even to say this clearly I have to stop and use a step by step list: 1) take either dimension of the original image (width or height) 2) multiply dimension by the scaling amount you're planning to use in the last step, to get the scaled image dimension. 3) subtract scaled image dimension from the corresponding dimension of the window to get the difference. 4) divide the difference in two to get the offset 5) translate the image up and over by the offset with affineTransform.translate() Now, if you're going to use rectangular images or rectangular windows, this is complicated in two ways. First, you have to do that series of steps above independently for each window. Second, you have to figure out how the rotation affected the image height and width. If you're dealing with rotations that don't divide easily into 90 degree chunks, it's even more complicated, since you can't just flip the width/height around. Now, to further complicate matters, if you're going to deal with images that may be larger than the window, you have to figure out how the negative values, etc, affect things. However, other than that it really doesn't change the steps - you still have to figure out how much to shove it horizontally and vertically to keep it centerd. You'll have to use clipping, described at the URL below, to keep java from drawing any of the image that's outside the window: http://java.sun.com/docs/books/tutorial/2d/display/clipping.html Anyway, so finally, you scale it with an affineTransform.scale(). Since you did all the annoying math before you scaled it, the scaled image should be centered nicely in your drawing area. Steven J. Owens puff@guild.net