UnityPack icon indicating copy to clipboard operation
UnityPack copied to clipboard

Support for ETC_RGB4?

Open mcorner opened this issue 8 years ago • 6 comments

Traceback (most recent call last):
  File "/usr/local/bin/unityextract", line 146, in <module>
    main()
  File "/usr/local/bin/unityextract", line 143, in main
    exit(app.run())
  File "/usr/local/bin/unityextract", line 56, in run
    self.handle_asset(asset)
  File "/usr/local/bin/unityextract", line 127, in handle_asset
    image = d.image
  File "/usr/local/lib/python3.5/site-packages/unitypack/engine/texture.py", line 151, in image
    raise NotImplementedError("Unimplemented format %r" % (self.format))
NotImplementedError: Unimplemented format <TextureFormat.ETC_RGB4: 34>

mcorner avatar Dec 02 '16 17:12 mcorner

An ETC decoder needs to be added to Pillow for this.

jleclanche avatar Dec 04 '16 12:12 jleclanche

Python and Unity are both completely new to me, but perhaps you could bundle a decoder:

http://pillow.readthedocs.io/en/latest/handbook/writing-your-own-file-decoder.html

using this tool: http://malideveloper.arm.com/resources/tools/mali-gpu-texture-compression-tool/

and this gist: https://gist.github.com/yin8086/6ce83c5d8e4cf1ac9879

as reference?

WedgeTalon avatar Jan 05 '17 22:01 WedgeTalon

Thanks. ill take a look.

Edit: Uh, that's no good. It's subprocessing the texture to a separate executable...

jleclanche avatar Jan 05 '17 22:01 jleclanche

Drat, I didn't catch that.

WedgeTalon avatar Jan 06 '17 00:01 WedgeTalon

Hi !

And what about that : https://github.com/hglm/texgenpack ?

It is C code but maybe something is possible ?

KevinHru avatar Apr 08 '17 13:04 KevinHru

There is a python library supporting unpacking ETC (and other) images if you are open to using another besides Pillow. Specifically, tex2img. Though I saw in PR #52 that someone may be trying to add Pillow support.

In any case, here's some code using it to unpack ETC and ETC2 images that unityextract doesn't support if anyone finds it useful. I modified unityextract to save as a pickle the image when the format was unsupported first.

# Line 134 of unityextract
				try:
					image = d.image
				except NotImplementedError as e:
					print("WARNING: Texture format not implemented. Skipping %r." % (filename),e)
					print('\tWriting Data Directly')
					python_data = pickle.dumps(d._obj)
					self.write_to_file(d.name + ".pickle", python_data, mode="wb")
					continue

The decompression code:

Show Code
#!/usr/bin/python3

import pickle,enum
with open('ETC_Image.pickle','rb') as f:
	data = pickle.load(f)
	
#print(data.keys()) odict_keys(['m_Name', 'm_Width', 'm_Height', 'm_CompleteImageSize', 'm_TextureFormat', 'm_MipCount', 'm_IsReadable', 'm_ReadAllowed', 'm_ImageCount', 'm_TextureDimension', 'm_TextureSettings', 'm_LightmapFormat', 'm_ColorSpace', 'image data', 'm_StreamData'])

