python : แตกไฟล์ JPG จากไฟล์ภาพ Canon
มีโจทย์อยู่คือ
เวลาไปเที่ยวหรือมีงานที่ต้องถ่ายภาพเป็นจำนวนมาก เกินการ์ดหน่วยความจำที่มีอยู่
เวลาการ์ดเต็ม ก็ต้องถ่ายออกมาเก็บไว้ในโน๊ตบุ๊ก
ปัญหาคือเวลาจะดูภาพจากโน๊ตบุ๊ก ซึ่งสเปคเครื่องต่ำมาก โหลดไฟล์ภาพใหญ่ ๆ ไม่ไหว มันจะดูได้ช้ามาก ๆ ดูภาพ 10 ภาพ ใช้เวลาไป 15 นาที
ทางแก้คือคัดลอกไฟล์ภาพมาแปลงเป็นไฟล์เล็ก (อาจจะแปลงด้วย gimp หรือ imagemagick ก็ได้) แต่เนื่องจากสเปคเครื่องต่ำมาก แปลงไฟล์แต่ละครั้งกินเวลาเป็นชั่วโมง ไม่ทันต่อเหตุการณ์
ทางออกอีกทางคือไปแตกเอาไฟล์ JPG อันเล็ก ที่ซ่อนอยู่ภายใต้ไฟล์ตัวจริงซึ่งใหญ่มาก เอาออกมาแทน วิธีนี้จะทำงานได้รวดเร็วกว่ามาก
เคยเขียน C ไว้เป็นไฟล์เล็ก ๆ บนวินโดวส์ แต่เที่ยวนี้ผมลองเอามาคอมไพล์บนลินุกส์ ปรากฎว่าคอมไพล์ไม่ผ่าน และภาษา C ก็ลืมสิ้นแล้ว อย่ากระนั้นเลย พึ่งไพธอนดีกว่า
ผมใช้กล้อง Canon และเราจะแตกไฟล์ JPG อันเล็ก ซึ่งเป็นไฟล์ลำดับที่ 3 ที่ซ่อนอยู่ในไฟล์ใหญ่ เลยตั้งชื่อโปรแกรมว่า canon3.py
เวลาใช้งานก็สั่ง
$ ./canon3.py FILENAME.JPG
ก็จะแตกไฟล์ FILENAME.JPG ไปเป็น canon3/FILENAME.JPG
หรือถ้าสั่ง
$ ./canon3.py
เฉย ๆ
ก็จะควานหาทุกไฟล์ในไดเรกทอรี่ที่เป็น JPG หรือ CRW และแตกไฟล์ย่อยออกมาใส่ในไดเรกทอรี่ย่อย canon3
โดยโปรแกรมจะคัดลอกเอาข้อมูล Exif ของกล้องติดไปด้วย (แต่ข้อมูลขนาดภาพใน Exif จะผิดจากความเป็นจริง ขี้เกียจแก้แล้วอ่ะ)
ทดลองแล้วความเร็วใสการแตกไฟล์ดีมาก (ไพธอนนี่ดีกว่าที่คิดเยอะเลย)
โค๊ดมีดังนี้
#!/usr/bin/env python # EXTRACT THIRD jpg FILE IN Canon CAMERA # # jpg file format # start with: FF D8 FF E1 NN NN ... (contain exif data to byte NN NN) # first JPG : FF D8 ... FF D9 (thumbnail) # second JPG: FF D8 ... FF D9 (real JPG) # third JPG : FF D8 ... FF D9 (hidden small JPG) # SKIP TO 2/3 OF FILE THEN SEARCH FOR THIRD #FFD8 TO #FFD9 # import sys, os, string # VAR tag_beg="\xff\xd8" tag_end="\xff\xd9" subdir="canon3" file_skel=[".JPG",".jpg",".jpeg"] dir_skel=["DCIM","CANON"] # PROCEDURE def process_file(filename): for fskel in file_skel: if fskel in filename: #OPEN FILE IN BINARY MODE try: f = open(filename, 'rb') except: print 'Could not open file to read !', filename sys.exit(3) if f is None: print 'Error opening file ', filename sys.exit(3) # COPY EXIF HEADING TO NEW FILE IN SUBDIR canon3 basename=os.path.basename(filename) print "%s -> %s/%s" % (basename,subdir,basename) if not os.path.exists(subdir): os.mkdir(subdir) # f_new=open(os.path.join(subdir,basename),"wb") # SEEK FF D8 FF E1 NN NN f.seek(4) offset_low=f.read(1) offset_hi=f.read(1) no_of_byte=ord(offset_low)*256+ord(offset_hi)-4 ## print "no_of_byte=%i" % no_of_byte # WRITE TO NEW FILE f_new.write("\xff\xd8\xff\xe1"+offset_low+offset_hi+f.read(no_of_byte)) # SEEK FOR THE REST 3RD JPG FILE # INCREASE SPEED BY SKIP TO 2/3 OF FILE f.seek(os.path.getsize(filename) * 2/3) is_found=False for i in f: if tag_beg in i: is_found=True # WRITE THIRD JPG TO NEW FILE f_new.write(tag_beg+i.split(tag_beg)[1]) for j in f: if tag_end in j: f_new.write(j.split(tag_end)[0]+tag_end) break f_new.close() else: f_new.write(j) # # break # # f.close() if not is_found: print "third JPG file not found." # # # def process_dir(dirname): ## print "dirname=%s" % dirname for dskel in dir_skel: if dskel in dirname: print "enter %s" % dirname os.chdir(dirname) filelist=os.listdir(".") for i in filelist: if os.path.isdir(i): process_dir(i) else: process_file(i) # # print "exit %s" % dirname os.chdir("..") # # # MAIN PROG def main(): if len(sys.argv) < 2: # PROCESS ALL FILE&DIR for filelist in os.listdir("."): if os.path.isdir(filelist): process_dir(filelist) else: process_file(filelist) # # else: filename = os.path.abspath(sys.argv[1]) if os.path.isdir(filename): process_dir(filename) else: process_file(filename) # # print "finished" if __name__=="__main__": main()
แถมอีกนิด
ถ้าจะให้หมุนภาพอัตโนมัติด้วย ต้องใช้แพคเกจ jhead
$ sudo apt-get install jhead
$ jhead -autorot *
- Printer-friendly version
- Log in or register to post comments
- 5878 reads
Recent comments