For pedagogical purposes, I'm trying to set up a simple drawing canvas on 
which to draw and display a single image with control of the individual 
pixels. Efficiency is no concern. To this end, I have a MutableImage class 
with getPixel and setPixel methods. Everything seems to work fine, except 
when blitting the generated image, pixels from columns on the left side for 
some reason also get displayed in columns about 2/3 to the right, e.g. in a 
500 pixel wide image, the content of columns 0-100 gets erroneously drawn 
also in columns ~300-400 (overwriting whatever should be in those columns). 
My hack around this is to save my generated image to file, then load it 
again with pyglet.image.load. When I then blit my generated image newly 
loaded from the file, it displays properly. So if my data is getting saved 
properly, does this mean there's a bug in blitting images after set_data?

p.s. I also get strange behavior in the saved .png. The generated image 
displays correctly in my window, but the saved file doesn't match, almost 
like a whole color channel is missing. Seems like *something* is screwy 
with the channels.

Here's my code:

import pyglet
    
class MutableImage(object):
    FORMAT = 'RGB'
    
    def __init__(self, image):
        self.image = image
        self.imageData = image.get_data(MutableImage.FORMAT, image.width * 
len(MutableImage.FORMAT))
        self.dataList = list(self.imageData)
    
    def getPixel(self, x, y):
        '''Returns tuple of (r, g, b)'''
        pixelIdx = x + (y * self.image.width)
        byteIdx = pixelIdx * len(MutableImage.FORMAT)
        return (
            ord(self.dataList[byteIdx]),
            ord(self.dataList[byteIdx + 1]),
            ord(self.dataList[byteIdx + 2])
        )
        
    def setPixel(self, x, y, color):
        ''' color is tuple of (R, G, B) as integers 0-255 '''
        # ignore requests to draw out of bounds
        if self.inBounds(x, y):
            pixelIdx = x + (y * self.image.width)
            byteIdx = pixelIdx * len(MutableImage.FORMAT)
            r, g, b = color
            self.dataList[byteIdx] = chr(r)
            self.dataList[byteIdx + 1] = chr(g)
            self.dataList[byteIdx + 2] = chr(b)
        
    def getImage(self):
        ''' return the current state of data '''
        data = ''.join(self.dataList)
        self.image.set_data(MutableImage.FORMAT, self.image.width * 
len(MutableImage.FORMAT), data)
        
        # without hack of saving as file then loading as file, a fraction 
of left side
        # gets redrawn on right side for no apparent reason when we blit 
the image
        self.image.save('hack-around.png')
        return pyglet.image.load('hack-around.png')
    
    def inBounds(self, x, y):
        if x < self.image.width and y < self.image.height:
            return True
        return False
        
    def clamp(self, x, y):
        if x >= self.image.width:
            x = self.image.width - 1
        if y >= self.image.height:
            y = self.image.height - 1
        return (x, y)
    
    def paintRectangle(self, lowerLeftCorner, upperRightCorner, color):
        ''' coords in (x, y) tuple  '''
        x1, y1 = lowerLeftCorner
        x2, y2 = upperRightCorner
        x1, y1 = self.clamp(x1, y1)
        x2, y2 = self.clamp(x2, y2)
        for x in range(x1, x2 + 1):
            for y in range(y1, y2 + 1):
                self.setPixel(x, y, color)
                
    def copyRegion(self, src, dest, width, height):
        ''' src and dest (x, y) tuples of lower left corner of regions '''
        pass
        
    def paintImage(self, dest, srcImage):
        ''' dest specifies lower left corner where to draw the srcImage '''
        mutableSrcImage = MutableImage(srcImage)
        destX, destY = dest
        for x in range(srcImage.width):
            for y in range(srcImage.height):
                color = mutableSrcImage.getPixel(x, y)
                self.setPixel(x + destX, y + destY, color)
    

def displayWindow(image):
    window = pyglet.window.Window(image.width, image.height, caption='image 
render')
    
    @window.event
    def on_draw():
        image.blit(0, 0)
       
    pyglet.app.run()



mi = MutableImage(pyglet.image.create(500, 900))
 
mi.paintRectangle((100, 0), (500, 900), (0, 255, 0))

for x in range(50, 500):
    mi.setPixel(x, 850, (255, 0, 0))
for x in range(50, 500):
    mi.setPixel(x, 450, (255, 0, 0))
for x in range(50, 500):
    mi.setPixel(x, 250, (255, 0, 0))    
mi.paintRectangle((0, 0), (100, 100), (0, 255, 255))
mi.paintRectangle((450, 850), (500, 900), (0, 255, 255))

displayWindow(mi.getImage())

-- 
You received this message because you are subscribed to the Google Groups 
"pyglet-users" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/pyglet-users/-/0V7JLZ6iAuYJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/pyglet-users?hl=en.

Reply via email to