from enum import IntEnum
class TextureFormat(IntEnum):
	# From UnityPack
	
	Alpha8 = 1
	ARGB4444 = 2
	RGB24 = 3
	RGBA32 = 4
	ARGB32 = 5
	RGB565 = 7

	# Direct3D
	DXT1 = 10
	DXT5 = 12

	RGBA4444 = 13
	BGRA32 = 14

	BC6H = 24
	BC7 = 25

	DXT1Crunched = 28
	DXT5Crunched = 29

	# PowerVR
	PVRTC_RGB2 = PVRTC_2BPP_RGB = 30
	PVRTC_RGBA2 = PVRTC_2BPP_RGBA = 31
	PVRTC_RGB4 = PVRTC_4BPP_RGB = 32
	PVRTC_RGBA4 = PVRTC_4BPP_RGBA = 33

	# Ericsson (Android)
	ETC_RGB4 = 34
	ATC_RGB4 = 35
	ATC_RGBA8 = 36

	# Adobe ATF
	ATF_RGB_DXT1 = 38
	ATF_RGBA_JPG = 39
	ATF_RGB_JPG = 40

	# Ericsson
	EAC_R = 41
	EAC_R_SIGNED = 42
	EAC_RG = 43
	EAC_RG_SIGNED = 44
	ETC2_RGB = 45
	ETC2_RGBA1 = 46
	ETC2_RGBA8 = 47

	# OpenGL / GLES
	ASTC_RGB_4x4 = 48
	ASTC_RGB_5x5 = 49
	ASTC_RGB_6x6 = 50
	ASTC_RGB_8x8 = 51
	ASTC_RGB_10x10 = 52
	ASTC_RGB_12x12 = 53
	ASTC_RGBA_4x4 = 54
	ASTC_RGBA_5x5 = 55
	ASTC_RGBA_6x6 = 56
	ASTC_RGBA_8x8 = 57
	ASTC_RGBA_10x10 = 58
	ASTC_RGBA_12x12 = 59

	@property
	def pixel_format(self):
		if self == TextureFormat.RGB24:
			return "RGB"
		elif self == TextureFormat.ARGB32:
			return "ARGB"
		elif self == TextureFormat.RGB565:
			return "RGB;16"
		elif self == TextureFormat.Alpha8:
			return "A"
		elif self == TextureFormat.RGBA4444:
			return "RGBA;4B"
		elif self == TextureFormat.ARGB4444:
			return "RGBA;4B"
		return "RGBA"
	
for k in data.keys():
	if k in ('image data',):#, 'm_StreamData'): 
		print(k,len(data[k]))
	else:
		print(k,data[k])
tf = TextureFormat(data['m_TextureFormat'])
print(tf)

from tex2img import *

# Formats
ETC1_RGB_NO_MIPMAPS = 0
ETC2PACKAGE_RGB_NO_MIPMAPS = 1
ETC2PACKAGE_RGBA_NO_MIPMAPS_OLD = 2
ETC2PACKAGE_RGBA_NO_MIPMAPS = 3
ETC2PACKAGE_RGBA1_NO_MIPMAPS = 4
ETC2PACKAGE_R_NO_MIPMAPS = 5
ETC2PACKAGE_RG_NO_MIPMAPS = 6
ETC2PACKAGE_R_SIGNED_NO_MIPMAPS = 7
ETC2PACKAGE_RG_SIGNED_NO_MIPMAPS = 8
ETC2PACKAGE_sRGB_NO_MIPMAPS = 9
ETC2PACKAGE_sRGBA_NO_MIPMAPS = 10
ETC2PACKAGE_sRGBA1_NO_MIPMAPS = 11
# TODO: SRGB Check

ex_unpack = {
	TextureFormat.ETC_RGB4 : lambda data,w,h : decompress_etc(data,w,h,ETC1_RGB_NO_MIPMAPS)
	TextureFormat.ETC2_RGB : lambda data,w,h : decompress_etc(data,w,h,ETC2PACKAGE_RGB_NO_MIPMAPS)
	TextureFormat.ETC2_RGBA1 : lambda data,w,h : decompress_etc(data,w,h,ETC2PACKAGE_RGBA1_NO_MIPMAPS)
	TextureFormat.ETC2_RGBA8 : lambda data,w,h : decompress_etc(data,w,h,ETC2PACKAGE_RGBA_NO_MIPMAPS)
}
from PIL import Image

if tf in ex_unpack:
	img_data,w,h = data['image data'],data['m_Width'],data['m_Height']
	name = data['m_Name']
	image_data = ex_unpack[tf](img_data,w,h)
	image = Image.frombytes('RGBA', (w,h), image_data, 'raw')
	
	image.save(open(name+'.png','wb'), format="png")

SirNate0 avatar Sep 16 '21 14:09 SirNate0