4

The Goal:

Finding the first black pixel on the left side of an image that contains black and transparent pixels only.

What I have:

I know how to get the pixel data and have an array of black and transparent pixels (found it here : https://stackoverflow.com/a/1262893/358480 ):

+ (NSArray*)getRGBAsFromImage:(UIImage*)image atX:(int)xx andY:(int)yy count:(int)count
{
 NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];

// First get the image into your data buffer
CGImageRef imageRef = [image CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = malloc(height * width * 4);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                             bitsPerComponent, bytesPerRow, colorSpace,
                                             kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);

// Now your rawData contains the image data in the RGBA8888 pixel format.
int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel;
for (int ii = 0 ; ii < count ; ++ii)
{
    NSUInteger alpha = (rawData[byteIndex + 3] * 1.0) / 255.0;
    byteIndex += 4;
    [result addObject:[NSNumber numberWithInt:alpha]];
}

free(rawData);

return result;
}

What is the problem ?

I can not understand the order which the function "scans" the image.

What i want is to get only the columns of the image and locate the first column that has at list 1 non-transperant pixel. this way I will know how to crop the left, transparent side of the image?

How can I get the pixels by columns?

Thanks

Shani

Community
  • 1
  • 1
shannoga
  • 19,649
  • 20
  • 104
  • 169

2 Answers2

4

The bytes are ordered left-to-right, top-to-bottom. So to do what you want, I think you want to loop over the rawData like this:

int x = 0;
int y = 0;
BOOL found = NO;
for (x = 0; x < width; x++) {
    for (y = 0; y < height; y++) {
        unsigned char alphaByte = rawData[(y*bytesPerRow)+(x*bytesPerPixel)+3];
        if (alphaByte > 0) {
            found = YES;
            break;
        }
    }
    if (found) break;
}

NSLog(@"First non-transparent pixel at %i, %i", x, y);

Then your first column that contains a non-transparent pixel will be column x.

mattjgalloway
  • 34,792
  • 12
  • 100
  • 110
0

Normally one would iterate over the image array from top to bottom over rows, and within each row from left to right over the columns. In this case you want the reverse: we want to iterate over each column, beginning at the left, and within the column we go over all rows and check if a black pixel is present.

This will give you the left-most black pixel:

size_t maxIndex = height * bytesPerRow;
for (size_t x = 0; x < bytesPerRow; x += bytesPerPixel)
{        
    for (size_t index = x; index < maxIndex; index += bytesPerRow)
    {
        if (rawData[index + 3] > 0)
        {
            goto exitLoop;
        }
    }
}
exitLoop:

if (x < bytesPerRow)
{
    x /= bytesPerPixel;
    // left most column is `x`
}

Well, this is equal to mattjgalloway, just slightly optimized, and neater too :O

Although a goto is usually permitted to abandon two loops from within the inner loop, it's still ugly. Makes me really miss those nifty flow control statements D has...

The function you provided in the example code does something different though. It starts at a certain position in the image (defined by xx and yy), and goes over count pixels going from the starting position to the right, continuing to next rows. It adds those alpha values to some array I suspect.

When passed xx = yy = 0, this will find the top-most pixel with certain conditions, not the left-most. This transformation is given by the code above. Do remind that a 2D image is simply a 1D array in memory, starting with the top row from left to right and proceeding with the next rows. Doing simple math one can iterate over rows or over columns.

Taco de Wolff
  • 1,682
  • 3
  • 17
  • 34