2011年4月13日水曜日

PIL で bin2png - その 2

昔? telnet しか許されていないホストで base64 したバイナリをコピペしたこと
思い出した...鶏卵、ブートストラップ。ソレやるか? で昨日の
> 超てきとーいいかげんにパディング
を貼り付けた結果、ながいブログエントリぃー。pack / unpack の使い方もわかっ
てないし、ムダな事ばっかじゃん。と思った方は是非メンテしてやってください。
コピペして bin2png.py とかで保存した後は、こちらも昨日のイメージを保存して
$ ./bin2png.py -d patch-2.6.38.2.gz.png -o patch-2.6.38.2.gz
とかで。
サイズ大きいファイルはシャレになりませんが、ブログに貼り付ける程度なら...
#!/usr/bin/python

import sys, os, math, struct
import getopt, logging
import Image

log = logging.getLogger()

def sqrint(n):
    r = math.ceil(math.sqrt(n) + 0.1)
    return (int(r), int(math.pow(r, 2) - n))


def encode(srcfp, dstfp):
    # calc sizes
    fsize = os.fstat(srcfp.fileno()).st_size
    log.debug("encode size: %d" % fsize)
    qfsize = fsize / 4
    sides, padlen = sqrint(qfsize)
    tupad = struct.unpack('BBBB', struct.pack('!L', fsize))

    # create data
    data = [tupad]
    for i in range(qfsize):
        data.append(struct.unpack('BBBB', srcfp.read(4)))
    nremain = fsize % 4
    data.append(struct.unpack('BBBB', srcfp.read(nremain) + '\x00' * (4 - nremain)))
    data.extend(((0, 0, 0, 0),) * (padlen / 4 - 1))

    # write out
    im = Image.new('RGBA', (sides, sides))
    im.putdata(data)
    im.save(dstfp, 'PNG')


def decode(srcfp, dstfp):
    im = Image.open(srcfp)
    imgcore = im.getdata() # needs checking mode?
    fsize = struct.unpack("!L", struct.pack("BBBB", *imgcore[0]))[0]
    log.debug("decode size: %d" % fsize)

    data = list(imgcore)[1:]
    b = bytearray()
    [b.extend(d) for d in data]
    dstfp.write(b[:fsize])


def usage():
    print >> sys.stderr, '''%s - convert file to png image
  -e | --encode          specify encoding file 
  -d | --decode          specify decoding file
  -o | --outfile         stdout if not specified
  -h | --help            show (this) usage message
  -v | --verbose         set logging level to DEBUG [default is INFO]
''' % sys.argv[0]

def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'e:d:o:hv',
                                   ['encode', 'decode', 'outfile', 
                                    'help', 'verbose'])
    except getopt.GetoptError, err:
        log.error(err)
        usage()
        sys.exit(2)

    isencode = False
    isdecode = False
    srcfp = None
    # 3.0: dstfp = sys.stdout.buffer?
    dstfp = os.fdopen(sys.stdout.fileno(), 'wb')

    for o, a in opts:
        if o in ("-h", "--help"):
            usage()
            sys.exit(0)
        elif o in ("-v", "--verbose"):
            log.setLevel(logging.DEBUG)
        elif o in ("-e", "--encode"):
            isencode = True
            srcfp = file(a, 'rb')
        elif o in ("-d", "--decode"):
            isdecode = True
            srcfp = file(a, 'rb')
        elif o in ("-o", "--outfile"):
            dstfp = file(a, 'wb')

    if not (isencode ^ isdecode):
        log.error("invalid action")
        usage()
        sys.exit(1)

    isencode and encode(srcfp, dstfp)
    isdecode and decode(srcfp, dstfp)


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(levelname)s %(message)s')
    main()

0 件のコメント: