Skip to content

Instantly share code, notes, and snippets.

@sfan5
Created January 6, 2014 10:13
Show Gist options
  • Save sfan5/8280735 to your computer and use it in GitHub Desktop.
Save sfan5/8280735 to your computer and use it in GitHub Desktop.
Tools to work with .cpbitmap files
#!/usr/bin/env python2
from PIL import Image
import sys
import struct
def r8(f):
return ord(f.read(1))
if len(sys.argv) <= 2:
print("Usage: %s <input> <output>" % sys.argv[0])
else:
f = open(sys.argv[1], "rb")
f.seek(-70, 2)
magic = f.read(8)
if magic != "bplist00":
print("Didn't find bplist header, are you sure this is a cpbitmap file?")
exit(1)
f.seek(42, 1)
dat = f.read(6)
width, height = struct.unpack("<HxxH", dat)
print("Size: %dx%d" % (width, height))
img = Image.new("RGBA", (width, height))
f.seek(0)
imgd = img.load()
for y in range(height):
for x in range(width):
b, g, r, a = r8(f), r8(f), r8(f), r8(f)
imgd[x, y] = (r, g, b, a)
f.close()
img.save(sys.argv[2])
#!/usr/bin/env python2
from PIL import Image
import sys
import struct
def w8(f, v):
f.write(chr(v))
if len(sys.argv) <= 2:
print("Usage: %s <input> <output>" % sys.argv[0])
else:
img = Image.open(sys.argv[1])
img = img.convert("RGBA")
f = open(sys.argv[2], "wb")
width, height = img.size
imgd = img.load()
for y in range(height):
for x in range(width):
r, g, b, a = imgd[x, y]
w8(f, b)
w8(f, g)
w8(f, r)
w8(f, a)
f.write("bplist00\x22\x40" + ("\x00" * 3) + "\x08" + ("\x00" * 6) + "\x01\x01" + ("\x00" * 7) + "\x01" + ("\x00" * 15)
+ "\x0d\x2e" + ("\x00" * 3) + struct.pack("<HccH", width, "\x00", "\x00", height) + "\x00\x00\x01" + ("\x00" * 3)
+ "\x01" + ("\x00" * 3) + "\x91\x32\xa4\xcb")
f.close()
@dymbox
Copy link

dymbox commented Oct 13, 2015

Needed to correct offsets to get it worked with iphone wallpapers, but eventually it works! )

cpbitmap2image.py:

13 f.seek(-74, 2)
18 f.seek(46, 1)

@sh00tg0a1
Copy link

For iOS 12. I changed the code like below.
The reason is on this thread of stack overflow and see the js version. https://stackoverflow.com/questions/7998324/dot-cpbitmap-images-imgaename-cpbitmap

from PIL import Image
import sys
import math
import struct

def r8(f):
    c = ord(f.read(1))
    return c

if len(sys.argv) <= 2:
    print("Usage: %s <input> <output>" % sys.argv[0])
else:
    f = open(sys.argv[1], "rb")
    f.seek(-78, 2)
    magic = f.read(8)
    print magic
    if magic != "bplist00":
        print("Didn't find bplist header, are you sure this is a cpbitmap file?")
        exit(1)
    f.seek(50, 1)
    dat = f.read(6)
    width, height = struct.unpack("<HxxH", dat)
    print("Size: %dx%d" % (width, height))
    img = Image.new("RGBA", (width, height))

    f.seek(0)
    imgd = img.load()

    # Take case of the line size
    line_size = int(math.ceil(width/16.0) * 16)
    print line_size
    for y in range(height):
        for x in range(width):
            b, g, r, a = r8(f), r8(f), r8(f), r8(f)
            imgd[x, y] = (r, g, b, a)
        f.seek((line_size - width)*4, 1)

    f.close()
    img.save(sys.argv[2])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment