using color tables with forms and bitblt?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

using color tables with forms and bitblt?

LawsonEnglish
OK, I'm such a noob here, that I'm not quite sure how to ask my question...


I have a "dwell file" -an array of values generated by a Mandelbrot Set
application, one per pixel, with arbitrary values between 1 and
xxxxxxxxxxx (currently less than 2 billion, and right now far less than
1,000,000)- and I would like to use them, suitably tweaked, as indices
into a ColorMap. The ColorMap need not have 1,000,000 entries. No-one
can see that many color differences in a Mandelbrot set anyway.

I can generate an array of Color (ColorArray?) but I'm not sure how to
use them to create the ColorMap, and I'm not sure how to use the
ColorMap to speedily change what is drawn in the first place.

Right now, I'm creating a color dictionary and drawing via:


1 to: 800 do: [:y|
     1 to: 800 do: [:x| |i|
         i := x+ ((y-1) *800).  aForm colorAt: x@y put:( myDictColors
at:  (myArray at: i )).]
         ].


where myDictColors is a dictionary whose keys are the dwells listed in
the dwell array file and whose values are Color objects from my array of
colors.

Drawing the above takes about 1.5 seconds, which is a bit slow. I'd like
realtime-ish updating as I play with colors in the palette. Can this be
done, at least up to the 4096 color limit that BitBlt has for ColorMaps?

If so, how?  I've been trying to figure out the various classes and I'm
stumped.


Thanks





--
Squeak from the very start (introduction to Squeak and Pharo Smalltalk for the (almost) complete and compleate beginner).
https://www.youtube.com/playlist?list=PL6601A198DF14788D&feature=view_all


Reply | Threaded
Open this post in threaded view
|

Re: using color tables with forms and bitblt?

Bob Arning-2
You could try something like this:

test1
"
BobsColorTest new test1
"
    | target cmap1 inputData cmap2 nextPV cmap3 |
   
    inputData _ Form extent: 800@800 depth: 16.
    nextPV _ 1.
    0 to: 799 do: [ :x |
        0 to: 799 do: [ :y |
            inputData pixelValueAt: x@y put: (nextPV _ nextPV + 1) \\ 30000.
        ].
    ].
    cmap1 _  Bitmap new: 32768.
    1 to: cmap1 size do: [:i | cmap1 at: i put: i  \\ 1023 * 32 + 1].
    cmap2 _  Bitmap new: 32768.
    1 to: cmap2 size do: [:i | cmap2 at: i put: i - 1 \\ 32 + 1].
    cmap3 _  Bitmap new: 32768.
    1 to: cmap3 size do: [:i | cmap3 at: i put: i - 1].
               
    {cmap1. cmap2. cmap3} do: [ :map |
        target _ Form extent: inputData extent depth: inputData depth.
        (BitBlt current toForm: target)
            sourceForm: inputData;
            sourceOrigin: 0@0;
            combinationRule: Form paint;
            destX: 0 destY: 0 width: inputData width height: inputData height;
            colorMap: map;
            copyBits.
        target asMorph openInWorld.
    ].

Cheers,
Bob

On 8/3/12 7:30 PM, Lawson English wrote:
OK, I'm such a noob here, that I'm not quite sure how to ask my question...


I have a "dwell file" -an array of values generated by a Mandelbrot Set application, one per pixel, with arbitrary values between 1 and xxxxxxxxxxx (currently less than 2 billion, and right now far less than 1,000,000)- and I would like to use them, suitably tweaked, as indices into a ColorMap. The ColorMap need not have 1,000,000 entries. No-one can see that many color differences in a Mandelbrot set anyway.

I can generate an array of Color (ColorArray?) but I'm not sure how to use them to create the ColorMap, and I'm not sure how to use the ColorMap to speedily change what is drawn in the first place.

Right now, I'm creating a color dictionary and drawing via:


1 to: 800 do: [:y|
    1 to: 800 do: [:x| |i|
        i := x+ ((y-1) *800).  aForm colorAt: x@y put:( myDictColors at:  (myArray at: i )).]
        ].


where myDictColors is a dictionary whose keys are the dwells listed in the dwell array file and whose values are Color objects from my array of colors.

Drawing the above takes about 1.5 seconds, which is a bit slow. I'd like realtime-ish updating as I play with colors in the palette. Can this be done, at least up to the 4096 color limit that BitBlt has for ColorMaps?

If so, how?  I've been trying to figure out the various classes and I'm stumped.


Thanks








