Great! But I'm not entirely sure about the erroneous results I was seeing.
I would think that erroneously assuming 3 bytes per pixel when there are
really 4 would result in color distortion, not a repetition of pixels. Nor
do I understand why saving/loading as a file fixed it, nor why the .png
output is still borked (though .jpg comes out fine).

On Mon, Dec 17, 2012 at 1:01 PM, Adam Bark <[email protected]> wrote:

>  On 17/12/12 10:41, Brian Will wrote:
>
> 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())
>
>  Ah ok, I solved it. As the documentation states "*Note:* You can make no
> assumptions about the return type; usually it will be ImageData or
> CompressedImageData, but patterns are free to return any subclass of
> AbstractImage." Therefore you must interrogate the returned image for it's
> format and pitch ie. on my system:
> >>> print image.pitch, image.format
> ... 2000 RGBA
>
> --
> You received this message because you are subscribed to the Google Groups
> "pyglet-users" group.
> 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.
>

-- 
You received this message because you are subscribed to the Google Groups 
"pyglet-users" group.
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