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
- 6121 reads







Recent comments