แปลง Jpeg เป็น BMP16 ด้วย Python

update จาก post ก่อน (link)

ก่อนหน้านี้เคยเขียนโปรแกรมแปลงไฟล์แบบเดียวกันนี้โดยใช้ SciPy (scipy.org) คราวนี้ลองใช้ Pillow (pillow.readthedocs.io) พบว่า code ง่ายกว่านิดนึง

#!/usr/bin/python3
from PIL import Image
import struct
import os.path

def RGB(r,g,b):
    return  (((r&0xF8)<<8)|((g&0xFC)<<3)|((b&0xF8)>>3)) #5 red | 6 green | 5 blue

def RGBfromArray(pixel):
    return RGB(pixel[0],pixel[1],pixel[2])

def genBMP16header(width,height):
    id = bytes("BM",'UTF-8')
    size = 70 + width*height*2
    dummy1 = 0
    dummp2 = 0
    bitmapOffset = 70
    sizeofDIB = 56
    bitmapWidth = width
    bitmapHeight = -1*height
    colorPlane = 1
    colorDepth = 16 # 16 bit / pixel
    compression = 3 # BI_Bitfields 
    sizeofBitmapArray = width*height*2
    h_resolution = 3780 # 96DPI
    v_resolution = 3780 
    colorPalette = 0
    importantColors = 0
    redbitmask = 0x0000F800
    greenbitmask = 0x000007E0
    bluebitmask = 0x0000001F
    alphabitmask = 0
    header = struct.pack('<2sLHHLLLlHHLLLLLLLLLL',id,size,dummy1,dummp2,bitmapOffset, \
                   sizeofDIB,bitmapWidth,bitmapHeight,colorPlane,colorDepth,compression, \
                   sizeofBitmapArray,h_resolution,v_resolution,colorPalette,importantColors, \
                   redbitmask,greenbitmask,bluebitmask,alphabitmask)
    return header

def convertFile(infile):
    outfile = infile+'.bmp'
    with open(outfile, 'bw') as f:      # then use shell command 'xxd file' to see hex dump
        image = Image.open(infile)
        header = genBMP16header(image.width,image.height)
        f.write(header)
        for y in range(image.height): # y row index
            for x in range(image.width):  # x col index
                r,g,b = image.getpixel((x,y))
                color = RGB(r,g,b)
                hiByte = (color & 0xFF00) >> 8
                loByte = color & 0x00FF
                f.write(bytes([loByte,hiByte])) 

files = ["hatsune_miku_girl_cute_posture_look_25061_320x240.jpg",
        "headphones_camera_retro_122094_320x240.jpg",
        "rose_flower_red_151238_320x240.jpg",
        "rose_stones_fragments_139704_320x240.jpg"]

if __name__ == '__main__':
    for file in files:
        if os.path.isfile(file):
            print('converting...{}'.format(file))
            convertFile(file)
        else:
            print('skipping...{}'.format(file))