FROM : Steve Christensen
DATE : Sun May 25 17:14:38 2008
On May 25, 2008, at 4:34 AM, Graham Cox wrote:
> On 25 May 2008, at 5:13 pm, Jens Alfke wrote:
>
>>> Is there any faster way of doing this than just iterating over
>>> the pixels like this? I can't think of anything but someone might
>>> have a bright idea.
>>
>> If you do test against pixels, work with the raw pixmap instead of
>> making an Obj-C call to get every pixel. Get the pointer to its
>> pixel data, and use the rowbytes and the pixel size to iterate
>> over pixels. If the pixmap is always in a known format, it's
>> pretty easy. (Sounds like it's 8-bit grayscale, which is as easy
>> as it gets, with one byte per pixel.)
>
> Yep, this is a good idea (and also thanks to Ken who suggested the
> same thing). I see a ~10x speed-up doing this:
>
> NSBitmapImageRep* bits = [self pathBitmapInRect:ir];
>
> // if any pixels in this bitmap are set, we have a hit.
> // fast method tests 4 pixels at a time in the raw data:
>
> unsigned dataLength = ([bits bytesPerRow] * [bits pixelsHigh])
> >> 2;
> unsigned* data = (unsigned*)[bits bitmapData];
> unsigned k = 0;
>
> // scan until we hit a non-white value or reach the end
>
> while(( k < dataLength ) && ( data[k++] == 0xFFFFFFFF ));
>
> hit = ( k < dataLength );
Unless you know for a fact that your bitmap data is packed such that
each row begins immediately after the previous row, you'll need to do
a bit more work. Bitmaps can be created with [bits bytesPerRow] >
bytesPerPixel * [bits pixelsWide]. In that case you could have some
uninitialized bytes between the end of one row and the beginning of
the next, which could affect the outcome of your test.
steve
DATE : Sun May 25 17:14:38 2008
On May 25, 2008, at 4:34 AM, Graham Cox wrote:
> On 25 May 2008, at 5:13 pm, Jens Alfke wrote:
>
>>> Is there any faster way of doing this than just iterating over
>>> the pixels like this? I can't think of anything but someone might
>>> have a bright idea.
>>
>> If you do test against pixels, work with the raw pixmap instead of
>> making an Obj-C call to get every pixel. Get the pointer to its
>> pixel data, and use the rowbytes and the pixel size to iterate
>> over pixels. If the pixmap is always in a known format, it's
>> pretty easy. (Sounds like it's 8-bit grayscale, which is as easy
>> as it gets, with one byte per pixel.)
>
> Yep, this is a good idea (and also thanks to Ken who suggested the
> same thing). I see a ~10x speed-up doing this:
>
> NSBitmapImageRep* bits = [self pathBitmapInRect:ir];
>
> // if any pixels in this bitmap are set, we have a hit.
> // fast method tests 4 pixels at a time in the raw data:
>
> unsigned dataLength = ([bits bytesPerRow] * [bits pixelsHigh])
> >> 2;
> unsigned* data = (unsigned*)[bits bitmapData];
> unsigned k = 0;
>
> // scan until we hit a non-white value or reach the end
>
> while(( k < dataLength ) && ( data[k++] == 0xFFFFFFFF ));
>
> hit = ( k < dataLength );
Unless you know for a fact that your bitmap data is packed such that
each row begins immediately after the previous row, you'll need to do
a bit more work. Bitmaps can be created with [bits bytesPerRow] >
bytesPerPixel * [bits pixelsWide]. In that case you could have some
uninitialized bytes between the end of one row and the beginning of
the next, which could affect the outcome of your test.
steve
| Related mails | Author | Date |
|---|---|---|
| Graham Cox | May 25, 07:55 | |
| Ken Thomases | May 25, 08:10 | |
| Jens Alfke | May 25, 09:13 | |
| Graham Cox | May 25, 13:34 | |
| Steve Christensen | May 25, 17:14 | |
| Gary L. Wade | May 25, 18:52 | |
| Jens Alfke | May 25, 18:58 | |
| Ken Ferry | May 26, 01:44 | |
| Graham Cox | May 26, 12:43 |






Cocoa mail archive

