Getting unexpected Pixels from Raw Image

2019-09-18 15:39发布

问题:

I am trying to catch R, G and B from some pixels on a game scene. For this I have created a Bitmap image in Black & White.

This image is first loaded on Init(), afterwards, every sprite movement is checked for it is really an available spot.

The thing is that I am getting unexpected data at R, G and B. I tried two Bitmap images (8bit and 24bit). They both have only black and white pixels. But the r, g and b keep telling me these pixels are any other color. I think that the "no_of_channels" should be 3, as I am not working with the alpha channel, right? Any ideas?

App.h

// background mask
UIImage* bgmask;
CGImageRef aCGImageRef;
CFDataRef rawData;
UInt8 * bgmaskbuf;

Init():

    // BG Mask
    bgmask = [UIImage imageNamed:@"mask.bmp"];
    aCGImageRef = bgmask.CGImage;

    rawData = CGDataProviderCopyData(CGImageGetDataProvider(aCGImageRef));
    bgmaskbuf = (UInt8 *) CFDataGetBytePtr(rawData);

Method to check Pixel's data:

-(BOOL) checkPixel: (CGFloat)x : (CGFloat)y{

BOOL result = FALSE;


//int length = CFDataGetLength(rawData);

//for(int i=0; i<length; i+=3)
//{
//    int r = bgmaskbuf[i];
//    int g = bgmaskbuf[i+1];
//    int b = bgmaskbuf[i+2];

//    NSLog(@"Ptr: %d, R: %d, G: %d, B: %d", i, r, g, b);
//}


int no_of_channels = 3;
int image_width = SCREEN_WIDTH();

unsigned long row_stride = image_width * no_of_channels; // 960 bytes in this case
unsigned long x_offset = x * no_of_channels;

/* assuming RGB byte order (as opposed to BGR) */
row_stride * (int)y + x_offset
int r = bgmaskbuf[next_pixel];
int g = bgmaskbuf[next_pixel + 1];
int b = bgmaskbuf[next_pixel + 2];
NSLog(@"Ptr: %d, R: %d, G: %d, B: %d",next_pixel r, g, b);

if((r==0)&&(g==0)&&(b==0)){
    result = TRUE;
}

    return result;
}

How to fix this? Thanks.

Following this question:

Here's what I've made to try to solve this:

At pixel check I try to run every pixel inside:

int length = CFDataGetLength(rawData);

for(int i=0; i<length; i+=3)
{
    int r = bgmaskbuf[i];
    int g = bgmaskbuf[i+1];
    int b = bgmaskbuf[i+2];

    NSLog(@"Ptr: %d, R: %d, G: %d, B: %d", i, r, g, b);
}

Length is 786432, which makes sense (1024 * 768 pixels). I can see/read all of the pixels, in total, 2359296 bytes (R + G + B).

Now, what is weird is that, when dealing with user's touch and movements, data buffer index such as 793941 gives me EXC_BAD_ACCESS, at address 0x13200555.

This happens when I try to read it like:

row_stride * (int)y + x_offset
int r = bgmaskbuf[next_pixel];
int g = bgmaskbuf[next_pixel + 1];
int b = bgmaskbuf[next_pixel + 2];

bgmaskbuf starts at 0x13240000.

So, address range from 0x13240000 through 0x13480000 should be readable.

But I have just read this same address a while ago!

回答1:

You will need to check some values. The row stride may not actually just be the image width and the number of channels. They like padding rows to keep them on boundaries. You should be able to get that information from the image. To check you could see if checkpixel works properly on the top/bottom row(some images are also in memory upside down) to see if the values are correct.



回答2:

What really worked for me:

  • Saved the bitmap image as 1 bit only (the best and most simple way to do this is Ms Paint, I couldn't find a Mac App).
  • The generated mask was indeed rotated 180 degrees from the screen image.

For this I used only 1 channel:

-(BOOL) checkPixel: (CGFloat)x : (CGFloat)y{

BOOL result = FALSE;

int no_of_channels = 1;
int image_width = SCREEN_WIDTH();

unsigned long row_stride = image_width * no_of_channels; // 960 bytes in this case
unsigned long x_offset = x * no_of_channels;


row_stride * (int)y + x_offset
int pixie = bgmaskbuf[next_pixel];

if(pixie==0)){
    result = TRUE;
}

Instead of code rotating the mask, I thought that Image Editing easier =)

Thanks to you all!