0

I am learning wxPython. My question is how create bit map. I have R, G, B values for each pixel but I don't know how create bit map from it. I tried use wx.BitmapFromBuffer, I don't understand how should I create this buffer. I went through each pixel and in linear way put in list R, G, B components, but it did not draw what I expected. Do you understand how the buffer should be constructed?.

I don't want draw each pixel on bitmap using wx.MemoryDC because it is too slow.

Thank you!

Edit: I use approach from wxPython demo - RawBitmapAccess.

    buf = numpy.empty((w,h,3), numpy.uint8)
    n = 29000
    for i in xrange(w):
        for j in xrange(h):
            r = int(n*255*field[j,i])
            if r > 253: 
                r = 253
            buf[i, j, 0] = int(r)
            buf[i, j, 1] = int(r)
            buf[i, j, 2] = int(b)
            #dc.SetPen(wx.Pen(wx.Colour(r,r,b)))
            #dc.DrawPoint(i,j)
    bmp = wx.BitmapFromBuffer(w, h, buf)
    gc = wx.GraphicsContext.Create(dc)
    gc.DrawBitmap(bmp, 0, 0, w, h)

If I uncomment my old way of drawing (two commented lines in the loop) then I got what I want - one fuzzy ball. If I don't uncomment them that I have odd picture - it is splitted vertically for several fragments, each have it own fuzzy ball, plus it look like that there is vertical lines of missed pixels. I use buffer in the same way as in demo program. Why I get weird picture?

Edit2: I figure out it. I should swap i and j in the loop.

0

1 Answer 1

3

As I posted in my previous answer, this is done using numpy, and there's an example in the demo call RawBitmapAccess. The code basically looks like,

def MakeBitmap2(self, red, green, blue, alpha=128):
    # Make an array of bytes that is DIM*DIM in size, with enough
    # slots for each pixel to have a RGB and A value
    #arr = makeByteArray( (DIM,DIM, 4) )
    arr = numpy.empty((DIM,DIM, 4), numpy.uint8)

    # just some indexes to keep track of which byte is which
    R, G, B, A = range(4)

    # initialize all pixel values to the values passed in
    arr[:,:,R] = red
    arr[:,:,G] = green
    arr[:,:,B] = blue
    arr[:,:,A] = alpha

    # Set the alpha for the border pixels to be fully opaque
    arr[0,     0:DIM, A] = wx.ALPHA_OPAQUE  # first row
    arr[DIM-1, 0:DIM, A] = wx.ALPHA_OPAQUE  # last row
    arr[0:DIM, 0,     A] = wx.ALPHA_OPAQUE  # first col
    arr[0:DIM, DIM-1, A] = wx.ALPHA_OPAQUE  # last col

    # finally, use the array to create a bitmap
    bmp = wx.BitmapFromBufferRGBA(DIM, DIM, arr)
    return bmp
Sign up to request clarification or add additional context in comments.

4 Comments

Yes, as you see, it's flipping the (i, j) order.
Keep in mind that although setting the pixels in the array individually is a good place to start, and you'll get some speed gain by not drawing the pixels individually, you'll get additional speed gain if you 'vectorize' the loop. That is, write this using numpy operations so you don't have the do the nested loops over the indices.
could you give quick example of 'vectorize' loop
Be 'vectorize' I mean use numpy funcs to work on whole arrays, rather than set them element by element. For an easy example, if G is your array, to add 1, just say G+1, or G+=1; which will add one to every element of the array and is much fast than, say [G[i,j]+=1 for i in range(w) for j in range(h)]. Numpy can take time to learn though (depending on what you need to do) since you need to be familiar with numpy functions, and learn to think in this way, so it may not be worth the effort if you don't need the additional speed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.