Re: Flip an NSBitmapImageRep
Re: Flip an NSBitmapImageRep
- Subject: Re: Flip an NSBitmapImageRep
- From: Tom Coates <email@hidden>
- Date: Sat, 14 Oct 2006 00:50:55 -0700
Simon-
I think this is relatively easy directly in objective C. At least it
is for monochrome (greyscale) images. I haven't ever tried it on
colored images, but the same techniques should still work.
For a Monochrome image, use the bitmapData method of NSBitmapImageRep
to obtain a pointer to an array of bytes that represents the pixel-by-
pixel brightness values of the image. Each byte ranges from 0
(black) to 255 (white) for that pixel. The data is organized row-by-
row. You can determine the number rows with method pixelsHigh. You
can determine the number of bytes per row with the (duh) bytesPerRow
method. Note that bytesPerRow isn't the same as pixelsWide, due to
some storage alignment issues - bytesPerRow is often larger. Once
you understand this structure you can directly change the contents of
the image just by writing to values offset from the pointer to the
bitmapData.
Here's an example of code that does a 180 degree rotation of a
subclassed Monochrome image.
- (void)rotate180
{
int x, y, w, h, bytesPerRow ;
unsigned char *pData ;
unsigned char *pTop ;
unsigned char *pBottom ;
unsigned char byte ;
// obtain a pointer to the monochrome/greyscale data
pData = [self bitmapData] ;
w = [self pixelsWide] ;
h = [self pixelsHigh] ;
bytesPerRow = [self bytesPerRow] ;
// Swap the contents of the outermost rows, then the next rows,
working from
// top&bottom toward the middle.
for (y = 0 ; y < h/2 ; ++y)
{
pTop = pData + y * bytesPerRow ;
pBottom = pData + (h-y-1) * bytesPerRow + w - 1 ;
for (x = 0 ; x < w ; ++x)
{
byte = *pTop ;
*pTop++ = *pBottom ;
*pBottom-- = byte ;
}
}
// If the height is an odd number of rows, then we have to reverse
the order
// of the middle row.
if ((h % 2) == 1)
{
y = h/2 ;
pTop = pData + y * bytesPerRow ; // Actually left edge
pBottom = pTop + w - 1 ; // Actually right edge of the
same row
for (x = 0 ; x < w/2 ; ++x)
{
byte = *pTop ;
*pTop++ = *pBottom ;
*pBottom-- = byte ;
}
}
} // rotate180
This could be easily modified to make your horizontal flip. Note
that the last section does exactly that operation on a single row.
You would just have to drop the first for-loop and modify the last
major block into a loop over all of the rows (looping on y).
A vertical flipper could also be implemented easily, by swapping
whole rows from top and bottom. The same technique allows you do
operations like inverting each pixel, i.e. making a negative image.
Just do
value = (255-Value)
on each pixel.
For full color bitmaps, the problem gets more complicated, but not
outrageously so. The bitmap data consists of three-bytes per pixel,
for RGB. But there may be other variations. And those three bytes
can be organized in at least two ways. One is "planar", with all the
Red pixels first, then the Green Pixels, then the Blue pixels.
Effectively you have three monochrome images to flip. But the image
could also be "meshed", stored in groups of three-bytes, for each
pixel, alternating RGB-RGB-RGB-RGB etc. In that case, you have to
swap left and right pixels in each row, three bytes at a time. You
can tell the two types apart using method isPlaner. And you can tell
how many color bytes there are per pixel with method samplesPerPixel.
So making a roll-your-own generic image flipper could take some work
to cover all the cases. But if you have only images of a single
type, then you can easily do something like the above code.
Hope that helps.
Tom :::/
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden