def parsed(self): content = StringIO.StringIO(self.content) make_map = { 1001: Parse.array_dynamic(model=CARRenditionSlice), 1003: Parse.array_dynamic(model=CARRenditionMetric), 1004: Parse.model(CARRenditionComposition), 1005: Parse.model(CARRenditionUTI), 1006: Parse.model(CARRenditionBitmapInfo), 1007: Parse.model(CARRenditionBytesPerRow), 1010: Parse.model(CARRenditionReference), } content_make = make_map.get(self.magic) return content_make(self, content) if content_make else None
class CARRendition(Model): RESIZE_MODE_FIXED = "Fixed Size" RESIZE_MODE_TILE = "Tile" RESIZE_MODE_SCALE = "Scale" RESIZE_MODE_HUNIFORM_VSCALE = "Horizontal Uniform; Vertical Scale" RESIZE_MODE_HSCALE_VUNIFORM = "Horizontal Scale; Vertical Uniform" @classmethod def make_from_buffer(cls, buffer, **kwargs): stream = StringIO.StringIO(buffer) return cls.make(stream, **kwargs) fields = [ ('magic', Parse.fixed("<4s")), ('version', Parse.fixed("<I")), ('flags', Parse.model(CARRenditionFlag)), ('width', Parse.fixed("<I")), ('height', Parse.fixed("<I")), ('scale_factor', Parse.fixed("<I")), ('pixel_format', Parse.fixed("<4s")), ('color_space_id', Parse.fixed("<B")), ('reserved', Parse.fixed("<3s")), ('modification_date', Parse.fixed("<I")), ('layout_raw', Parse.fixed("<H")), ('reserved', Parse.fixed("<H")), ('name', Parse.terminated("\x00", fixed=128)), ('info_len', Parse.fixed("<I")), ('bitmap_count', Parse.fixed("<I")), ('reserved', Parse.fixed("<I")), ('payload_size', Parse.fixed("<I")), ('info', Parse.array_fixed(model=CARRenditionInfo, size='info_len')), ('content', Parse.dynamic("payload_size")), ] @cached_property def raw(self): if len(self.content): return CARRenditionRaw.make_from_buffer(self.content) @cached_property def layout(self): return CAR_RENDITION_LAYOUT_BY_ID.get(self.layout_raw, "unknown") @cached_property def is_resizable(self): return 25 >= self.layout_raw >= 20 and len(self.slices) > 1 @cached_property def slices(self): return filter(lambda x: x.parsed is CARRenditionSlice, self.info) @cached_property def resize_mode(self): mode_map = { "one_part_tile": CARRendition.RESIZE_MODE_TILE, "three_part_horizontal_tile": CARRendition.RESIZE_MODE_TILE, "three_part_vertical_tile": CARRendition.RESIZE_MODE_TILE, "nine_part_tile": CARRendition.RESIZE_MODE_TILE, "one_part_scale": CARRendition.RESIZE_MODE_SCALE, "three_part_horizontal_scale": CARRendition.RESIZE_MODE_SCALE, "three_part_vertical_scale": CARRendition.RESIZE_MODE_SCALE, "nine_part_scale": CARRendition.RESIZE_MODE_SCALE, "nine_part_horizontal_uniform_vertical_scale": CARRendition.RESIZE_MODE_HUNIFORM_VSCALE, "nine_part_horizontal_uniform_vertical_scale": CARRendition.RESIZE_MODE_HSCALE_VUNIFORM, } return mode_map.get(self.layout, CARRendition.RESIZE_MODE_FIXED) def dump(self): print "Rendition: %s" % self.name print "Width: %d" % self.width print "Height: %d" % self.height print "Scale: %f" % (self.scale_factor / 100.0) print "Layout: %s" % self.layout_raw print "Resizable: %d" % self.is_resizable print "Payload size: %d" % self.payload_size if self.is_resizable: for i, slice in enumerate(self.slices): print "Slice %d: (%u, %u) %u x %u" % \ (i, slice.x, slice.y, slice.width, slice.height) print "Resize mode: %s" % self.resize_mode print "Attributes:" for attribute, value in self.attributes.iteritems(): print "[%.2d] %s = %s" % \ (attribute.identifier_raw, attribute.identifier, value) print ""