0

I am trying to insert pixels dynamically to a PNG image file and try to retrieve it back without any alteration to pixels I saved using the code below. But I'm not successful in doing so. Can someone help me point where the problem is? Thanks.

// Original pixels for debugging only
NSString *sPixels = @"12345678";
const char *cpPixels8 = sPixels.UTF8String;

char *cpPixelsStore = calloc(sPixels.length + 1, 1);
strncpy(cpPixelsStore, cpPixels8, sPixels.length);

unsigned int r,g,b,a;
for(int j = 0; j < sPixels.length; j += 4)
{
    r = cpPixelsStore[j+0];
    g = cpPixelsStore[j+1];
    b = cpPixelsStore[j+2];
    a = cpPixelsStore[j+3];

    printf("r:0x%X g:0x%X b:0x%X a:0x%X\n", r, g, b, a);
}

int width = 2;
int height = 1;
int bytesPerRow = 4 * width;
int bitsPerComponent = 8;
int bitsPerPixel = 32;

CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | kCGImageAlphaLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, cpPixelsStore, (bytesPerRow * height), NULL);

CGImageRef imRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

CGDataProviderRelease(provider);

UIImage *imNewTemp = [UIImage imageWithCGImage:imRef];
NSData *datPNG = UIImagePNGRepresentation(imNewTemp);

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *sFile = [documentsDirectory stringByAppendingPathComponent:@"Pic.png"];

[datPNG writeToFile:sFile atomically:YES];

CGImageRelease(imRef);

// Cross verify save
UIImage *imTemp = [UIImage imageWithContentsOfFile:sFile];
NSData *datImagePixels = (__bridge NSData *)CGDataProviderCopyData(CGImageGetDataProvider(imTemp.CGImage));
unsigned char *ucpPixelBytes = (unsigned char *)[datImagePixels bytes];

for(int j = 0; j < datImagePixels.length; j += 4)
{
    r = ucpPixelBytes[j+0];
    g = ucpPixelBytes[j+1];
    b = ucpPixelBytes[j+2];
    a = ucpPixelBytes[j+3];

    printf("r:0x%X g:0x%X b:0x%X a:0x%X\n", r, g, b, a);
}

Initial printf returns this during creation: r:0x31 g:0x32 b:0x33 a:0x34 r:0x35 g:0x36 b:0x37 a:0x38

printf after saving and retrieving the file gives this output: r:0xA g:0xA b:0xA a:0x31 r:0xC g:0xB b:0xB a:0x35

I'm lost in translation. Please help.

A 1
  • 1

1 Answers1

0

NSData is immutable - you need a NSMutableData object, then you use 'mutableBytes' to get the pointer. NSMutableData *nData = [NSMutableData dataWithData:datImagePixels];

Now you have the data to create a NEW image with your modifications. You can use the Quartz method CGImageCreate() to get a CGImageRef, and from that a UIImage.

David H
  • 40,852
  • 12
  • 92
  • 138
  • Based on your suggestion, I modified my code as shown below and it still does not work. I still do not know what I'm doing wrong. // Cross verify save UIImage *imTemp = [UIImage imageWithContentsOfFile:sFile]; NSData *datImagePixels = (__bridge NSData *)CGDataProviderCopyData(CGImageGetDataProvider(imTemp.CGImage)); NSMutableData *nData = [NSMutableData dataWithData:datImagePixels]; unsigned char *ucpPixelBytes = (unsigned char *)[nData bytes]; – A 1 Aug 29 '12 at 19:04
  • char *ucpPixelBytes = (unsigned char *)[nData mutableBytes] - mutableBytes, just as I said originally. What I suggest you do first is just set the bytes to a single color, verify that code works, then proceed to more complex changes. This is complex/tedious stuff - you need to query the CGImage for its width, height, rowbytes, pixel layout, etc etc. – David H Aug 29 '12 at 19:28