ในหัวข้อนี้เราจะพยายามปรับโค้ดของเราให้ยืดหยุ่น รองรับสองสถานการณ์นี้ครับ
กรณีแรก รูปสีแบบ RGB
อันนี้ค่อนข้างง่าย รูป RGB ก็จะมี offset เพิ่มขึ้นเป็น 3 เท่าของรูปเทา เนื่องจากมี 3 channels
เราก็จะใช้โค้ดประมาณนี้
#for grayscale offset = rr*(rowRead*oriW) #if RGB if img.mode=='RGB': offset = offset*3
กรณีที่สอง มีเศษเหลือของแถวจากการอ่าน
ตัวอย่างเช่น รูปมีทั้งสิ้น 7001 แถว (ความสูง) เราต้องการอ่านทีละ 128 พิกเซล
ก็จะต้องวนอ่านเท่ากับ 7001/128 = 54.69 หรือ 55 รอบ ซึ่งรอบสุดท้ายจะอ่านแค่ 7001%128 = 89 แถว
โค้ดที่ใช้ก็จะคือ
rowRead = 128 #keep original rowRead, used when there are extra last set of rows rowReadExtra = rowRead #size of original image oriW, oriH = img.size totalRead = oriH/rowRead #is oriH is divisible by rowRead? rowLeft = oriH%rowRead #if there are some rows left at the bottom, add one more row to process if rowLeft!=0: totalRead = totalRead+1
ลองดูตัวอย่างเต็มได้ตามโค้ดนี้ครับ ในที่นี้เราจะวนอ่านรูปสี RGB ขนาด 7076x7001 พิกเซลและบันทึกไว้เป็นไฟล์ใหม่ชื่อ output.tif ซึ่งเหมือนรูปตั้งต้นทุกประการ
from PIL import Image img = Image.open("mfu2009(chs. 1,2,3).tif") #create new output image out = Image.new(img.mode, img.size, None) #try to read every 128 rows rowRead = 128 #keep original rowRead, used when there are extra last set of rows rowReadExtra = rowRead #size of original image oriW, oriH = img.size totalRead = oriH/rowRead #is oriH is divisible by rowRead? rowLeft = oriH%rowRead #if there are some rows left at the bottom, add one more row to process if rowLeft!=0: totalRead = totalRead+1 #image header size, please check by img.tile, it is different for images header = img.tile[0][2]; #loop for each partial read for rr in range(totalRead): #reopen image, necessary due to partial loading img = Image.open("mfu2009(chs. 1,2,3).tif") #------- tile parameters -------- #for grayscale offset = rr*(rowRead*oriW) #if RGB if img.mode=='RGB': offset = offset*3 #if the last set of row is additional if rr==totalRead-1 and rowLeft!=0: rowRead = rowLeft #set tile size img.tile = [('raw', (0, 0, oriW, rowRead), header + offset, ('RGB', 0, 1))] #------- size parameters -------- img.size = (oriW, rowRead) #load part of image img.load() #copy part of image to new image #paste(source image, top-left corner) out.paste(img,(0,rr*rowReadExtra)) #save output to file out.save("output.tif","TIFF")
สำหรับกรณีที่สองนี้ เราสามารถคิดใหม่ก็ได้ว่า ให้อ่านแถวสุดท้ายเพิ่มขึ้น ซึ่งก็จะดีกว่าวิธีที่แล้ว เพราะลดขั้นตอนในการวนลูปลงหนึ่งขั้น ตัวอย่างเช่น
รูปมีทั้งสิ้น 7001 แถว (ความสูง) เราต้องการอ่านทีละ 128 พิกเซล
ก็จะต้องวนอ่านเท่ากับ 7001/128 = 54.69 หรือ 54 รอบ ซึ่งรอบสุดท้ายจะอ่านเพิ่มเป็น 128+(7001%128) = 128+89 = 217 แถว
โค้ดใหม่จะประมาณนี้ครับ ให้ผลลัพธ์เหมือนเดิม เร็วกว่าเดิมนิดนึง
from PIL import Image img = Image.open("mfu2009(chs. 1,2,3).tif") #create new output image out = Image.new(img.mode, img.size, None) #try to read every 128 rows rowRead = 128 #keep original rowRead, used when there are extra last set of rows rowReadExtra = rowRead #size of original image oriW, oriH = img.size totalRead = oriH/rowRead #is oriH is divisible by rowRead? rowLeft = oriH%rowRead #image header size, please check by img.tile, it is different for images header = img.tile[0][2]; #loop for each partial read for rr in range(totalRead): #reopen image, necessary due to partial loading img = Image.open("mfu2009(chs. 1,2,3).tif") #------- tile parameters -------- #for grayscale offset = rr*(rowRead*oriW) #if RGB if img.mode=='RGB': offset = offset*3 #if the last set of row is additional if rr==totalRead-1 and rowLeft!=0: rowRead = rowRead + rowLeft #set tile size img.tile = [('raw', (0, 0, oriW, rowRead), header + offset, ('RGB', 0, 1))] #------- size parameters -------- img.size = (oriW, rowRead) #load part of image img.load() #copy part of image to new image #paste(source image, top-left corner) out.paste(img,(0,rr*rowReadExtra)) #save output to file out.save("output.tif","TIFF")
ต่อไปเราคงต้องมาลองเทียบเวลาในการประมวลผลว่า การอ่านทั้งหมดและอ่านทีละส่วน เร็วหรือช้ากว่ากันเท่าใดครับ
No comments:
Post a Comment