Reply | Threaded
Open this post in threaded view
|

Re: using color tables with forms and bitblt?

LawsonEnglish
Thanks, that works.

Though I think the usecase of the ability to swiftly switch palettes is of value, even in 32 bit forms.

form>>mapColor:to:  and mapColors:to should be able to use a full 32 bit color. The bitblt docs say that only 5 bits of the Color object's RGB values are used no matter the depth of the destination form. This is a serious limitation for anyone hoping to prototype/implement a modern image-oriented application.

Cairo no doubt changes this, but Cairo also violates the port anywhere paradigm that Squeak is based on, I think.

L




On 8/4/12 8:34 AM, Bob Arning wrote:
You could try something like this:

test1
"
BobsColorTest new test1
"
    | target cmap1 inputData cmap2 nextPV cmap3 |
   
    inputData _ Form extent: 800@800 depth: 16.
    nextPV _ 1.
    0 to: 799 do: [ :x |
        0 to: 799 do: [ :y |
            inputData pixelValueAt: x@y put: (nextPV _ nextPV + 1) \\ 30000.
        ].
    ].
    cmap1 _  Bitmap new: 32768.
    1 to: cmap1 size do: [:i | cmap1 at: i put: i  \\ 1023 * 32 + 1].
    cmap2 _  Bitmap new: 32768.
    1 to: cmap2 size do: [:i | cmap2 at: i put: i - 1 \\ 32 + 1].
    cmap3 _  Bitmap new: 32768.
    1 to: cmap3 size do: [:i | cmap3 at: i put: i - 1].
               
    {cmap1. cmap2. cmap3} do: [ :map |
        target _ Form extent: inputData extent depth: inputData depth.
        (BitBlt current toForm: target)
            sourceForm: inputData;
            sourceOrigin: 0@0;
            combinationRule: Form paint;
            destX: 0 destY: 0 width: inputData width height: inputData height;
            colorMap: map;
            copyBits.
        target asMorph openInWorld.
    ].

Cheers,
Bob

On 8/3/12 7:30 PM, Lawson English wrote:
OK, I'm such a noob here, that I'm not quite sure how to ask my question...


I have a "dwell file" -an array of values generated by a Mandelbrot Set application, one per pixel, with arbitrary values between 1 and xxxxxxxxxxx (currently less than 2 billion, and right now far less than 1,000,000)- and I would like to use them, suitably tweaked, as indices into a ColorMap. The ColorMap need not have 1,000,000 entries. No-one can see that many color differences in a Mandelbrot set anyway.

I can generate an array of Color (ColorArray?) but I'm not sure how to use them to create the ColorMap, and I'm not sure how to use the ColorMap to speedily change what is drawn in the first place.

Right now, I'm creating a color dictionary and drawing via:


1 to: 800 do: [:y|
    1 to: 800 do: [:x| |i|
        i := x+ ((y-1) *800).  aForm colorAt: x@y put:( myDictColors at:  (myArray at: i )).]
        ].


where myDictColors is a dictionary whose keys are the dwells listed in the dwell array file and whose values are Color objects from my array of colors.

Drawing the above takes about 1.5 seconds, which is a bit slow. I'd like realtime-ish updating as I play with colors in the palette. Can this be done, at least up to the 4096 color limit that BitBlt has for ColorMaps?

If so, how?  I've been trying to figure out the various classes and I'm stumped.


Thanks









    


-- 
Squeak from the very start (introduction to Squeak and Pharo Smalltalk for the (almost) complete and compleate beginner).
https://www.youtube.com/playlist?list=PL6601A198DF14788D&feature=view_all 


Reply | Threaded
Open this post in threaded view
|

Re: using color tables with forms and bitblt?

Bob Arning-2
Maybe the VM folks will see the value in adding this or maybe you could write a plugin. Barring that, this speeds things up quite a bit over the naive implementation:

