0
votes

I'm trying to do something very simple:

1) Draw a UIImage into a CG bitmap context

2) Get a pointer to the data of the image

3) iterate over all pixels and just set all R G B components to 0 and alpha to 255. The result should appear pure black.


This is the original image I am using. 200 x 40 pixels, PNG-24 ARGB premultiplied alpha (All alpha values == 255):

original


This is the result (screenshot from Simulator), when I do not modify the pixels. Looks good:

unmodified result


This is the result, when I do the modifications! It looks like if the modification was incomplete. But the for-loops went over EVERY single pixel. The counter proves it: Console reports modifiedPixels = 8000 which is exactly 200 x 40 pixels. It looks always exactly the same.

modified result

Note: The PNG image I use has no alpha < 255. So no transparent pixels.


This is how I create the context. Nothing special...

int bitmapBytesPerRow = (width * 4);
int bitmapByteCount = (bitmapBytesPerRow * imageHeight);

colorSpace = CGColorSpaceCreateDeviceRGB();

bitmapData = malloc(bitmapByteCount);
bitmapContext = CGBitmapContextCreate(bitmapData,
                width,
                height,
                8, // bits per component
                bitmapBytesPerRow,
                colorSpace,
                CGImageAlphaPremultipliedFirst);

Next, I draw the image into that bitmapContext, and obtain the data like this:

void *data = CGBitmapContextGetData(bitmapContext);

This is the code which iterates over the pixels to modify them:

size_t bytesPerRow = CGImageGetBytesPerRow(img);

NSInteger modifiedPixels = 0;
for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
        long int offset = bytesPerRow * y + 4 * x;

        // ARGB
        unsigned char alpha = data[offset];
        unsigned char red = data[offset+1];
        unsigned char green = data[offset+2];
        unsigned char blue = data[offset+3];

        data[offset] = 255;
        data[offset+1] = 0;
        data[offset+2] = 0;
        data[offset+3] = 0;

        modifiedPixels++;
    }
}

When done, I obtain a new UIImage from the bitmap context and display it in a UIImageView, to see the result:

CGImageRef imageRef = CGBitmapContextCreateImage(bitmapContext);
UIImage *img = [[UIImage alloc] initWithCGImage:imageRef];

Question:

What am I doing wrong?

Is this happening because I modify the data while iterating over it? Must I duplicate it?

2
Are you sure that's the right code? It's setting everything to 255, which should turn up as white.tc.
Yes, right code. I just forgot to edit these values here. Previously I tried to make the image white, but the example image was hard to see here on the white background. So I made it black.Proud Member
the code is using blank memory from malloc(), but the example is pre-populated with an image, i'm wondering if the image isn't in the exact format you think it isbshirley
I've updated the question. Hope it's clear now. The malloc() is just for creating the context. Then the image gets drawn into it, and then I obtain the data pointer from the context.Proud Member
sounds like a padding problemJohnmph

2 Answers

1
votes

Might you're getting wrong height or width.... and by the way 240x40=9600 not 8000 so that's for sure that you're not iterating over each and every pixel.

1
votes

Use CGBitmapContextGetBytesPerRow(bitmapContext) to get bytesPerRow instead getting from image (image has only 3 bytes per pixels if it hasn't alpha informations)