class ConvertToPDF(BaseClass): def __init__(self, language=None): """ - language: language of messages """ super().__init__(language) self.pdf = FPDF(unit='mm', format='A4') self.pdf.set_compression(True) # A4 format size self.pdf_size = {'P': {'w': 210, 'h': 297}, 'L': {'w': 297, 'h': 210}} def apply(self, patch, page): """ Converts image to file pdf. where: - path: directory where the images are - page: integer number page """ self.message.toprint('IMAGE_CREATE_PDF') cover = Image.open(patch) width, height = cover.size # convert pixel in mm with 1px=0.264583 mm width, height = float(width * 0.264583), float(height * 0.264583) # get page orientation from image size orientation = 'P' if width < height else 'L' # make sure image size is not greater than the pdf format size width = width if width < self.pdf_size[orientation][ 'w'] else self.pdf_size[orientation]['w'] height = height if height < self.pdf_size[orientation][ 'h'] else self.pdf_size[orientation]['h'] # center image self.pdf.add_page(orientation=orientation) self.pdf.image(patch, self.settings.PDF_X, self.settings.PDF_Y, width, height) self.message.toprint('IMAGE_CREATED_PDF', {'page': page}) def save(self, file_destin): """ Save image to file pdf. where: - file_destin: name file destiny """ self.message.toprint('SAVE_PDF') self.pdf.output(file_destin, 'F') self.message.toprint('SAVED_PDF')
def create_PDF_file(sourcedir, dest, name): print('Creating {}/{}'.format(dest, name)) pdf = FPDF(orientation="P",unit="mm",format="A4") pdf.set_compression(True) pdf.add_page() pdf.add_font('FreeMono', '', 'font/FreeMono.ttf', uni=True) pdf.set_margins(0,0,0) files = os.listdir(sourcedir) # create destination directory if not present if not os.path.exists(dest): os.makedirs(dest) # write index if 'index.txt' in files: print('Index found') pdf.set_font('FreeMono',size=12) with open('{}/index.txt'.format(sourcedir),'r', encoding='cp1250') as index: entries = index.readlines() for entry in entries: pagenum = int(entry[-4:]) link = pdf.add_link() pdf.set_link(link, page=pagenum +1) pdf.set_x(0) # print('{} {}'.format(entry[:-6],pagenum)) pdf.write(5, '{}...........{}\n'.format(entry[:-6],pagenum), link) print('Index built') # remove all except .jpg files = list(filter(lambda x: x.endswith('.jpg'), files)) # sort by numbers files.sort(key=lambda x: int(x[-8:-4])) print('Adding {} images'.format(len(files))) for imag in files: pdf.image(name='{}/{}'.format(sourcedir, imag), type='JPG', w=210, h=297) print('Writing pdf file...') pdf.output('{}/{}'.format(dest, name), 'F') pdf.close() print('Done\n')
import os from fpdf import FPDF #create pdf pdf = FPDF('L', 'pt', 'letter') pdf.add_page() pdf.set_compression(True) #width and height of image (1:2 ratio), height is limiting ih = pdf.h iw = ih * 11 / 8.5000000 #coordinates of image x, y = 0, 0 directory = 'tile' #loop through all images for i in range(0, 32): pdf.image(directory + '/' + str(i) + '_1.png', 0, 0, 'png') pdf.add_page() # print(filename) print(i) pdf.output(directory + '/' + 'ticket-tiled-2.pdf', 'F') print('all done!')
from PIL import Image from fpdf import FPDF import os import pathlib import time #Obtem o diretorio atual. Supoe-se que o script esta na mesma pasta das imagens para serem redimensionadas. directory = os.path.dirname(os.path.abspath(__file__)) pdf = FPDF(format="A4") pdf.set_compression(False) result = pathlib.Path('imgs_reduzidas/').mkdir(exist_ok=True) w = int(input("Insira a largura da imagem (cm): ")) h = int(input("Insira a altura da imagem (cm): ")) #Converte CM para Pixels w_px = int(38 * w) h_px = int(38 * h) size = w_px, h_px list_formats = (".jpg", ".png", ".jpeg") for i,file in enumerate(os.listdir(directory)): is_image = False #Obtem o nome do arquivo e o formato e coloca-os em uma lista ("nome", "formato") file_name = os.path.splitext(file) #print(">>", file_name[1]) for f in list_formats: if(file_name[1] == f): #Verifica se o formato do arquivo pode ser convertido. Se sim, encerra a verificacao. is_image = True break if(is_image): #Abre a imagem im = Image.open(file) #Redimensiona a imagem para o tamanho escolhido
def create_qc_pdf(**kwargs): try: kwargs['company'] = kwargs.get('company', u'台茂化工儀器原料行') kwargs['product'] = kwargs.get('product', u'product name?') kwargs['ASE_pn'] = kwargs.get('ASE_pn', u'ASE PN?') if not kwargs.get('lot_no'): kwargs['make_date'] = date.today() kwargs['test_date'] = date.today() kwargs['lot_no'] = u'lot number?' else: year = 2000 + int(kwargs['lot_no'][1:3]) month = int(kwargs['lot_no'][3:5]) day = int(kwargs['lot_no'][5:7]) kwargs['make_date'] = date(year, month, day) kwargs['test_date'] = date(year, month, day) kwargs['exp_period'] = kwargs.get('exp_period', u'一年') kwargs['amount'] = kwargs.get('amount', u'amount?') kwargs['tester'] = kwargs.get('tester', u'tester?') kwargs['test_params'] = kwargs.get('test_params', []) except Exception as e: print e return # Set placement and style of values tm_branch = dict(x=30, y=25, w=178-30, h=10, align='C') product_name = dict(x=31, y=50, w=104-31, h=15, align='L') product_ASE_pn = dict(x=105, y=50, w=104-31, h=15, align='L') make_date = dict(x=31, y=65, w=104-31, h=8, align='L') test_date = dict(x=31, y=73, w=104-31, h=8, align='L') exp_period = dict(x=31, y=81, w=104-31, h=9, align='L') lot_no = dict(x=105, y=65, w=104-31, h=8, align='L') amount = dict(x=105, y=73, w=104-31, h=8, align='L') tester = dict(x=105, y=81, w=104-31, h=9, align='L') # Create PDF FPDF = myPDF('P','mm','A4') FPDF.set_compression(False) FPDF.set_creator('TM_2014') FPDF.set_title(u'Quality inspection report for lot# {}'.format(kwargs['lot_no'])) FPDF.set_author(u'Taimau Chemicals') FPDF.set_subject(kwargs['lot_no']) # FPDF.set_subject(u'{} {}'.format(kwargs['product'], kwargs['lot_no']), isUTF8=True) FPDF.alias_nb_pages() FPDF.add_page() # Adding a page also creates a page break from last page FPDF.add_font(family=u'SimHei', style='', fname=font, uni=True) # Only .ttf and not .ttc FPDF.set_font(family=u'SimHei', style='', size=16) FPDF.xycell(txt=kwargs['company'], **tm_branch) FPDF.set_font(family=u'SimHei', style='B', size=13) FPDF.xycell(txt=u'產品: {}'.format(kwargs['product']), **product_name) FPDF.xycell(txt=u'料號: {}'.format(kwargs['ASE_pn']), **product_ASE_pn) FPDF.xycell(txt=u'製造日期: {}'.format(kwargs['make_date']), **make_date) FPDF.xycell(txt=u'檢驗日期: {}'.format(kwargs['test_date']), **test_date) FPDF.xycell(txt=u'保存期間: {}'.format(kwargs['exp_period']), **exp_period) FPDF.xycell(txt=u'批號: {}'.format(kwargs['lot_no']), **lot_no) FPDF.xycell(txt=u'生產數量: {}'.format(kwargs['amount']), **amount) FPDF.xycell(txt=u'取樣人員: {}'.format(kwargs['tester']), **tester) FPDF.set_left_margin(30) FPDF.set_xy(x=30, y=105) for (a, b, c) in kwargs['test_params']: if a+b+c == u'': break FPDF.cell(49, 10, txt=a, align='C') FPDF.cell(49, 10, txt=b, align='C') FPDF.cell(49, 10, txt=c, align='C') FPDF.ln() FPDF.cell(49) FPDF.cell(49, 10, txt=u'以下空白', align='C') initialfilename = u'QC_{}_{}'.format(kwargs['product'], kwargs['lot_no']) FILE_OPTS = dict( title = u'PDF name and location.', defaultextension = '.pdf', initialdir = os.path.expanduser('~') + '/Desktop/', initialfile = initialfilename, ) if settings.load().get(u'pdfpath'): FILE_OPTS['initialdir'] = settings.load()[u'pdfpath'] outfile = os.path.normpath(tkFileDialog.asksaveasfilename(**FILE_OPTS)) if os.path.exists(outfile): os.remove(outfile) if outfile and not os.path.exists(outfile): FPDF.output(name=outfile) try: subprocess.call(['start', outfile], shell=True) return except: pass try: print u'Trying alternate subprocess command.' subprocess.call(['start', '/D'] + list(os.path.split(outfile)), shell=True) return except UnicodeEncodeError: pass try: os.startfile(outfile) return except: pass print u'Failed to autoload PDF after creation.' return else: head = u'Cancelled' body = u'Canceled PDF creation.' tkMessageBox.showinfo(head, body)
class Cards_Creator: # n prime number __n = -1 # number of symbols per card = n + 1 __sn = -1 # symbol width __sw = -1 # cols per page __colspp = -1 # rows per page __rowspp = -1 # cards per page __cardspp = -1 # images list __files = None # cards list __cards = None # card width __cw = -1 # card height __ch = -1 # card radius __cr = -1 # page width __pw = -1 # page height __ph = -1 def __init__(self, symbols_per_card, cards, files): self.__colspp = 2 self.__rowspp = 3 self.__cardspp = self.__colspp * self.__rowspp self.__n = symbols_per_card - 1 self.__sn = symbols_per_card self.__files = files self.__cards = cards # A4 size is 210 x 297 mm self.__pw = 210 self.__ph = 297 self.__recalculate() def __init_PDF(self): # init pdf generation self.__pdf = FPDF() self.__pdf.set_margins(left=5, top=5, right=5) self.__pdf.set_compression(False) def __recalculate(self): # A4 size can contain rows x columns cards self.__cw = self.__pw / self.__colspp self.__ch = self.__ph / self.__rowspp self.__cr = min(self.__cw, self.__ch) self.__sw = self.__cr / 4 print("Card size: %d x %d." % (self.__cw, self.__ch)) print("Card radius: %d." % (self.__cr)) def __add_markers(self): self.__pdf.image("./lib/marker.png", 0, 0) self.__pdf.image("./lib/marker.png", self.__pw - 1, 0) self.__pdf.image("./lib/marker.png", self.__pw - 1, self.__ph - 1) self.__pdf.image("./lib/marker.png", 0, self.__ph - 1) def __add_image_to_card(self, x, y, r, i, file_index): delta_angle = math.pi * 2 / (self.__sn - 1) angle = delta_angle * i if i < 1: px = x - self.__sw / 2 py = y - self.__sw / 2 else: if i % 2 == 0: delta = -6 else: delta = 1 px = x + ((r+delta) * math.cos(angle) - self.__sw / 2) py = y + ((r+delta) * math.sin(angle) - self.__sw / 2) self.__pdf.image(self.__files[file_index-1], px, py, self.__sw) def __add_card_to_pdf(self, card, col, row, r): for i in range(len(card)): px = col * self.__cw + self.__cw / 2 py = row * self.__ch + self.__ch / 2 self.__add_image_to_card(px, py, r, i, card[i]) self.__pdf.image("./lib/circle.png", px - self.__cr / 2 + 1, py - self.__cr/2 + 1, self.__cr - 2) def __add_pages(self): # generate all pages index = 0 page_num = 0 cards_total = len(self.__cards) pages_total = math.ceil(cards_total / self.__cardspp) # iterate thgrough all cards while index < cards_total: i = index % self.__cardspp # generate 6 cards per page if i == 0: page_num += 1 self.__pdf.add_page() self.__add_markers() print("Generating page %d out of %d." % (page_num, pages_total)) card = self.__cards[index] col = i % self.__colspp row = math.floor(i / self.__colspp) self.__add_card_to_pdf(card, col, row, self.__cr / 3) index += 1 def __add_external_pages(self, path): # generate all pages index = 0 page_num = 0 cards_total = len(self.__cards) pages_total = math.ceil(cards_total / self.__cardspp) # iterate thgrough all cards while index < cards_total: i = index % self.__cardspp # generate 6 cards per page if i == 0: page_num += 1 self.__pdf.add_page() self.__add_markers() print("Generating page %d out of %d." % (page_num, pages_total)) card = self.__cards[index] col = i % self.__colspp row = math.floor(i / self.__colspp) #self.__add_card_to_pdf(card, col, row, self.__cr / 3) px = col * self.__cw + self.__cw / 2 py = row * self.__ch + self.__ch / 2 self.__pdf.image(path + format(index, '02d') + ".png", px - self.__cr / 2 + 1, py - self.__cr/2 + 1, self.__cr - 2) index += 1 def __add_intro_page(self, pdf, files): cols = 5 page_top = 50 page_left = 15 page_width = 200 page_height = 270 pdf.add_font('Font', '', "C:\Windows\Fonts\Verdana.ttf", uni=True) pdf.add_font('Font', 'B', "C:\Windows\Fonts\Verdana.ttf", uni=True) pdf.add_page() pdf.set_font('Font', 'B', 20) pdf.cell(page_width, 10, "DOBBLE", border=0, ln=0, align="C") pdf.set_font('Font', '', 14) pdf.text( 25, 25, "Oto symbole, jakie możesz napotkać na poszczególnych kartach:") pdf.set_font('Font', 'B', 9) i = 0 for file in files: col = i % cols row = math.floor(i / cols) text = file.split( '/')[-1:][0].split('.')[-2:-1][0].replace('_', ' ') print(col, row, text) pdf.image(file, page_left + col * 40, page_top + row * 20 - 16, h=12) pdf.text(page_left + col * 40, page_top + row * 20, text) i += 1 def set_page_format(self, cols, rows): self.__colspp = cols self.__rowspp = rows self.__cardspp = cols * rows self.__recalculate() def generate_cards(self, path): if len(self.__files) >= len(self.__cards): print("Generating %d cards in separate png files, %d symbols per card." % (len(self.__cards), self.__sn)) os.makedirs(path) i = 0 for item in self.__cards: print(item) image_urls = [self.__files[num - 1] for num in item] print(image_urls) Card().generate_card(image_urls, path + format(i, '02d') + ".png") i += 1 def generate_pdf(self, path, file_name): if len(self.__files) >= len(self.__cards): print("Generating PDF file with %d cards, %d cards per A4 page, %d symbols per card." % (len(self.__cards), self.__cardspp, self.__sn)) self.__init_PDF() self.__add_intro_page(self.__pdf, self.__files) # self.__add_pages() self.__add_external_pages(path + "cards/") self.__pdf.output(path + file_name + ".pdf")
def process(self, output_file_name=None, dpi=150, offset=0, fps=10, height_mm=50, margins=Margin(10, 10, 10, 10), paper_format='a4'): def draw_raster(): for ix in range(0, nx + 1): xx = x0 + ix * total.width pdf.line(xx, y0, xx, y1) if offset > 0 and ix != nx: pdf.line(xx + offset, y0, xx + offset, y1) for iy in range(0, ny + 1): yy = y0 + iy * total.height pdf.line(x0, yy, x1, yy) height_mm = float(height_mm) tmp_files = [] if self.clip: if fps != self.clip.fps: if self.verbosity > 0: print 'Transcoding from {} fps to {} fps ...'.format(self.clip.fps, fps) self.clip.write_videofile('tmp.mp4', fps=fps, audio=False) tmp_files.append('tmp.mp4') self.clip = VideoFileClip('tmp.mp4') self.fps = self.clip.fps self.frame_count = int(self.clip.duration * self.fps) clip_size = Size.from_tuple(self.clip.size) elif self.frames: clip_size = Size.from_tuple(self.im.size) paper = self.PAPER_SIZES[paper_format.lower()] printable_area = Size(paper.width - margins.left - margins.right, paper.height - margins.top - margins.bottom) frame_mm = Size(height_mm / clip_size.height * clip_size.width, height_mm) total = Size(offset + frame_mm.width, frame_mm.height) frame = Size(int(frame_mm.width / 25.4 * dpi), int(frame_mm.height / 25.4 * dpi)) nx = int(printable_area.width / total.width) ny = int(printable_area.height / total.height) if self.verbosity > 0: print 'Input: {} fps, {}x{}, {} frames'\ '\n from: {}'\ .format( self.fps, clip_size.width, clip_size.height, self.frame_count, self.input_file_name ) print 'Output: {}dpi, {}x{}, {:.2f}mm x {:.2f}mm, {}x{} tiles'\ '\n to: {}'\ .format( dpi, frame.width, frame.height, frame_mm.width, frame_mm.height, nx, ny, output_file_name ) pdf = FPDF(unit='mm', format=paper_format.upper(), orientation='L') pdf.set_compression(True) pdf.set_title('Funny video') pdf.set_author('Oliver Lau <*****@*****.**> - Heise Medien GmbH & Co. KG') pdf.set_creator('flippy') pdf.set_keywords('flip-book, video, animated GIF') pdf.set_draw_color(128, 128, 128) pdf.set_line_width(0.1) pdf.set_font('Helvetica', '', 12) pdf.add_page() i = 0 page = 0 tx, ty = -1, 0 x0, y0 = margins.left, margins.top x1, y1 = x0 + nx * total.width, y0 + ny * total.height if self.clip: all_frames = self.clip.iter_frames() elif self.frames: all_frames = AnimatedGif(self.im) else: all_frames = [] for f in all_frames: ready = float(i + 1) / self.frame_count if self.verbosity: sys.stdout.write('\rProcessing frames |{:30}| {}%' .format('X' * int(30 * ready), int(100 * ready))) sys.stdout.flush() tx += 1 if type(f) == GifImagePlugin.GifImageFile: f.putpalette(self.palette) self.last_im.paste(f) im = self.last_im.convert('RGBA') else: im = Image.fromarray(f) im.thumbnail(frame.to_tuple()) if tx == nx: tx = 0 ty += 1 if ty == ny: ty = 0 draw_raster() pdf.add_page() page += 1 temp_file = 'tmp-{}-{}-{}.jpg'.format(page, tx, ty) im.save(temp_file) tmp_files.append(temp_file) x = x0 + tx * total.width y = y0 + ty * total.height pdf.image(temp_file, x=x + offset, y=y, w=frame_mm.width, h=frame_mm.height) text = Point(x, y + frame_mm.height - 2) if offset > 0: pdf.rotate(90, text.x, text.y) pdf.text(text.x, text.y + 5, '{}'.format(i)) pdf.rotate(0) i += 1 if y != 0 and x != 0: draw_raster() if self.verbosity > 0: print '\nGenerating PDF ...' pdf.output(name=output_file_name) if self.verbosity > 0: print 'Removing temporary files ...' for temp_file in tmp_files: os.remove(temp_file)
def to_pdf(self, **kwargs): from fpdf import FPDF import random paper_format = kwargs.get('paper_format', 'a4') paper = self.PAPER_SIZES[string.lower(paper_format)] font_scale = kwargs.get('font_scale', 1) font_name = kwargs.get('font_name') colorize = kwargs.get('colorize', False) if font_name is not None and not colorize: self.generate_luminosity_mapping(font_name) orientation = kwargs.get('orientation') if self.im.width > self.im.height: orientation = 'l' else: orientation = 'p' if orientation == 'l': paper.width, paper.height = paper.height, paper.width inner = Size(ceil(paper.width - self.margins.left - self.margins.right), ceil(paper.height - self.margins.top - self.margins.bottom)) imgpixels = Size(self.im.width, self.im.height) scale = min(inner.width, inner.height) / max(imgpixels.width, imgpixels.height) offset = Point(self.margins.left + (inner.width - imgpixels.width * scale) / 2, self.margins.bottom + (inner.height - imgpixels.height * scale) / 2) pdf = FPDF(unit='mm', format=paper_format.upper(), orientation=orientation.upper()) pdf.set_compression(True) pdf.set_title('ASCII Art') pdf.set_author('Oliver Lau <*****@*****.**> - Heise Medien GmbH & Co. KG') pdf.set_creator('asciifier') pdf.set_keywords('retro computing art fun') pdf.add_page() if font_name is not None: pdf.add_font(font_name, fname=font_name, uni=True) else: font_name = 'Courier' pdf.set_font(font_name, '', mm2pt(scale * font_scale)) for y in range(0, self.im.height): yy = offset.y + scale * y for x in range(0, self.im.width): c = self.result[x][y] if c != ' ': if colorize is True: r, g, b = self.im.getpixel((x, y)) pdf.set_text_color(r, g, b) pdf.text(offset.x + x * scale, yy, random.choice(Asciifier.COLOR_CHARS)) else: pdf.text(offset.x + x * scale, yy, c) crop_area = Margin(offset.y - scale, offset.x + (self.im.width - 1 + font_scale) * scale, offset.y + (self.im.height - 2 + font_scale) * scale, offset.x) if kwargs.get('cropmarks', False): pdf.set_draw_color(0, 0, 0) pdf.set_line_width(pt2mm(0.1)) for p in [Point(crop_area.left, crop_area.top), Point(crop_area.right, crop_area.top), Point(crop_area.right, crop_area.bottom), Point(crop_area.left, crop_area.bottom)]: pdf.line(p.x - 6, p.y, p.x - 2, p.y) pdf.line(p.x + 2, p.y, p.x + 6, p.y) pdf.line(p.x, p.y - 6, p.x, p.y - 2) pdf.line(p.x, p.y + 2, p.x, p.y + 6) if kwargs.get('logo'): logo_width = 20 pdf.image(kwargs.get('logo'), x=(crop_area.right - crop_area.left - logo_width / 2) / 2, y=crop_area.bottom + 10, w=logo_width) return pdf.output(dest='S')
def to_pdf(self, **kwargs): from fpdf import FPDF import random paper_format = kwargs.get('paper_format', 'a4') paper = self.PAPER_SIZES[string.lower(paper_format)] font_scale = kwargs.get('font_scale', 1) font_name = kwargs.get('font_name') colorize = kwargs.get('colorize', False) if font_name is not None and not colorize: self.generate_luminosity_mapping(font_name) orientation = kwargs.get('orientation') if self.im.width > self.im.height: orientation = 'l' else: orientation = 'p' if orientation == 'l': paper.width, paper.height = paper.height, paper.width inner = Size( ceil(paper.width - self.margins.left - self.margins.right), ceil(paper.height - self.margins.top - self.margins.bottom)) imgpixels = Size(self.im.width, self.im.height) scale = min(inner.width, inner.height) / max(imgpixels.width, imgpixels.height) offset = Point( self.margins.left + (inner.width - imgpixels.width * scale) / 2, self.margins.bottom + (inner.height - imgpixels.height * scale) / 2) pdf = FPDF(unit='mm', format=paper_format.upper(), orientation=orientation.upper()) pdf.set_compression(True) pdf.set_title('ASCII Art') pdf.set_author('Oliver Lau <*****@*****.**> - Heise Medien GmbH & Co. KG') pdf.set_creator('asciifier') pdf.set_keywords('retro computing art fun') pdf.add_page() if font_name is not None: pdf.add_font(font_name, fname=font_name, uni=True) else: font_name = 'Courier' pdf.set_font(font_name, '', mm2pt(scale * font_scale)) for y in range(0, self.im.height): yy = offset.y + scale * y for x in range(0, self.im.width): c = self.result[x][y] if c != ' ': if colorize is True: r, g, b = self.im.getpixel((x, y)) pdf.set_text_color(r, g, b) pdf.text(offset.x + x * scale, yy, random.choice(Asciifier.COLOR_CHARS)) else: pdf.text(offset.x + x * scale, yy, c) crop_area = Margin( offset.y - scale, offset.x + (self.im.width - 1 + font_scale) * scale, offset.y + (self.im.height - 2 + font_scale) * scale, offset.x) if kwargs.get('cropmarks', False): pdf.set_draw_color(0, 0, 0) pdf.set_line_width(pt2mm(0.1)) for p in [ Point(crop_area.left, crop_area.top), Point(crop_area.right, crop_area.top), Point(crop_area.right, crop_area.bottom), Point(crop_area.left, crop_area.bottom) ]: pdf.line(p.x - 6, p.y, p.x - 2, p.y) pdf.line(p.x + 2, p.y, p.x + 6, p.y) pdf.line(p.x, p.y - 6, p.x, p.y - 2) pdf.line(p.x, p.y + 2, p.x, p.y + 6) if kwargs.get('logo'): logo_width = 20 pdf.image(kwargs.get('logo'), x=(crop_area.right - crop_area.left - logo_width / 2) / 2, y=crop_area.bottom + 10, w=logo_width) return pdf.output(dest='S')
def process( self, output_file_name=None, dpi=150, offset=0, fps=10, height_mm=50, margins=Margin(10, 10, 10, 10), paper_format="a4", ): def draw_raster(): for ix in range(0, nx + 1): xx = x0 + ix * total.width pdf.line(xx, y0, xx, y1) if offset > 0 and ix != nx: pdf.line(xx + offset, y0, xx + offset, y1) for iy in range(0, ny + 1): yy = y0 + iy * total.height pdf.line(x0, yy, x1, yy) height_mm = float(height_mm) tmp_files = [] if self.clip: if fps != self.clip.fps: if self.verbosity > 0: print "Transcoding from {} fps to {} fps ...".format(self.clip.fps, fps) self.clip.write_videofile("tmp.mp4", fps=fps, audio=False) tmp_files.append("tmp.mp4") self.clip = VideoFileClip("tmp.mp4") self.fps = self.clip.fps self.frame_count = int(self.clip.duration * self.fps) clip_size = Size.from_tuple(self.clip.size) elif self.frames: clip_size = Size.from_tuple(self.im.size) paper = self.PAPER_SIZES[paper_format.lower()] printable_area = Size(paper.width - margins.left - margins.right, paper.height - margins.top - margins.bottom) frame_mm = Size(height_mm / clip_size.height * clip_size.width, height_mm) total = Size(offset + frame_mm.width, frame_mm.height) frame = Size(int(frame_mm.width / 25.4 * dpi), int(frame_mm.height / 25.4 * dpi)) nx = int(printable_area.width / total.width) ny = int(printable_area.height / total.height) if self.verbosity > 0: print "Input: {} fps, {}x{}, {} frames" "\n from: {}".format( self.fps, clip_size.width, clip_size.height, self.frame_count, self.input_file_name ) print "Output: {}dpi, {}x{}, {:.2f}mm x {:.2f}mm, {}x{} tiles" "\n to: {}".format( dpi, frame.width, frame.height, frame_mm.width, frame_mm.height, nx, ny, output_file_name ) pdf = FPDF(unit="mm", format=paper_format.upper(), orientation="L") pdf.set_compression(True) pdf.set_title("Funny video") pdf.set_author("Oliver Lau <*****@*****.**> - Heise Medien GmbH & Co. KG") pdf.set_creator("flippy") pdf.set_keywords("flip-book, video, animated GIF") pdf.set_draw_color(128, 128, 128) pdf.set_line_width(0.1) pdf.set_font("Helvetica", "", 12) pdf.add_page() i = 0 page = 0 tx, ty = -1, 0 x0, y0 = margins.left, margins.top x1, y1 = x0 + nx * total.width, y0 + ny * total.height if self.clip: all_frames = self.clip.iter_frames() elif self.frames: all_frames = AnimatedGif(self.im) else: all_frames = [] for f in all_frames: ready = float(i + 1) / self.frame_count if self.verbosity: sys.stdout.write("\rProcessing frames |{:30}| {}%".format("X" * int(30 * ready), int(100 * ready))) sys.stdout.flush() tx += 1 if type(f) == GifImagePlugin.GifImageFile: f.putpalette(self.palette) self.last_im.paste(f) im = self.last_im.convert("RGBA") else: im = Image.fromarray(f) im.thumbnail(frame.to_tuple()) if tx == nx: tx = 0 ty += 1 if ty == ny: ty = 0 draw_raster() pdf.add_page() page += 1 temp_file = "tmp-{}-{}-{}.jpg".format(page, tx, ty) im.save(temp_file) tmp_files.append(temp_file) x = x0 + tx * total.width y = y0 + ty * total.height pdf.image(temp_file, x=x + offset, y=y, w=frame_mm.width, h=frame_mm.height) text = Point(x, y + frame_mm.height - 2) if offset > 0: pdf.rotate(90, text.x, text.y) pdf.text(text.x, text.y + 5, "{}".format(i)) pdf.rotate(0) i += 1 if y != 0 and x != 0: draw_raster() if self.verbosity > 0: print "\nGenerating PDF ..." pdf.output(name=output_file_name) if self.verbosity > 0: print "Removing temporary files ..." for temp_file in tmp_files: os.remove(temp_file)