ในไพธอนมีมอดูลชื่อ pdf2image ซึ่งเอาไว้แปลงไฟล์ pdf มาเป็นไฟล์รูปภาพได้
ในบทความนี้จะเขียนอธิบายถึงวิธีการใช้งานมอดูลนี้อย่างง่าย
การติดตั้งและใช้งาน pdf2image สามารถติดตั้งได้ง่ายโดยใช้ pip เช่นเดียวกับมอดูลส่วนใหญ่
pip install pdf2image
พอติดตั้งแล้วก็สามารถใช้งานได้เลย โดยมอดูลนี้โดยหลักๆแล้วมีอยู่แค่ ๒ ฟังก์ชัน คือ
convert_from_path
กับ
convert_from_bytes
แต่โดยทั่วไปแล้วใช้แค่
convert_from_path
เป็นหลัก
การใช้ convert_from_path ฟังก์ชัน
convert_from_path
ใช้เพื่อเปิดไฟล์ pdf ขึ้นมาเป็นลิสต์ของออบเจ็กต์รูปภาพของมอดูล PIL (pillow) ซึ่งสามารถใช้เมธอด
.save()
เพื่อทำการบันทึกเป็นไฟล์ภาพชนิดต่างๆได้
ตัวอย่างเช่นถ้าต้องการแปลงไฟล์ pdf ที่มีแค่หน้าเดียวให้เป็นไฟล์รูปภาพอาจเขียนโค้ดได้ดังนี้
import pdf2image
lis_img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf')
lis_img[0].save(r'ภาพจากคัมภีร์คาถาต้องห้าม.png')
ชนิดของภาพอาจเป็น png, jpg, gif, tif, bmp, ฯลฯ จะเป็นไฟล์ชนิดไหนก็ถูกตัดสินอัตโนมัติจากสกุลไฟล์ที่เขียนในชื่อ เช่นถ้าเขียนเป็ฯ
lis_img[0].save('xxx.jpg')
ก็จะได้เป็นไฟล์ jpg
ผลที่อ่านได้จาก
convert_from_path
นั้นเป็นลิสต์ซึ่งมีหลายภาพอยู่ข้างใน ถ้าหากต้องการจะเอามาบันทึกเป็นไฟล์ภาพก็อาจวนด้วย for แล้วบันทึกทีละภาพโดยใส่เลขหน้าไว้ข้างหลังชื่อ เช่น
import pdf2image
lis_img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf')
for i in range(len(lis_img)):
lis_img[i].save(r'ภาพจากคัมภีร์คาถาต้องห้าม_%d.png'%(i+1))
การใช้ convert_from_bytes ฟังก์ชัน
convert_from_bytes
นั้นก็คล้ายกับ
convert_from_path
แค่จะไม่ได้อ่าน pdf จากตัวไฟล์ แต่ไปอ่านจากข้อมูลไบต์ภายในตัวไฟล์ ถ้าจะใช้อ่านไฟล์จากภาพก็ต้องเปิดไฟล์ขึ้นมาด้วย open ในโหมด rb ก่อนแล้วอ่านข้อมูลในตัวไฟล์แล้วจึงค่อยใช้
convert_from_bytes
อย่างตัวอย่างที่แปลง pdf เป็นภาพหลายๆหน้านั้นถ้าจะใช้
convert_from_bytes
ก็อาจเขียนได้แบบนี้
import pdf2image
with open(r'คัมภีร์คาถาต้องห้าม.pdf','rb') as f:
lis_img = pdf2image.convert_from_bytes(f.read())
for i in range(len(lis_img)):
lis_img[i].save(r'ภาพจากคัมภีร์คาถาต้องห้ามx_%d.png'%(i+1))
การปรับความละเอียดของภาพ ปกติเมื่อใช้
convert_from_path
โดยไม่ได้กำหนดขนาดความละเอียดของภาพจะได้ภาพที่อาจใหญ่ไปหน่อย แต่หากต้องการทำให้ภาพเล็กลงหรือใหญ่ขึ้นไปอีกก็อาจทำได้โดยใส่คีย์เวิร์ด
dpi
ลงไป เช่น
lis_img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',dpi=72)
ถ้าไม่ได้ใส่ละก็ ค่าตั้งต้นคือ 200 ซึ่งค่อนข้างใหญ่
อนึ่ง จริงๆ dpi นั้นเป็นอาร์กิวเมนต์ตัวที่ ๒ อยู่แล้ว ดังนั้นก็อาจละ
dpi=
ไปก็ได้ เช่น
lis_img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',72)
การกำหนดขนาดของภาพ นอกจากกำหนดความละเอียดของภาพแล้ว เราอาจทำการกำหนดขนาดความกว้างและสูงของภาพโดยตรงได้เลย โดยใส่คีย์เวิร์ด
size
แล้วใส่ทูเพิลของความกว้างและสูงที่ต้องการลงไปได้เลย เช่น
lis_img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',size=(300,200))
print(lis_img[0].size) # ได้ (300, 200)
แต่หากต้องการกำหนดแค่ความกว้างแล้วให้ความสูงถูกเปลี่ยนตามสัดส่วนละก็อาจใส่ตัวหลังเป็น None เช่น
lis_img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',size=(300,None))
print(lis_img[0].size) # ได้ (300, 425)
ในตัวอย่างนี้ใช้กับเอกสารที่เป็ฯหน้า A4 ดังนั้นถ้าความกว้างเป็น 300 ความสูงก็จะเป็น 425 อย่างที่เห็น
และเช่นเดียวกัน หากตัวหน้าเป็น None ก็จะเป็นการกำหนดความสูง แล้วให้ความกว้างกำหนดตามสัดส่วนโดยอัตโนมัติ เช่น
lis_img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',size=(None,200))
print(lis_img[0].size) # ได้ (142, 200)
นอกจากนี้อาจใส่เป็นเลขตัวเดียวก็ได้ ซึ่งนั่นจะหมายความว่ากำหนดทั้งความกว้างและสูงเป็นค่านั้น
lis_img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',size=300)
print(lis_img[0].size) # ได้ (300, 300)
การเอาเฉพาะบางหน้า หากต้องการจะเอาเฉพาะแค่บางหน้าภายในไฟล์ pdf ก็อาจทำได้โดยการใส่คีย์เวิร์ด
first_page
และ
last_page
ลงไป
เช่นถ้าต้องการแค่หน้า 2 ไปจนถึงหน้า 4 ก็อาจเขียนเป็น
lis_img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',first_page=2,last_page=4)
print(len(lis_img)) # ได้ 3
แบบนี้ก็จะได้มาแค่ ๓ หน้า คือหน้า 2,3,4
อนึ่ง เลขหน้าในที่นี้จะนับจาก 1 ไม่ใช่นับจาก 0 ต่างจากลิสต์ในไพธอนที่เริ่มจาก 0 ดังนั้นระวังสับสน
การทำภาพโปร่งใส ปกติภาพที่ได้จากการใช้
convert_from_path
โดยทั่วไปจะได้ภาพที่ไม่มีความโปร่งใส และฉากหลังเป็นสีขาว แต่ให้ด้านหลังสีขาวนี้กลายเป็นโปร่งใสแทนก็ทำได้โดยใส่คีย์เวิร์ด
transparent=True
ลงไป เพียงแต่ว่าจะต้องใส่
fmt='png'
ลงไปด้วย เพื่อให้อ่านขึ้นมาในโหมดภาพ png ซึ่งมีค่าความโปร่งใสอยู่ตั้งแต่แรก
อนึ่ง
fmt
ในที่นี้ปกติไม่ได้จำเป็นต้องใส่ เพราะยังไงตอนที่จะบันทึกเป็นภาพโดยใช้
.save()
ก็กำหนดสกุลของภาพได้ตามที่ต้องการอยูด้วย แต่โดยปกติถ้าไม่ได้ใส่ fmt จะถูกอ่านเป็นชนิด ppm (portable pixmap) ซึ่งไม่ได้รวมค่า alpha (ค่าความไม่ใส) อยู่ด้วย
ลองเปิดแบบต่างๆแล้วเทียบผลลัพธ์ดู
img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',fmt='png')[0]
print(img.mode) # ได้ RGB
img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',fmt='png',transparent=True)[0]
print(img.mode) # ได้ RGBA
img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',transparent=True)[0]
print(img.mode) # ได้ RGB
ในที่นี้ RGBA คือโหมดของภาพที่มีความโปร่งใส ถ้านำมาบันทึกเป็นไฟล์ png ก็จะได้จะเป็นภาพที่ฉากหลังโปร่งใส จะเห็นได้ว่าถึงใส่
transparent=True
แต่ถ้าไม่ได้ใส่
fmt='png'
ไปด้วยก็จะได้ผลไม่ต่างจากไม่ใส่ คือได้โหมด RGB ซึ่งเป็นภาพสีธรรมดาไม่มี A (คือค่า alpha) รวมอยู่
การทำเป็นภาพขาวดำ หากไม่ต้องการสี ต้องการเปิดในโหมดภาพขาวดำก็ทำได้โดยใส่
grayscale=True
ลงไป เท่านี้ก็กลายเป็นภาพขาวดำแล้ว
img = pdf2image.convert_from_path(r'คัมภีร์คาถาต้องห้าม.pdf',grayscale=True)[0]
print(img.mode) # ได้ L
การทำไฟล์ tiff หลายหน้า ไฟล์ tiff (.tif) นั้นเป็นสกุลไฟล์ภาพที่สามารถบันทึกภาพหลายภาพลงในไฟล์เดียวได้ โดยแต่ละภาพนั้นจะถูกใส่แยกเป็นหน้า
การใช้ pdf2image เพื่อบันทึกแต่ละหน้าใน pdf ลงมาเป็นหน้าใน tiff อาจเขียนได้ดังนี้
import pdf2image
pdf_file = r'เอกสาร.pdf' # ชื่อไฟล์ pdf ที่จะแปลง
img_file = r'ภาพ.tif' # ชื่อไฟล์ tiff ที่ต้องการ
lis_img = pdf2image.convert_from_path(pdf_file,dpi=72)
lis_img[0].save(img_file,compression='tiff_deflate',save_all=True,append_images=lis_img[1:])
ในที่นี้จริงๆไม่ใช่ความสามารถของ pdf2image โดยตรง แต่เป็นความสามารถของเมธอด
.save()
ของตัวออบเจ็กต์ภาพของ PIL ดังนั้นจะขอละการอธิบายในรายละเอียด
การแปลงไฟล์เวิร์ดเป็นไฟล์ภาพ หากต้องการจะแปลงไฟล์เวิร์ดไปเป็นไฟล์ภาพ เราอาจใช้ docx2pdf ร่วมกับ pdf2image ได้
ที่จริงแล้วถ้ามีวิธีที่สามารถแปลงจากเวิร์ดเป็นภาพได้โดยตรงละก็คงไม่จำเป็นต้องทำแบบนี้ แต่ดูเหมือนจะไม่มีวิธี ดังนั้นจึงต้องใช้วิธีแปลง ๒ ต่อแบบนี้
สำหรับเรื่องการแปลงจากเวิร์ดเป็น pdf โดยใช้ docx2pdf อ่านได้ใน
https://phyblas.hinaboshi.com/20230207 โค้ดแปลงเวิร์ดเป็นภาพ png อาจเขียนได้แบบนี้
import docx2pdf
import pdf2image
import os
word_file = r'คัมภีร์คาถาต้องห้าม.docx' # ชื่อไฟล์เวิร์ดที่ต้องการแปลง
img_path = r'ภาพจากคัมภีร์คาถาต้องห้าม' # ชื่อโฟลเดอร์ที่จะวางไฟล์ภาพที่ได้
dpi = 72 # ค่าความละเอียดของภาพ
# ก่อนอื่นแปลงเป็น pdf ก่อน
pdf_file = word_file+'.pdf' # ชื่อไฟล์ pdf ที่จะสร้างขึ้นมาชั่วคราว แต่เดี๋ยวก็จะลบอยู่แล้วที่จริงจะตั้งยังไงก็ได้
docx2pdf.convert(word_file,pdf_file)
# ถ้าโฟลเดอร์ที่จะวางรูปนั้นยังไม่มีอยู่ก็สร้างขึ้นมาก่อน
if(not os.path.exists(img_path)):
os.mkdir(img_path)
# ทำการแปลงจาก pdf เป็นภาพ
lis_img = pdf2image.convert_from_path(pdf_file,dpi)
for i,img in enumerate(lis_img,1):
img.save(os.path.join(img_path,str(i)+'.png'))
os.remove(pdf_file) # ไฟล์ pdf ใช้เสร็จแล้วก็ลงทิ้งได้
แบบนี้แล้วก็จะได้ภาพของแต่ละหน้าในไฟล์เวิร์ดนั้นมาอยู่ในโฟลเดอร์ที่กำหนดไว้
ถ้าหากมีอยู่หน้าเดียวอยู่แล้วก็อาจเขียนแบบนี้ได้เลย
word_file = r'คัมภีร์คาถาต้องห้าม.docx' # ชื่อไฟล์เวิร์ดที่ต้องการแปลง
img_file = r'ภาพจากคัมภีร์คาถาต้องห้าม.png' # ไฟล์ภาพที่ต้องการสร้าง
dpi = 72 # ค่าความละเอียดของภาพ
pdf_file = word_file+'.pdf'
docx2pdf.convert(word_file,pdf_file)
pdf2image.convert_from_path(pdf_file,dpi)[0].save(img_file)
os.remove(pdf_file)
เท่านี้ก็สามารถแปลงไฟล์เวิร์ดให้เป็นรูปภาพได้แล้ว
สรุปทิ้งท้าย สุดท้ายนี้ของสรุปคีย์เวิร์ดต่างๆที่ใช้ใส่ใน
convert_from_path
ซึ่งได้กล่าวถึงมาในข้างต้นไว้ตรงนี้
dpi |
ความละเอียดของภาพที่อ่านได้ |
size |
ขนาดของภาพที่อ่านได้ |
first_page |
หน้าแรกที่จะอ่าน |
last_page |
หน้าสุดท้ายที่จะอ่าน |
fmt |
ฟอร์แม็ตของภาพที่อ่านได้ |
transparent |
ถ้าใส่ True จะได้ภาพที่ฉากหลังโปร่งใส |
grayscale |
ถ้าใส่ True จะได้ภาพขาวดำ |
อ้างอิง