2007.07.12 15:21 "[Tiff] how to rotate an image", by Oliver Geisen

2007.07.16 04:57 "[Tiff] Image Roation by 180 degrees", by Richard Nolde

Oliver wrote:

I found your code, compiled it, and it worked well, good work!

But allow me some questions/conclusions about that: What i want to do is, image rotation by 180 degrees only. The whole point in processing images with libtiff is that one have only a limited part of the image inside a memoryblock to work with. This is an advantage because some images (our own also) will get very big.

Special care must be taken if imagedata is bilevel (1 bit per pixel) but converting all the data into an 8 bit pixel, process it and reconvert it to 1 bit pixels seems to be clumsy.

Oliver,
  I do not convert each pixel into a full byte and the rewrite it.

If you look at the code in tiffcrop, you will see that it is all done with tight loops addressing one byte at a time, but not expanding each bit to a full byte. It involves a series of shifts and masks, tracking the bit offset within the source and destination bytes and carrying the "extra" bits over to the next byte each time for non-aligned scenarios. There are separate cases for handling byte aligned and non-aligned data to optimize the performance whenever possible. If you are going to use a lookup table, you might as well reverse the whole byte in one operation, but again this only works for the simple case of byte aligned data. I handle the cases where the start and/or ending pixels are not byte aligned as well as the simple cases where one or both are byte aligned. For 90 or 270 degrees you are reading one byte at a time but writing each bit of that byte to a different address in the output raster, hence the performance degradation.

The current limitation of my code is that I read an entire image into memory in one pass. It handles strips and tiles for you. However, since the rotation code works only on input and output buffer pointers, it has no way to know whether you are calling it with one scanline or the whole image. Just remove the outer loop that iterates over the whole image and pass it one row at a time. This will work fine for any rotation as long as you allocate the entire output buffer before the first call and add the additional parameters to track the current row or column which you must do in your calling function. You would just be moving the outer loop from my rotation function into your calling function and reading the input image one line at a time instead of all at once. Unless the image is very large and causes swapping on your system, I doubt that the change will make much difference as most of the time is spent in reading and writing the image to/from disk.

For tiles, I think you will have to read and track enough tiles to make up a full scanline at a time unless you want to thrash your disk system re-reading them repeatedly to pull one line of data out of each tile and piece them together to make a scanline each time. Alternately, if the tiles contain a multiple of 8 bits, you could just swap the top left tile with the bottom right one while reversing the bits. For lines that are not a multiple of 8 bits, you will have to "borrow and carry" them across tiles.

My code is intended for processing a series of two or three hundred smaller images, say 2600x4200, or ten or twenty 14400x10800 pixel images in a single file so it makes extensive use of the same buffers rather than allocating a buffer for each image.

Richard Nolde