def image(self): from PIL import Image from decrunch import File as CrunchFile if self.format not in IMPLEMENTED_FORMATS: raise NotImplementedError("Unimplemented format %r" % (self.format)) if self.format in (TextureFormat.DXT1, TextureFormat.DXT1Crunched): codec = "bcn" args = (1, ) elif self.format in (TextureFormat.DXT5, TextureFormat.DXT5Crunched): codec = "bcn" args = (3, ) else: codec = "raw" args = (self.format.pixel_format, ) mode = "RGB" if self.format.pixel_format in ("RGB", "RGB;16") else "RGBA" size = (self.width, self.height) data = self.image_data if self.format in (TextureFormat.DXT1Crunched, TextureFormat.DXT5Crunched): data = CrunchFile(self.image_data).decode_level(0) # Pillow wants bytes, not bytearrays data = bytes(data) if not data and size == (0, 0): return None return Image.frombytes(mode, size, data, codec, args)
def image(self): from PIL import Image from decrunch import File as CrunchFile import etcpack # needs to be imported once in the active code, so that the codec can register itself if self.format not in IMPLEMENTED_FORMATS: raise NotImplementedError("Unimplemented format %r" % (self.format)) if self.format in (TextureFormat.DXT1, TextureFormat.DXT1Crunched): codec = "bcn" args = (1, ) elif self.format in (TextureFormat.DXT5, TextureFormat.DXT5Crunched): codec = "bcn" args = (3, ) elif self.format == TextureFormat.BC7: codec = "bcn" args = (7, ) elif self.format in (TextureFormat.ETC2_RGB, ): # ETC2PACKAGE_RGB_NO_MIPMAPS codec = "etc2" args = (1, ) elif self.format in (TextureFormat.ETC2_RGBA1, ): # ETC2PACKAGE_RGBA1_NO_MIPMAPS codec = "etc2" args = (4, ) elif self.format in (TextureFormat.ETC2_RGBA8, ): # ETC2PACKAGE_RGBA_NO_MIPMAPS codec = "etc2" args = (3, ) else: codec = "raw" args = (self.format.pixel_format, ) mode = "RGB" if self.format.pixel_format in ("RGB", "RGB;16") else "RGBA" size = (self.width, self.height) data = self.image_data if self.format in (TextureFormat.DXT1Crunched, TextureFormat.DXT5Crunched): data = CrunchFile(self.image_data).decode_level(0) # Pillow wants bytes, not bytearrays data = bytes(data) if not data and size == (0, 0): return None return Image.frombytes(mode, size, data, codec, args)
def image(self): from PIL import Image from decrunch import File as CrunchFile if self.format not in IMPLEMENTED_FORMATS: raise NotImplementedError("Unimplemented format %r" % (self.format)) if self.format in (TextureFormat.DXT1, TextureFormat.DXT1Crunched): codec = "bcn" args = (1, ) elif self.format in (TextureFormat.DXT5, TextureFormat.DXT5Crunched): codec = "bcn" args = (3, ) elif self.format == TextureFormat.BC7: codec = "bcn" args = (7, ) elif self.format in (TextureFormat.ETC_RGB4, TextureFormat.ETC2_RGB, TextureFormat.ETC2_RGBA1, TextureFormat.ETC2_RGBA8): codec = "etc2" args = ( self.format, self.format.pixel_format, ) else: codec = "raw" args = (self.format.pixel_format, ) mode = "RGB" if self.format.pixel_format in ("RGB", "RGB;16") else "RGBA" size = (self.width, self.height) data = self.image_data if self.format in (TextureFormat.DXT1Crunched, TextureFormat.DXT5Crunched): data = CrunchFile(self.image_data).decode_level(0) if self.format in TextureFormat.ASTC_FORMATS(): block_sz = self.format.astc_block_size data = decompress_astc(data, self.width, self.height, block_sz, block_sz, False) # Pillow wants bytes, not bytearrays data = bytes(data) if not data and size == (0, 0): return None return Image.frombytes(mode, size, data, codec, args)
def get_image_from_texture2d(texture_2d, flip=True) -> Image: # init variables mode = "RGBA" codec = "raw" args = ("RGBA",) swap = [] # for 4444 types to fix their channels image_data = texture_2d.image_data texture_format = texture_2d.m_TextureFormat platform = texture_2d.platform # INT8 if texture_format == TextureFormat.Alpha8: args = ('A',) elif texture_format == TextureFormat.R8: mode = 'RGB' args = ('R',) elif texture_format == TextureFormat.RG16: image_data_size = len(image_data) rgba32 = bytearray(image_data_size * 2) for i in range(0, image_data_size, 2): rgba32[i * 2 + 1] = image_data[i + 1] # G rgba32[i * 2 + 0] = image_data[i] # R rgba32[i * 2 + 3] = 255 # A image_data = bytes(rgba32) if texture_format == TextureFormat.ARGB4444: args = ('RGBA;4B',) swap = [2, 1, 0, 3] elif texture_format == TextureFormat.RGB24: mode = 'RGB' args = ('RGB',) elif texture_format == TextureFormat.RGBA32: args = ('RGBA',) elif texture_format == TextureFormat.ARGB32: args = ('ARGB',) elif texture_format == TextureFormat.RGBA4444: args = ('RGBA;4B',) swap = [3, 2, 1, 0] elif texture_format == TextureFormat.BGRA32: args = ('BGRA',) # INT16 elif texture_format == TextureFormat.R16: mode = 'RGB' args = ('R;16',) # rgba32 = bytearray(image_data_size * 2) # for i in range(0, image_data_size, 2): # f = Half.ToHalf(image_data, i) # rgba32[i * 2 + 0] = (math.ceil(f * 255))%256 # R # rgba32[i * 2 + 3] = 255 # A # image_data = bytes(rgba32) elif texture_format == TextureFormat.RGB565: # test passed mode = 'RGB' args = ('BGR;16',) image_data = swap_bytes_for_xbox(image_data, platform) # FLOAT elif texture_format == TextureFormat.RFloat: mode = 'RGB' args = ('RF',) elif texture_format == TextureFormat.RGBAFloat: mode = 'RGBA' args = ('RGBAF',) # BCN elif texture_format in [ # test passed TextureFormat.DXT1, TextureFormat.DXT1Crunched ]: args = (1,) codec = 'bcn' image_data = swap_bytes_for_xbox(image_data, platform) elif texture_format in [ # test passed TextureFormat.DXT5, TextureFormat.DXT5Crunched ]: args = (3,) codec = 'bcn' image_data = swap_bytes_for_xbox(image_data, platform) elif texture_format == TextureFormat.BC4: args = (4,) codec = 'bcn' mode = 'L' elif texture_format == TextureFormat.BC5: args = (5,) codec = 'bcn' elif texture_format == TextureFormat.BC6H: args = (6,) codec = 'bcn' elif texture_format == TextureFormat.BC7: args = (7,) codec = 'bcn' # ETC elif texture_format in [ # test passed TextureFormat.ETC_RGB4Crunched, TextureFormat.ETC_RGB4_3DS, TextureFormat.ETC_RGB4 ]: args = (0,) codec = 'etc2' mode = 'RGB' elif texture_format == TextureFormat.ETC2_RGB: # test passed args = (1,) codec = 'etc2' mode = 'RGB' elif texture_format == TextureFormat.ETC2_RGBA1: args = (4,) codec = 'etc2' elif texture_format in [ # test passed TextureFormat.ETC2_RGBA8Crunched, TextureFormat.ETC_RGBA8_3DS, TextureFormat.ETC2_RGBA8 ]: args = (3,) codec = 'etc2' # PVRTC elif texture_format == TextureFormat.PVRTC_RGB2: args = (0,) codec = 'pvrtc' mode = 'RGBA' elif texture_format == TextureFormat.PVRTC_RGBA2: args = (0,) codec = 'pvrtc' mode = 'RGBA' elif texture_format == TextureFormat.PVRTC_RGB4: # test passed args = (0,) codec = 'pvrtc' mode = 'RGBA' elif texture_format == TextureFormat.PVRTC_RGBA4: args = (0,) codec = 'pvrtc' mode = 'RGBA' # ASTC elif texture_format in [ TextureFormat.ASTC_RGB_4x4, # test pass TextureFormat.ASTC_RGBA_4x4, # test pass ]: codec = 'astc' args = (4, 4) elif texture_format in [ TextureFormat.ASTC_RGB_5x5, # test pass TextureFormat.ASTC_RGBA_5x5, # test pass ]: codec = 'astc' args = (5, 5) elif texture_format in [ TextureFormat.ASTC_RGB_6x6, # test pass TextureFormat.ASTC_RGBA_6x6, # test pass ]: codec = 'astc' args = (6, 6) elif texture_format in [ TextureFormat.ASTC_RGB_8x8, # test pass TextureFormat.ASTC_RGBA_8x8, # test pass ]: codec = 'astc' args = (8, 8) elif texture_format in [ TextureFormat.ASTC_RGB_10x10, # test pass TextureFormat.ASTC_RGBA_10x10, # test pass ]: codec = 'astc' args = (10, 10) elif texture_format in [ TextureFormat.ASTC_RGB_12x12, # test pass TextureFormat.ASTC_RGBA_12x12, # test pass ]: codec = 'astc' args = (12, 12) if not image_data: raise EOFError("No Image Data") # return Image.new('RGBA') if 'Crunched' in texture_format.name: # if (version[0] > 2017 or (version[0] == 2017 and version[1] >= 3) #2017.3 and up # or m_TextureFormat == TextureFormat.ETC_RGB4Crunched # or m_TextureFormat == TextureFormat.ETC2_RGBA8Crunched): # # Unity Crunch # image_data = bytes(CrunchFile_U(image_data).decode_level(0)) # image_data_size = len(image_data) # else: #normal crunch # decrunch is using a modified crunch which uses the original crunch and only uses the Unity Version for etc1/2 image_data = bytes(CrunchFile(image_data).decode_level(0)) img = Image.frombytes(mode, (texture_2d.m_Width, texture_2d.m_Height), image_data, codec, args) if swap: channels = img.split() img = Image.merge(mode, [channels[x] for x in swap]) if img and flip: return img.transpose(Image.FLIP_TOP_BOTTOM) return img
def image(self): # cached ? image = getattr(self, '_image', False) if image: return image # implemented? if self.format not in IMPLEMENTED_FORMATS: #use external tools to extract image if sys.platform != 'win32': print('Unimplemented image type.') return None try: self._image = processUnimplementedTexture2D(self) return self._image except NotImplementedError: raise NotImplementedError("Unimplemented format %r" % (self.format)) except Exception as e: print('Error during external extraction\n%s' % e) return None # extraction of implemented image from PIL import Image mode = "RGB" if self.format.pixel_format in ("RGB", "RGB16") else "RGBA" size = (self.width, self.height) data = self.image_data # Pillow wants bytes, not bytearrays from decrunch import File as CrunchFile if self.format in (TextureFormat.DXT1Crunched, TextureFormat.DXT5Crunched, TextureFormat.ETC_RGB4Crunched, TextureFormat.ETC2_RGBA8Crunched): data = CrunchFile(data).decode_level(0) data = bytes(data) if not data or size == (0, 0): return None # Image from bytes if self.format in (TextureFormat.DXT1, TextureFormat.DXT1Crunched): codec = "bcn" args = (1, ) elif self.format in (TextureFormat.DXT5, TextureFormat.DXT5Crunched): codec = "bcn" args = (3, ) elif self.format == TextureFormat.BC7: codec = "bcn" args = (7, ) elif self.format in (TextureFormat.ETC_RGB4, TextureFormat.ETC2_RGB, TextureFormat.ETC2_RGBA1, TextureFormat.ETC2_RGBA8, TextureFormat.ETC2_RGBA8Crunched): codec = "etc2" args = ( self.format, self.format.pixel_format, ) else: codec = "raw" args = (self.format.pixel_format, ) image = Image.frombytes(mode, size, data, codec, args) # Apply Fix ~ 1. flip image, 2. secondary format fix channels = ImageOps.flip(image).split() if self.format in [ TextureFormat.RGB565, # 7 TextureFormat.RGBA4444 # 13 ]: channels = tuple(reversed(channels)) elif self.format in [TextureFormat.ARGB4444 # 2 ]: channels = (channels[2], channels[1], channels[0], channels[3]) if len(channels) == 3: self._image = Image.merge("RGB", channels) else: self._image = Image.merge("RGBA", channels) return self._image
def image(self): from PIL import Image from decrunch import File as CrunchFile import hashlib, os, struct if self.format not in IMPLEMENTED_FORMATS: raise NotImplementedError("Unimplemented format %r" % (self.format)) if self.format in PKM_HEADERS: version = b'20' if self.format == TextureFormat.ETC_RGB4: version = b'10' t = PKM_HEADERS[self.format] header = struct.pack('!4s2sbbHHHH', b'PKM ', version, 0, t, self.width, self.height, self.width, self.height) image_data = header + self.image_data sha1 = hashlib.sha1(image_data).hexdigest() infile = "%s/image_data_%s.pkm" % (tempfile.gettempdir(), sha1) outfile = "%s/image_data_%s.png" % (tempfile.gettempdir(), sha1) open(infile, "wb+").write(image_data) subprocess.run( ["etcpack", infile, tempfile.gettempdir(), "-ext", "PNG"], stdout=subprocess.PIPE) im = Image.open(outfile) im.transpose(Image.FLIP_TOP_BOTTOM) os.remove(infile) os.remove(outfile) return im if self.format in (TextureFormat.DXT1, TextureFormat.DXT1Crunched): codec = "bcn" args = (1, ) elif self.format in (TextureFormat.DXT5, TextureFormat.DXT5Crunched): codec = "bcn" args = (3, ) elif self.format == TextureFormat.BC7: codec = "bcn" args = (7, ) else: codec = "raw" args = (self.format.pixel_format, ) mode = "RGB" if self.format.pixel_format in ("RGB", "RGB;16") else "RGBA" size = (self.width, self.height) data = self.image_data if self.format in (TextureFormat.DXT1Crunched, TextureFormat.DXT5Crunched): data = CrunchFile(self.image_data).decode_level(0) data = bytes(data) if not data and size == (0, 0): return None img = Image.frombytes(mode, size, data, codec, args) if self.format == TextureFormat.RGBA4444: a, b, g, r = img.split() img = Image.merge("RGBA", (r, g, b, a)) return img