def from_raw(self, data, width, height, x_offset=0, y_offset=0, pal=None): """Load a raw 8-bpp image, converting to the Doom picture format (used by all graphics except flats)""" pal = pal or palette.default trans = chr(pal.tran_index) # First pass: extract pixel data in column+post format columns_in = [data[n:width*height:width] for n in range(width)] columns_out = [] for column in columns_in: # Split into chunks of continuous non-transparent pixels postdata = filter(None, column.split(trans)) # Find the y position where each chunk starts start_rows = [] in_trans = True for y in range(height): if column[y] == trans: in_trans = True elif in_trans: start_rows.append(y) in_trans = False columns_out.append(zip(start_rows, postdata)) # Second pass: compile column+post data, adding pointers data = [] columnptrs = [] pointer = 4*width + 8 for column in columns_out: columnptrs.append(util.pack('l', pointer)) for row, pixels in column: data.append("%c%c\x00%s\x00" % (row, len(pixels), pixels)) pointer += 4 + len(pixels) data.append('\xff') pointer += 1 # Merge everything together self.data = ''.join([util.pack('4h', width, height, x_offset, y_offset), ''.join(columnptrs), ''.join(data)])
def from_raw(self, data, width, height, x_offset=0, y_offset=0, pal=None): """Load a raw 8-bpp image, converting to the Doom picture format (used by all graphics except flats)""" pal = pal or palette.default trans = chr(pal.tran_index) # First pass: extract pixel data in column+post format columns_in = [data[n:width * height:width] for n in range(width)] columns_out = [] for column in columns_in: # Split into chunks of continuous non-transparent pixels postdata = filter(None, column.split(trans)) # Find the y position where each chunk starts start_rows = [] in_trans = True for y in range(height): if column[y] == trans: in_trans = True elif in_trans: start_rows.append(y) in_trans = False columns_out.append(zip(start_rows, postdata)) # Second pass: compile column+post data, adding pointers data = [] columnptrs = [] pointer = 4 * width + 8 for column in columns_out: columnptrs.append(util.pack('l', pointer)) for row, pixels in column: data.append("%c%c\x00%s\x00" % (row, len(pixels), pixels)) pointer += 4 + len(pixels) data.append('\xff') pointer += 1 # Merge everything together self.data = ''.join([ util.pack('4h', width, height, x_offset, y_offset), ''.join(columnptrs), ''.join(data) ])
def from_Image(self, im, translate=False): """Load from a PIL Image instance If the input image is 24-bit, the colors will be looked up in the current palette. If the input image is 8-bit, indices will simply be copied from the input image. To properly translate colors between palettes, set the `translate` parameter.""" pixels = im.tostring() width, height = im.size # High resolution graphics not supported yet, so truncate height = min(254, height) xoff, yoff = (width // 2)-1, height-5 if im.mode == "RGB": pixels = "".join([chr(self.palette.match(util.unpack('<BBB', \ pixels[i*3:(i+1)*3]))) for i in range(width*height)]) elif im.mode == 'P': srcpal = im.palette.tostring() if translate: R = [ord(c) for c in srcpal[0::3]] G = [ord(c) for c in srcpal[1::3]] B = [ord(c) for c in srcpal[2::3]] # Work around PIL bug: "RGB" loads as "BGR" from bmps (?) if util.filename[-4:].lower() == '.bmp': srcpal = zip(B, G, R) else: srcpal = zip(R, G, B) lexicon = [chr(self.palette.match(c)) for c in srcpal] pixels = "".join([lexicon[ord(b)] for b in pixels]) else: # Simply copy pixels. However, make sure to translate # all colors matching the transparency color to the # right index. This is necessary because programs # aren't consistent in choice of position for the # transparent entry. packed_color = util.pack("BBB", *util.pal.tran_color) ri = 0 while ri != -1: ri = srcpal.find(packed_color, ri+3) if not ri % 3 and ri//3 != self.palette.tran_index: pixels = pixels.replace(chr(ri//3), chr(self.palette.tran_index)) else: raise TypeError, "image mode must be 'P' or 'RGB'" self.from_raw(pixels, width, height, xoff, yoff, self.palette)
def from_Image(self, im, translate=False): """Load from a PIL Image instance If the input image is 24-bit, the colors will be looked up in the current palette. If the input image is 8-bit, indices will simply be copied from the input image. To properly translate colors between palettes, set the `translate` parameter.""" pixels = im.tostring() width, height = im.size # High resolution graphics not supported yet, so truncate height = min(254, height) xoff, yoff = (width // 2) - 1, height - 5 if im.mode == "RGB": pixels = "".join([chr(self.palette.match(util.unpack('<BBB', \ pixels[i*3:(i+1)*3]))) for i in range(width*height)]) elif im.mode == 'P': srcpal = im.palette.tostring() if translate: R = [ord(c) for c in srcpal[0::3]] G = [ord(c) for c in srcpal[1::3]] B = [ord(c) for c in srcpal[2::3]] # Work around PIL bug: "RGB" loads as "BGR" from bmps (?) if util.filename[-4:].lower() == '.bmp': srcpal = zip(B, G, R) else: srcpal = zip(R, G, B) lexicon = [chr(self.palette.match(c)) for c in srcpal] pixels = "".join([lexicon[ord(b)] for b in pixels]) else: # Simply copy pixels. However, make sure to translate # all colors matching the transparency color to the # right index. This is necessary because programs # aren't consistent in choice of position for the # transparent entry. packed_color = util.pack("BBB", *util.pal.tran_color) ri = 0 while ri != -1: ri = srcpal.find(packed_color, ri + 3) if not ri % 3 and ri // 3 != self.palette.tran_index: pixels = pixels.replace(chr(ri // 3), chr(self.palette.tran_index)) else: raise TypeError, "image mode must be 'P' or 'RGB'" self.from_raw(pixels, width, height, xoff, yoff, self.palette)
def set_offsets(self, xy): """Set the (x, y) offsets of the graphic.""" self.data = self.data[0:4] + util.pack('hh', *xy) + self.data[8:]