Re: Back to getting pixel RGBColor values from a pixmap



In article <reinder-B5427E.23153817122005@xxxxxxxxxxxxxxx>,
Reinder Verlinde <reinder@xxxxxxxxxxxxxxxx> wrote:

> In article <43a47287$0$95967$742ec2ed@xxxxxxxxxxxxxx>,
> Don Bruder <dakidd@xxxxxxxxx> wrote:
>
> > Here's how I'm getting a pixel at the moment:
> >
> > Note: This routine was designed, tested, and intended *ONLY* for use
> > with 32-bit direct color PixMaps as implemented for MacOS 9.1/Carbon.
> > [...]
> > RGBColor getpixel(GWorldPtr Source, int H, int V)
>
> If you want this function to be fast, it probably is better to pass a
> RGBColor * to this function. Otherwise, the compiler may copy the
> RGBColor to return it.
>
> > {
> > PixMapHandle ThePixMapHandle = GetGWorldPixMap(Source);
> > Ptr BaseAddress = GetPixBaseAddr(ThePixMapHandle);
> > long RowBytes = GetPixRowBytes(ThePixMapHandle);
> > long Index = 0L;
>
> Are you sure you need 'Index'? I can't see where you use it.

Ahhh... Another "leftover" I missed - At one point, I was doing the
"which set of bytes should I be looking at" calculation one step at a
time so I could breakpoint through it and be able to see what was what
at any given instant without needing to beg or bribe the debugger into
showing it to me.

>
> > PixelStruct ThePixel = {0, 0, 0, 0};
> > PixelStruct *PixelPtr = &ThePixel;
> > RGBColor ThePixelColor = {0, 0, 0};
> > Rect Bounds = {0,0,0,0};
>
> Is it me, or did you forget to initialize 'Bounds'?

????
There *SHOULD* be a "GetPortBounds(Source, &Bounds);" line in there...
<checks "live" source> Yep, the posted version is missing that line, but
the "production" version has it. I must have "dropped" it when I was
hand-wrapping the comments and otherwise "pretty-izing" the code prior
to posting so that it wouldn't come out the other end of the posting
process looking like it'd been run through a wood chipper.

>
> > Locker(Source); // My conditional version of LockPixels()
> > // Sanity-check the H/V values against Source's bounds Rect.
> > // (Things get *REALLY* hairy if we trying playing outside it)
> > if ((Bounds.left <= H) && (H <= Bounds.right) &&
> > (Bounds.top <= V) && (V <= Bounds.bottom))
> > {
> > // H/V OK. "Fold" them into a linear index into the array of
> > // 4 byte RGBColor values and use that to point to the desired
> > // pixel's raw RGB value in the array.
> > PixelPtr = (PixelStruct *)BaseAddress +
> > (V * RowBytes) +
> > (H * sizeof(PixelStruct));
> > }
>
> 1. This probably does not matter in your case, but in general, you can
> not be sure that Bounds.left and Bounds.top both are zero. For example,
> you can have a 16x16 pixel GWorld with topleft at {30000,-20000}.

You're correct that it doesn't matter for me. I'm (at least currently)
using this code exclusively with 640x480 GWorlds that have their origin
at 0,0, even though as coded (intentionally so), it's easily possible to
pass it a different sized GWorld, or one with its origin someplace other
than 0,0. For my purposes, that's a non-issue, since the only way
something like that is going to happen is if I screw up and somehow
mangle a GWorld before passing it in.

> 2. How large is an int on your system/compiler combination? If it is 2
> bytes, that calculation could easily overflow, returning a PixelPtr that
> points before the BaseAddress.

True. It isn't biting me in this incarnation (probably because I'm
working with GWorlds that are always 640x480 - Although I think I recall
setting up ints to be 4 bytes, as well) but with bigger ones, it could
easily be a problem. Changing H/V to longs instead of ints should cope
with that nicely, regardless of what the int size setting is. Nice
catch! :)