test2
"
BobsColorTest new test2
"
    | target cmap1 inputData cmap2 nextPV cmap3 inputDataBits targetBits results t forceAlpha preAlloc |
   
    inputData _ Form extent: 800@800 depth: 32.
    nextPV _ 1.
    0 to: 799 do: [ :x |
        0 to: 799 do: [ :y |
            inputData pixelValueAt: x@y put: ((nextPV _ nextPV + 1) \\ 30000 bitAnd: 16rffffff).
        ].
    ].
    forceAlpha _ 16rff000000.
    cmap1 _  Bitmap new: 256*256*256.
    1 to: cmap1 size do: [:i | cmap1 at: i put:( i  \\ 65536 * 256 + 1 bitOr: forceAlpha)].
    cmap2 _  Bitmap new: 256*256*256.
    1 to: cmap2 size do: [:i | cmap2 at: i put: (i - 1 \\ 256 + 1 bitOr: forceAlpha)].
    cmap3 _  Bitmap new: 256*256*256.
    1 to: cmap3 size do: [:i | cmap3 at: i put: (i - 1 bitOr: forceAlpha)].
               
    preAlloc _ {cmap1. cmap2. cmap3} collect: [ :map |
        {map. Form extent: inputData extent depth: inputData depth}
    ].
    t _ [
        results _ preAlloc collect: [ :pair |
            target _ pair second.
            targetBits _ target bits.
            inputDataBits _ inputData bits.
            1 to: targetBits size do: [ :i |
                targetBits at: i put: (pair first at: (inputDataBits at: i) +1)
            ].
            target
        ].
    ] timeToRun.
    results do: [ :each |
        each  asMorph openInWorld.
    ].
    self inform: t asString,'ms to map ',results size asString,' times'.

Cheers,
Bob
On 8/5/12 2:43 AM, Lawson English wrote:
Thanks, that works.

Though I think the usecase of the ability to swiftly switch palettes is of value, even in 32 bit forms.

form>>mapColor:to:  and mapColors:to should be able to use a full 32 bit color. The bitblt docs say that only 5 bits of the Color object's RGB values are used no matter the depth of the destination form. This is a serious limitation for anyone hoping to prototype/implement a modern image-oriented application.

Cairo no doubt changes this, but Cairo also violates the port anywhere paradigm that Squeak is based on, I think.

L




On 8/4/12 8:34 AM, Bob Arning wrote:
You could try something like this:

test1
"
BobsColorTest new test1
"
    | target cmap1 inputData cmap2 nextPV cmap3 |
   
    inputData _ Form extent: 800@800 depth: 16.
    nextPV _ 1.
    0 to: 799 do: [ :x |
        0 to: 799 do: [ :y |
            inputData pixelValueAt: x@y put: (nextPV _ nextPV + 1) \\ 30000.
        ].
    ].
    cmap1 _  Bitmap new: 32768.
    1 to: cmap1 size do: [:i | cmap1 at: i put: i  \\ 1023 * 32 + 1].
    cmap2 _  Bitmap new: 32768.
    1 to: cmap2 size do: [:i | cmap2 at: i put: i - 1 \\ 32 + 1].
    cmap3 _  Bitmap new: 32768.
    1 to: cmap3 size do: [:i | cmap3 at: i put: i - 1].
               
    {cmap1. cmap2. cmap3} do: [ :map |
        target _ Form extent: inputData extent depth: inputData depth.
        (BitBlt current toForm: target)
            sourceForm: inputData;
            sourceOrigin: 0@0;
            combinationRule: Form paint;
            destX: 0 destY: 0 width: inputData width height: inputData height;
            colorMap: map;
            copyBits.
        target asMorph openInWorld.
    ].

Cheers,
Bob

On 8/3/12 7:30 PM, Lawson English wrote:
OK, I'm such a noob here, that I'm not quite sure how to ask my question...


I have a "dwell file" -an array of values generated by a Mandelbrot Set application, one per pixel, with arbitrary values between 1 and xxxxxxxxxxx (currently less than 2 billion, and right now far less than 1,000,000)- and I would like to use them, suitably tweaked, as indices into a ColorMap. The ColorMap need not have 1,000,000 entries. No-one can see that many color differences in a Mandelbrot set anyway.

I can generate an array of Color (ColorArray?) but I'm not sure how to use them to create the ColorMap, and I'm not sure how to use the ColorMap to speedily change what is drawn in the first place.

Right now, I'm creating a color dictionary and drawing via:


1 to: 800 do: [:y|
    1 to: 800 do: [:x| |i|
        i := x+ ((y-1) *800).  aForm colorAt: x@y put:( myDictColors at:  (myArray at: i )).]
        ].


where myDictColors is a dictionary whose keys are the dwells listed in the dwell array file and whose values are Color objects from my array of colors.

Drawing the above takes about 1.5 seconds, which is a bit slow. I'd like realtime-ish updating as I play with colors in the palette. Can this be done, at least up to the 4096 color limit that BitBlt has for ColorMaps?

If so, how?  I've been trying to figure out the various classes and I'm stumped.


Thanks










