Ah, endianness issue, isn't it fun! BitBlt really operates on 32-bit words, so 
4 pixels of your 8-bit form are stuffed into one word. And they are big-endian 
by default. You can indicate little-endian forms by using a negative depth. So, 
if you use -8 for your form depth it works.

You are (probably) on an x86 processor, which is little-endian, so your byte 
array's first byte ends up in the least significant byte of the first word. 
Interpreting that as a big-endian word gives the pattern you noticed.

I should have mentioned that stuffing a byte array into a form is a hack (there 
is even a method Form>>hackBits:). It is a useful hack, see for example 
Bitmap>>asByteArray. But by looking at that method you see you need to pay 
attention to your CPU's endianness:

        Smalltalk isLittleEndian
                ==> true

Your code could use this:

        Smalltalk isLittleEndian ifTrue: [form swapEndianness].

(or initialize its depth to 8 or -8 depending on endianness).

The "proper" way would be to use a "bitPoker", which is independent of 
endianness, but considerably slower:

        | w h bytes form poker |
        w := 200.
        h := 200.
        bytes := ((1 to: w*h) collect: [:i | 255 ]) asByteArray.
        1 to: w do: [ :x |
            1 to: h do: [ :y |
                x = y ifTrue: [ bytes at: (w*(y - 1) + x) put: 0 ]
            ]
        ].
        form := ColorForm extent: w@h depth: 8.
        form colors: ((0 to: 255) collect: [:i | Color gray: i / 255]).
        poker := BitBlt bitPokerToForm: form.
        0 to: w-1 do: [ :x |
            0 to: h-1 do: [ :y |
                poker pixelAt: x@y put: (bytes at: w * y + x + 1).
            ]
        ].
        form display

(Btw, don't put parens into "1 to: w do:". It works but defeats an important 
optimization).

- Bert -

On 12.06.2014, at 02:32, Sungjin Chun <chu...@castlesoft.co.kr> wrote:

> Thanks you for your answer, however there is something I missed here.
> 
> I've tried following code
> 
> | w h bytes form |
> w := 200.
> h := 200.
> bytes := ((1 to: w*h) collect: [:i | 255 ]) asByteArray.
> (1 to: w) do: [ :x |
>     (1 to: h) do: [ :y |
>         x = y ifTrue: [ bytes at: (w*(y - 1) + x) put: 0 ]
>     ]
> ].
> form := ColorForm extent: w@h depth: 8 bits: bytes.
> form colors: ((0 to: 255) collect: [:i | Color gray: i / 255]).
> form display
> 
> What I expected is diagonal line but the result is not. What's wrong with my 
> code?
> 
> Thank you in advance.
> 
> 
> 
> On Wed, Jun 11, 2014 at 7:41 PM, Bert Freudenberg <b...@freudenbergs.de> 
> wrote:
> On 11.06.2014, at 00:36, Sungjin Chun <chu...@castlesoft.co.kr> wrote:
> 
> > Hi,
> >
> > I want to draw gray scale bitmap using byte array which has pixel by pixel 
> > gray
> > scale value as byte like this;
> >
> > [0 0 0 0 0 0 0 0
> >  16 23 255 78 12 12 12 12
> > ...
> > ...] (8x4 for example)
> >
> > I can draw this using Pen class pixel by pixel manner but this is very slow 
> > and
> > I think there should be faster way of creating a Form using above byte 
> > array.
> 
> If the width is a multiple of 4, you can use the byte array directly as form 
> bits:
> 
> | w h bytes form |
> w := 100.
> h := 60.
> bytes := ((1 to: w*h) collect: [:i | 256 atRandom - 1]) asByteArray.
> form := ColorForm extent: w@h depth: 8 bits: bytes.
> form colors: ((0 to: 255) collect: [:i | Color gray: i / 255]).
> form display
> 
> This would be the best and fastest way. If the width is not a multiple of 4 
> then perhaps you can add the necessary padding when creating the byte array. 
> Otherwise, a very fast way is to use BitBlt to copy whole lines from the byte 
> array to the form.
> 
> But even creating a byte array with the right padding just using at:put: 
> would be a lot faster than using a Pen.
> 
> - Bert -

Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________
Beginners mailing list
Beginners@lists.squeakfoundation.org
http://lists.squeakfoundation.org/mailman/listinfo/beginners

Reply via email to