Library images are stored in the /System/Library/Images/<platform>/
directory on the SD Card, where <platform>
is the lowercase shortname of the platform the images have been created for.
A single asset's CRC32 (lowercase only) directly becomes the image filename: 02468ace.bin
If multiple assets are used, all assets' binary files shall be concatenated in alphabetical order and the CRC32 of the entire resulting blob is taken, as above.
If multiple assets are contained within subfolders, all assets' binary files shall be concatenated in alphabetical order within each directory, starting in the deepest subfolder and recursively traversing the folder structure alphabetically outwards.
Folder/B/Sample/1.bin+2.bin+
Folder/B/3.bin+4.bin+
Folder/D/C/5.bin+6.bin+
Folder/D/7.bin+8.bin+
Folder/9.bin
Note that simply using a previous CRC32's as the starting value for the next block can be used instead of concatenating all files. Both methods give the same result, as long as the same order is followed.
Library images have an 8 byte header:
32 bit (Little Endian) format: 0x41504910
= RGB 16 bit or 0x41504920
= RGB 32 bit
16 bit (Little Endian) image width in pixels
16 bit (Little Endian) image height in pixels
Library images contain the RGB pixel data (rotated by 90 degrees anti-clockwise) after the header:
Not currently used
BGRA (Big Endian) 1 pixel byte order: 0xBB
, 0xGG
, 0xRR
, 0xAA
Set the Alpha color channel of each pixel to 0xFF/255
so the image is fully opaque
(8 bit color channels: B = Blue, G = Green, R = Red, A = Alpha)
import sys
import struct
import PIL
from PIL import Image, ImageOps
from pathlib import Path
def main(argv=None):
print("Image Converter v1.0")
if len(sys.argv) == 2: # Print Error If Not Enough Arguments Given
print("Error: Output file not specified")
print("Usage: image_converter [image_in] [file_out]")
print("Supported images: BLP, BMP, DDS, DIB, EPS, GIF, ICNS, ICO, IM, JPEG, JPEG 2000,")
print(" MSP, PCX, PNG, PPM, SGI, SPIDER, TGA, TIFF, WebP and XBM")
sys.exit()
if len(sys.argv) >= 4: # Print Error If Too Many Arguments Given
print("Error: Too many arguments specified")
print("Usage: image_converter [image_in] [file_out]")
print("Supported images: BLP, BMP, DDS, DIB, EPS, GIF, ICNS, ICO, IM, JPEG, JPEG 2000,")
print(" MSP, PCX, PNG, PPM, SGI, SPIDER, TGA, TIFF, WebP and XBM")
sys.exit()
if len(sys.argv) == 1: # Print Usage If No Arguments Given
print("Usage: image_converter [image_in] [file_out]")
print("Supported images: BLP, BMP, DDS, DIB, EPS, GIF, ICNS, ICO, IM, JPEG, JPEG 2000,")
print(" MSP, PCX, PNG, PPM, SGI, SPIDER, TGA, TIFF, WebP and XBM")
else: # Convert Image
if argv is None: argv = sys.argv[1:]
infilename, outfilename = argv
in_file = Path(infilename)
if in_file.is_file(): # Input File Exists
in_img = PIL.Image.open(infilename)
out_img = open(outfilename, 'wb')
width, height = in_img.size
bpp = 4
print("Image: Name =", infilename)
print("Image: BPP =", bpp*8)
print("Image: Width =", width)
print("Image: Height =", height)
print("Saving Image...")
# PASS 1: Convert Image To RGBA
rgb_img = in_img.convert("RGBA")
#rgb_img.show()
# PASS 2: Rotate Image 90 Degrees Anti-Clockwise
out = rgb_img.rotate(90, expand=True)
#out.show()
# PASS 3: Convert Image Data To 32-bit $BGRA Binary Data
pixels = out.getdata()
image = []
image.append(bpp*8) # Header Magic (32-bit)
image.append(0x49)
image.append(0x50)
image.append(0x41)
image.append(width&0xFF) # Header Width (16-bit)
image.append((width>>8)&0xFF)
image.append(height&0xFF) # Header Height (16-bit)
image.append((height>>8)&0xFF)
for i in range(width*height):
image.append(pixels[i][2]) # Blue Byte
image.append(pixels[i][1]) # Green Byte
image.append(pixels[i][0]) # Red Byte
image.append(pixels[i][3]) # Alpha Byte
for i in range((width*height*bpp)+8): out_img.write(struct.pack('B', image[i])) # Write Header + Pixels
out_img.close()
print("Done")
else: # Input File Does Not Exist
print("Error: Couldn't open the file", infilename, "for input")
print("Usage: image_converter [image_in] [file_out]")
print("Supported images: BLP, BMP, DDS, DIB, EPS, GIF, ICNS, ICO, IM, JPEG, JPEG 2000,")
print(" MSP, PCX, PNG, PPM, SGI, SPIDER, TGA, TIFF, WebP and XBM")
if __name__ == '__main__':
main()