-- 
Squeak from the very start (introduction to Squeak and Pharo Smalltalk for the (almost) complete and compleate beginner).
https://www.youtube.com/playlist?list=PL6601A198DF14788D&feature=view_all 



    



Reply | Threaded
Open this post in threaded view
|

Re: using color tables with forms and bitblt?

LawsonEnglish



On 8/5/12 4:30 AM, Bob Arning wrote:
Maybe the VM folks will see the value in adding this or maybe you could write a plugin.
Actually, I've been looking at the BitBltPlugin.c source (it apparently isn't written in slang?) but...


you've saved me a lot of time (and saved me from my ADHD distraction) with this.

Thanks!

L

Barring that, this speeds things up quite a bit over the naive implementation:

test2
"
BobsColorTest new test2
"
    | target cmap1 inputData cmap2 nextPV cmap3 inputDataBits targetBits results t forceAlpha preAlloc |
   
    inputData _ Form extent: 800@800 depth: 32.
    nextPV _ 1.
    0 to: 799 do: [ :x |
        0 to: 799 do: [ :y |
            inputData pixelValueAt: x@y put: ((nextPV _ nextPV + 1) \\ 30000 bitAnd: 16rffffff).
        ].
    ].
    forceAlpha _ 16rff000000.
    cmap1 _  Bitmap new: 256*256*256.
    1 to: cmap1 size do: [:i | cmap1 at: i put:( i  \\ 65536 * 256 + 1 bitOr: forceAlpha)].
    cmap2 _  Bitmap new: 256*256*256.
    1 to: cmap2 size do: [:i | cmap2 at: i put: (i - 1 \\ 256 + 1 bitOr: forceAlpha)].
    cmap3 _  Bitmap new: 256*256*256.
    1 to: cmap3 size do: [:i | cmap3 at: i put: (i - 1 bitOr: forceAlpha)].
               
    preAlloc _ {cmap1. cmap2. cmap3} collect: [ :map |
        {map. Form extent: inputData extent depth: inputData depth}
    ].
    t _ [
        results _ preAlloc collect: [ :pair |
            target _ pair second.
            targetBits _ target bits.
            inputDataBits _ inputData bits.
            1 to: targetBits size do: [ :i |
                targetBits at: i put: (pair first at: (inputDataBits at: i) +1)
            ].
            target
        ].
    ] timeToRun.
    results do: [ :each |
        each  asMorph openInWorld.
    ].
    self inform: t asString,'ms to map ',results size asString,' times'.

Cheers,
Bob



-- Squeak from the very start (introduction to Squeak and Pharo Smalltalk for the (almost) complete and compleate beginner). https://www.youtube.com/playlist?list=PL6601A198DF14788D&feature=view_all


Reply | Threaded
Open this post in threaded view
|

Re: using color tables with forms and bitblt?

Bob Arning-2

On 8/5/12 9:08 AM, Lawson English wrote:
On 8/5/12 4:30 AM, Bob Arning wrote:
Maybe the VM folks will see the value in adding this or maybe you could write a plugin.
Actually, I've been looking at the BitBltPlugin.c source (it apparently isn't written in slang?) but...
Well, it certainly *was* ....

loadColorMap
    "ColorMap, if not nil, must be longWords, and
    2^N long, where N = sourceDepth for 1, 2, 4, 8 bits,
    or N = 9, 12, or 15 (3, 4, 5 bits per color) for 16 or 32 bits."
    | cmSize oldStyle oop cmOop |
    self inline: true.
    cmFlags _ cmMask _ cmBitsPerColor _ 0.
    cmShiftTable _ nil.
    cmMaskTable _ nil.
    cmLookupTable _ nil.
    cmOop _ interpreterProxy fetchPointer: BBColorMapIndex ofObject: bitBltOop.
    cmOop = interpreterProxy nilObject ifTrue:[^true].
    cmFlags _ ColorMapPresent. "even if identity or somesuch - may be cleared later"
    oldStyle _ false.
    (interpreterProxy isWords: cmOop) ifTrue:[
        "This is an old-style color map (indexed only, with implicit RGBA conversion)"
        cmSize _ interpreterProxy slotSizeOf: cmOop.
        cmLookupTable _ interpreterProxy firstIndexableField: cmOop.
        oldStyle _ true.
    ] ifFalse: [
        "A new-style color map (fully qualified)"
        ((interpreterProxy isPointers: cmOop)
...snip...

Can't think why that would change, but don't know how to verify these days.