> 3. This code may be correct, but I would write an extra pair of
> parentheses:
> PixelPtr = (PixelStruct *)(BaseAddress +
> (V * RowBytes) +
> (H * sizeof(PixelStruct)));
> because I either:
> - am too lazy to remember C operator precedence order
> - rather spend my time on things that matter
> - just prefer writing solid code

Or the fourth option you neglected to mention:
- Like me, you're so anal when you code that you habitually keep a roll
of toilet paper within arm's reach - "Just in case" :)

I often go "overkill" mode on paren use if there's even the slightest
doubt in my mind about ops precedence, but for some reason, this
instance escaped the usual treatment. I'll fix that immediately now that
you've brought it to my attention. :)

> Things may get bad when you keep a pixmap locked across a WaitNextEvent
> call, because locking the pixels may prevent the system from moving them
> around to make room for memory allocated by another application.

Hmmm... That might have only limted relevance for me then, since if this
thing turns out as I envision, it'll likely be the only thing running
(other than the OS) on a machine that would otherwise be sitting in the
closet collecting dust.

> For what you are doing, you can safely do the whole
> LockPixels/GetBaseAddress thing once, then iterate over all pixels, then
> unlock the thing and call WaitNextEvent.

That routine currently gets called from a routine that is in turn
called from my Timer event handler (I'm using the CarbonEvents event
model) - Still safe in that situation? If so, I could fairly easily move
the "setup" work to the calling routine, lock/get what I need once, then
call it as needed, unlocking only when I'm getting ready to exit the
handler.

> Given the requirements of your application, it might even be that you
> can just as well keep the thing locked the whole time (chances are you
> won't be running much else, anyway)

Well, at the moment, I'm wanting to run it on an older, otherwise
"unloved" rig I'm currently using to keep the closet floor from floating
away. :) It'll end up being pretty much a single-task system, if things
end up the way I plan.

> > Is there a better way? Seems like there has to be, since programs like
> > Photoshop manage it, and at a much higher speed.
>
> How do you know Photoshop uses GWorlds?

I don't, but Photoshop uses something that's at least *SOMEWHAT* like a
GWorld and produces results that would be no different than mine for the
same operation - assuming mine were working properly... Ergo, it has to
be using something that bears at least some functional resemblance to a
GWorld, even if it's working directly in an on-screen window's PixMap or
some sort of custom internal image format.

--
Don Bruder - dakidd@xxxxxxxxx - If your "From:" address isn't on my whitelist,
or the subject of the message doesn't contain the exact text "PopperAndShadow"
somewhere, any message sent to this address will go in the garbage without my
ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info
.



Relevant Pages

  • Re: Back to getting pixel RGBColor values from a pixmap
    ... > RGBColor getpixel(GWorldPtr Source, int H, int V) ... RGBColor * to this function. ... you can have a 16x16 pixel GWorld with topleft at. ... > Getting the handle to the pixmap, ...
    (comp.sys.mac.programmer.help)
  • Re: dilation
    ... one pixel off, and I had array index out of bound errors). ... int foreground = 255; ... //create binary image from the input image ... //foreground, i set it to foreground value and exit for cycle. ...
    (sci.image.processing)
  • Malloc code
    ... set up some data in a strucuture called GMM. ... struct GMM{ ... will be displayed starting at pixel. ... int SETWINEXTHORZ_MSB, ...
    (microsoft.public.vc.language)
  • Re: Problems with BufferedImage and ColorModel
    ... > I've been experimenting with BufferedImage and am attempting to extract the ... > individual R, G, B, and Alpha values from the color of each pixel in an image. ... > I pass that value to the getRedmethod of the ColorModel I get from ... is coded into the int value returned from getRGB. ...
    (comp.lang.java.help)
  • Re: 8 Bytes support in scroll functions
    ... But I didn't say to set it to 5GB; I said you should determine a divisor and appl;y the ... A scrollbar doesn't really ... get is 1 pixel, so on a 1024x768 display, a horizontal scrollbar can ... GetScrollPos and SetScrollRange takes int as input and return an int ...
    (microsoft.public.vc.mfc)