-1

So, i'm trying to combine multiple files (PDF's and images) using just Python. So far managed to do with PDFs and "JPG" images. However, everytime i try to convert "PNG" images to PDF using PIL, an error pops-up saying "ValueError: cannot save mode RGBA".

I know PIL can convert "RGBA" to "RGB" but for some reason the code below is not working properly.

Any ideas why?

P.S.: Started learning Python one week ago, if it's obvious to you, please, be kind.

PYTHON CODE

# pip instal PyPDF2

from pathlib import Path
import os
import sys
import img2pdf
from PIL import Image 
from PyPDF2 import PdfFileMerger

source_dir = sys.argv[1]

os.chdir(sys.argv[1])

print(sys.argv[1])

merger = PdfFileMerger()

for item in os.listdir(source_dir):
    
    if item.endswith('jpg'):
        print(item)
        output = "output.pdf"
        print(output)

        if os.path.isfile(output):
            expand = 1
            while True:
                expand += 1
                new_output = output.split(".pdf")[0] + str(expand) + ".pdf"
                print(new_output)
                
                if os.path.isfile(new_output):
                    continue
                else:
                    output = new_output
                    Image.open(item).save(output, "PDF", resolution=100.0)
                    break
                    
                    
        if not os.path.isfile(output):
                    print(output)
                    Image.open(item).save(output, "PDF", resolution=100.0)

for item in os.listdir(source_dir):
        
    if item.endswith('png'):
        print(item)
        saida = "saida.pdf"
        print(saida)
        if Image.open(item).mode == "RGBA":
            Image.open(item).convert("RGB")

        if os.path.isfile(saida):
            expande = 1
            while True:
                expand += 1
                new_saida = saida.split(".pdf")[0] + str(expande) + ".pdf"
                print(new_saida)
                
                if os.path.isfile(new_saida):
                    continue
                else:
                    saida = new_saida
                    Image.open(item).save(saida, "PDF", resolution=100.0)
                    break
                    
                    
        if not os.path.isfile(saida):
                    print(saida)
                    Image.open(item).save(saida, "PDF", resolution=100.0)
    
                       
for item in os.listdir(source_dir):
    
    if item.startswith('Doc.'):
        merger.merge(position=0, fileobj=item, bookmark=None, pages=None)
        
    if item.endswith('pdf'):
        merger.append(item)
                  
merger.write('tentativa.pdf')
merger.close()


filepath = source_dir + "\\"

for item in os.listdir(source_dir):
    if item.startswith('Doc'):
        docname = item
        os.rename(filepath + docname, filepath + 'delete.pdf')

for item in os.listdir(source_dir):
    
    if item.startswith('output'):
        os.remove(item)

for item in os.listdir(source_dir):
    if item.startswith('delete'):
        os.remove(item)

    if item.startswith('tentativa'):
        docname2 = item
        os.rename(filepath + docname2, filepath + docname)        
    

2 Answers2

1

You need to convert your PNG from RGBA to RGB first. Png has an extra alpha channel hence RGBA. RGBA is 32bit while RGB is 24bit. as mentioned here

Sample code:

from PIL import Image

PNG_FILE = 'a.png'
PDF_FILE = 'b.pdf'

rgba = Image.open(PNG_FILE)
rgb = Image.new('RGB', rgba.size, (255, 255, 255))  # white background
rgb.paste(rgba, mask=rgba.split()[3])               # paste using alpha channel as mask
rgb.save(PDF_FILE, 'PDF', resoultion=100.0)
  • 1
    So "Image.open(item).convert" do not work on this case? – Renan Liporaci Aug 04 '20 at 22:07
  • ofcourse, you can open the image with the image.open() subclass but the type of data read and type of data expected will mismach while converting RGBA ==> RGB which is the line mentioning [Image.open(item).convert("RGB") ] somewhere in your second for loop... JUST remove the mode and use the above code rgb= Image.new('RGB', rgba.size, (255, 255, 255)) and paste the data in it. –  Aug 04 '20 at 22:25
0

You need to convert your PNG from RGBA to RGB first, like this:

from PIL import Image

PNG_FILE = 'image.png'
PDF_FILE = 'doc.pdf'

rgba = Image.open(PNG_FILE)
rgb = Image.new('RGB', rgba.size, (255, 255, 255))  # white background
rgb.paste(rgba, mask=rgba.split()[3])               # paste using alpha channel as mask
rgb.save(PDF_FILE, 'PDF', resoultion=100.0)
coltonrusch
  • 194
  • 11