vImage ARGB frustrations
vImage ARGB frustrations
- Subject: vImage ARGB frustrations
- From: Jeff LaMarche <email@hidden>
- Date: Tue, 3 Feb 2004 14:04:36 -0500
Playing around with the new vImage api in the Acceleration framework.
The big issue (I think) that I'm hitting is that vImage wants
everything in ARGB (8888 or FFFF) or planar format. My source NSImages
that I have are typically RGB, although I'm trying to code to handle
RGBA or grayscale images as well. I understand the reasons for using
ARGB in a performance-tuned image-processing engine, but it would have
been nice if they had given us a little more common ground between
vImage and NSImage.
My attempts to add a blur method to NSImage in a category have been
complete unsuccessful. In order to be able to use the
vImageConvolve_ARGB8888 method, I'm trying create ARGB bitmap data from
my bitmap image - I'm guessing that this might be a problem in an image
with a premultiplied alpha, but in my case, my test image is a plain
old RGB bitmap with no alpha channel, and it's still not working.
Basically, I'm getting an NSBitmapImageRep, and looping through it
pixel-by-pixel, copying the results to an NSMutableData that's large
enough to hold the same image with four channels (A,R,G,B)
else if (bpp == 3) // RGB
{
p2[0] = 255; //A
p2[1] = p1[0]; //R
p2[2] = p1[1]; //G
p2[3] = p1[2]; //B
}
Probably not fast, but seems like it should generate the ARGB data I
need, right? Or is ARGB8888 more complex than that? Does anyone have
code they'd share that shows how to get ARGB data out of an NSImage or
NSBitmapImageRep?
I'll post the entirety of my source code (two categories, one on
NSImage and one on NSData) at the end of the e-mail... I'd be much
obliged if anyone can point my stupidity out to me.
Thanks,
Jeff
@implementation NSImage(vImage)
//
------------------------------------------------------------------------
--------------------------------
- (NSImage *)blur:(int)radius
//
------------------------------------------------------------------------
--------------------------------
{
// Yeah, I know, this should probably be a category on
NSBitmapImageRep.. shoot me.
int matrixDimension = (radius*2)+1;
int16_t kernel[matrixDimension^2];
int16_t *kernelPtr = &kernel;
vImage_Buffer src;
vImage_Buffer dst;
NSImage *finalImage;
// We need an ARGB8888 bitmap, but typically will get RGB or
premultiplied RGBA
// NSBitmapImageRep *imageRep = [NSBitmapImageRep
imageRepWith
Data:[self TIFFRepresentation]];
if (self != nil)
{
src.height = [self size].height;
src.width = [self size].width;
src.rowBytes = [self size].width * 4;
// This call swaps the bits around to ARGB, padding with extra
bits if necessary
NSMutableData *srcData = [self ARGB8888Data];
src.data = [srcData bytes];
NSMutableData *destData = [NSMutableData dataWithCapacity:[srcData
length]];
dst.height = [self size].height;
dst.width = [self size].width;
dst.rowBytes = [self size].width * 4;
dst.data = [destData mutableBytes];
// The Blur function comes from the sample code for vImage, and simply
loads a packed array with the values for a blur...
int divisor = Blur( kernelPtr, matrixDimension, matrixDimension);
vImageConvolve_ARGB8888 (&src, &dst, NULL, 0, 0, kernelPtr,
matrixDimension, matrixDimension, divisor, NULL, kvImageEdgeExtend);
NSBitmapImageRep *destImageRep = [NSBitmapImageRep
imageRepWith
Data:[destData RGBDataFromARGBDataWithWidth:[self
size].width andHeight:[self size].height]];
finalImage = [[NSImage alloc] initWithSize:[self size]];
[finalImage addRepresentation:destImageRep];
}
else return nil;
return [finalImage autorelease];
}
//
------------------------------------------------------------------------
--------------------------------
- (NSMutableData *)ARGB8888Data
//
------------------------------------------------------------------------
--------------------------------
{
NSBitmapImageRep *imageRep = [NSBitmapImageRep
imageRepWith
Data:[self TIFFRepresentation]];
int width = [imageRep pixelsWide];
int height = [imageRep pixelsHigh];
int x, y;
NSMutableData *ret = [NSMutableData
dataWithCapacity:width*height*4];
unsigned char *srcData = [imageRep bitmapData];
unsigned char *destData = [ret mutableBytes];
unsigned char *p1, *p2;
int bpp = [imageRep bitsPerPixel] / 8;
for ( y = 0; y < height; y++ )
{
for ( x = 0; x < width; x++ )
{
p1 = srcData + bpp * (y * width + x);
p2 = destData + 4 * (y * width + x);
if (bpp == 1) // Grayscale
{
// I don't think this is the best way to convert a grayscale
// image into an ARGB... **** TO DO: Research
p2[0] = 255; //A
p2[1] = p1[0]; //R
p2[2] = p1[0]; //G
p2[3] = p1[0]; //B
}
else if (bpp == 3) // RGB
{
p2[0] = 255; //A
p2[1] = p1[0]; //R
p2[2] = p1[1]; //G
p2[3] = p1[2]; //B
}
else if (bpp == 4) // RGBA
{
p2[0] = p1[3]; //A
p2[1] = p1[0]; //R
p2[2] = p1[1]; //G
p2[3] = p1[2]; //B
}
else
{
NSLog(@"ARGB8888 data can't be generated; unrecognized source
format!.");
[imageRep release];
return nil;
}
}
}
[imageRep release];
return ret;
}
@end
@implementation NSData(Filter)
//
------------------------------------------------------------------------
--------------------------------
- (NSData *)RGBDataFromARGBDataWithWidth:(int)width
andHeight:(int)height
//
------------------------------------------------------------------------
--------------------------------
{
int i, j;
unsigned char *p1, *p2;
NSMutableData *ret = [NSMutableData dataWithCapacity:[self
length]*.75];
unsigned char *srcData = [self bytes];
unsigned char *destData = [ret mutableBytes];
for (i = 0; i < width; i++)
{
for (j=0; j < width; j++)
{
p1 = srcData + 4 * (i * width + j);
p2 = destData + 3 * (i * width + j);
p2[0] = p1[1]; // R
p2[1] = p1[2]; // G
p2[2] = p1[3]; // B
}
}
return ret;
}
//
------------------------------------------------------------------------
--------------------------------
- (NSData *)RGBADataFromARGBDataWithWidth:(int)width
andHeight:(int)height
//
------------------------------------------------------------------------
--------------------------------
{
int i, j;
unsigned char *p1, *p2;
NSMutableData *ret = [NSMutableData dataWithCapacity:[self length]];
unsigned char *srcData = [self bytes];
unsigned char *destData = [ret mutableBytes];
for (i = 0; i < width; i++)
{
for (j=0; j < width; j++)
{
p1 = srcData + 4 * (i * width + j);
p2 = destData + 4 * (i * width + j);
p2[0] = p1[1]; //R
p2[1] = p1[2]; //G
p2[2] = p1[3]; //B
p2[3] = p1[0]; //A
}
}
return ret;
}
@end
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.