การจัดการไฟล์ bitmap เพื่อแสดงผลบนจอ TFT
ซื้อจอ TFT แบบในรูปมา เพื่อจะใช้กับ Arduino โปรแกรมแรกที่ใช้กับจอนี้เป็น example ที่มากับ library ของ adafruit ก็ใช้งานได้ดี เห็นที่จอมีช่อง sd card อยู่ ก็เลยลองให้แสดงรูปใน sd card วนๆ ไปดู แก้ไขจากตัวอย่างโปรแกรมแสดงรูปที่อยู่ใน library ของ adafruit เช่นเดียวกัน ปรากฏว่าทำงานได้ แต่ช้ามากๆ โดยรูปที่จะเอาขึ้นจอต้องเป็นไฟล์ BMP ด้วย ค้นพบว่ารูปแบบการแสดงผลของจอเป็นแบบ 16 บิต คือ สีแดง 5 บิต สีเชียว 6 บิต สี น้ำเงิน 5 บิต
ถ้าจะให้แสดงผลเร็วขึ้นก็ต้องแปลงไฟล์ BMP แบบ 24 บิต เป็น 16 บิต ก่อน ซึ่งอ่านดูหลายที่เขาแนะให้ใช้ GIMP (GIMP.org) แปลงไฟล์ โดยเลือก save ไฟล์ เป็น BMP 16 บิต แต่เราก็ไม่อยากลง GIMP เพราะว่าไม่ได้ใช้งานมันทำอย่างอื่น นึกไปนึกมา python น่าจะทำได้นะ ก็เจอว่า SciPy มี function สำหรับอ่านไฟล์รูปภาพด้วย ถ้าอ่านไฟล์ได้ค่าสีของแต่ละ pixel ได้เราก็แปลงเป็น 16 บิต และ save ลงเป็นไฟล์ข้อมูลเฉยๆ ได้ แล้วเอาไปเขียนขึ้นจอตรงๆ เลย
Code แปลงค่าสี
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])
with open(outputfile, 'bw') as f: # then use shell command 'xxd file' to see hex dump
image= misc.imread(os.path.join(inputfile), flatten= 0)
for m in range(len(image)): # m row index
for n in range(len(image[0])): # n col index
color = RGBfromArray(image[m][n])
hiByte = (color & 0xFF00) >> 8
loByte = color & 0x00FF
f.write(bytes([loByte,hiByte]))
ผลก็คือทำงานได้เร็วกว่าไฟล์ BMP เดิมๆ มาก
คราวนี้พอได้ไฟล์ข้อมูล pixel ดิบๆ แล้ว อยากได้เป็น BMP แบบ 16 บิตล่ะ ก็เจอว่ามีโปรแกรมแปลงไฟล์ให้โหลดฟรีๆ ที่ https://www.displaymodule.com/pages/imageconverter เป็นบริษัทขายจอสำหรับ embedded system เลยลองแปลงไฟล์เพื่อที่จะแกะ header ของไฟล์ BMP ดู และเทียบกับไฟล์ BMP ที่ยังไม่ได้แปลงด้วย โดยอ้างอิงข้อมูลจาก https://en.wikipedia.org/wiki/BMP_file_format
ได้ข้อมูลแล้วก็เอาไปเขียนโปรแกรมเติม header ให้กับไฟล์ข้อมูล pixel ให้กลายเป็น BMP ซะ Code python สำหรับส่วนสร้าง header ก็ตามนี้
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