Skip to content

Commit

Permalink
PyDviPng cleanup, added diff-image and run-and-compare
Browse files Browse the repository at this point in the history
  • Loading branch information
FabriceSalvaire committed Sep 22, 2014
1 parent ac384d8 commit 43e82a7
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 53 deletions.
3 changes: 3 additions & 0 deletions PyDvi/TeXUnit.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@

####################################################################################################

# x_in_y means number of x corresponding to 1 y

# 1 in = 72 bp
big_point_in_inch = 72
# 1 cc = 12 dd
Expand All @@ -74,6 +76,7 @@
inch_in_mm = 1 / mm_in_inch
point_in_mm = point_in_inch * inch_in_mm
inch_in_point = 1 / point_in_inch

mm_in_point = 1 / point_in_mm
pt_in_sp = fractions.Fraction(1, scaled_point_in_point)

Expand Down
79 changes: 42 additions & 37 deletions PyDviPng/DviMachine.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,13 @@

import logging

import numpy as np

from PIL import Image, ImageDraw

####################################################################################################

from PyDvi.Dvi.DviMachine import DviMachine, DviSimplifyMachine
from PyDvi.Font.PkFont import PkFont
from PyDvi.Font.Type1Font import Type1Font
from PyDvi.Dvi.DviMachine import DviSimplifyMachine
from PyDvi.TeXUnit import *
from PyDvi.Tools.Interval import Interval2D

####################################################################################################

Expand All @@ -56,10 +53,13 @@ def __init__(self, font_manager):

##############################################

def begin_run_page(self, png_path, dpi):
def begin_run_page(self, png_path, dpi, tight=False):

self._dpi = dpi
self._png_path = png_path
self._dpi = dpi
self._tight = tight

self._sp_to_px = self._dpi * sp2in(1)

program = self.current_opcode_program

Expand All @@ -72,36 +72,51 @@ def begin_run_page(self, png_path, dpi):
self._logger.warning('Page size is null')
width, height = 210, 297 # use A4

width_px = self.mm_to_px(width)
height_px = self.mm_to_px(height)
width_px = self.mm2px(width)
height_px = self.mm2px(height)

self._logger.info("Image dimension (width, height) = ({},{})".format(width_px, height_px))

self._image = Image.new('RGB', (width_px, height_px), color=(255, 255, 255))
self._draw = ImageDraw.Draw(self._image)

self._bounding_box = None

##############################################

def end_run_page(self):

self._image.save(self._png_path)
if self._tight:
image = self._image.crop(self._bounding_box.bounding_box())
else:
image = self._image
image.save(self._png_path)

##############################################

def mm_to_px(self, x):
# Fixme: better unit ?
def mm2px(self, x):
return rint(mm2in(x)*self._dpi)

##############################################

def sp2px(self, x):
return rint(self._sp_to_px * x)

##############################################

def paint_rule(self, x, y, w, h):

# self._logger.info("\nrule ({}, {}) +({}, {})".format(x, y, w, h))
x_mm, y_mm, w_mm, h_mm = [sp2mm(z) for z in (x, y, w, h)]

self._draw.rectangle([self.mm_to_px(x) for x in (x_mm, y_mm - h_mm, x_mm + w_mm, y_mm)],
x0, y0, x1, y1 = [self.sp2px(x) for x in (x, y - h, x + w, y)]
self._draw.rectangle((x0, y0, x1, y1),
fill=self.current_colour.colour)

rule_bounding_box = Interval2D([x0, x1], [y0, y1])
if self._bounding_box is None:
self._bounding_box = rule_bounding_box
else:
self._bounding_box |= rule_bounding_box

##############################################

def paint_char(self, xg, yg, char_bounding_box, font, dvi_font, glyph_index):
Expand All @@ -120,32 +135,22 @@ def paint_char(self, xg, yg, char_bounding_box, font, dvi_font, glyph_index):
size = dvi_font.magnification * sp2pt(dvi_font.design_size) # pt

glyph = font.get_glyph(glyph_index, size, resolution=self._dpi)
glyph_bitmap = -(glyph.glyph_bitmap - 255)
height_px, width_px = glyph_bitmap.shape[:2] # depth
glyph_bitmap = 255 - glyph.glyph_bitmap # inverse: paint black on white
height, width = glyph_bitmap.shape[:2] # depth

xg_mm = sp2mm(xg) + glyph.px_to_mm(glyph.offset[0])
yg_mm = sp2mm(yg) + glyph.px_to_mm(glyph.size[1] - glyph.offset[1]) # offset = top - origin
# width = glyph.px_to_mm(glyph.size[0])
# height = glyph.px_to_mm(glyph.size[1])
x = self.sp2px(xg) + glyph.offset[0]
y = self.sp2px(yg) + glyph.size[1] - glyph.offset[1] # offset = top - origin

x_px = self.mm_to_px(xg_mm)
y_px = self.mm_to_px(yg_mm)
x0, y0, x1, y1 = [x, y - height, x + width, y]

glyph_image = Image.fromarray(glyph_bitmap)
self._image.paste(glyph_image, [x_px, y_px - height_px, x_px + width_px, y_px])

# x_mm = sp2mm(char_bounding_box.x.inf)
# y_mm = sp2mm(char_bounding_box.y.inf)
# box_width = sp2mm(char_bounding_box.x.length())
# box_height = sp2mm(char_bounding_box.y.length())
# y_mm -= box_height

# glyph_index = self._glyph_indexes[font_id]
# positions, bounding_boxes, texture_coordinates, colours = self.glyphs[font_id]
# positions[glyph_index] = xg_mm, yg_mm, width, height
# bounding_boxes[glyph_index] = x_mm, y_mm, box_width, box_height
# texture_coordinates[glyph_index] = glyph.texture_coordinates
# colours[glyph_index] = self.current_colour.colour
self._image.paste(glyph_image, (x0, y0, x1, y1))

char_bounding_box = Interval2D([x0, x1], [y0, y1])
if self._bounding_box is None:
self._bounding_box = char_bounding_box
else:
self._bounding_box |= char_bounding_box

####################################################################################################
#
Expand Down
4 changes: 2 additions & 2 deletions PyDviPng/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ def process_dvi_stream(self, dvi_path):

##############################################

def run_page(self, png_path, page_index=0, dpi=100):
def run_page(self, png_path, page_index=0, dpi=100, tight=False):

if page_index >= 0 and page_index < self.number_of_pages:
self._logger.info("Run page: {}".format(page_index))
# page_bounding_box = self._dvi_machine.compute_page_bounding_box(page_index)
program_page = self._dvi_machine.dvi_program[page_index] # Fixme: simplify
self._dvi_machine.process_page_xxx_opcodes(program_page)
self._dvi_machine.run_page(page_index, dpi=dpi, png_path=png_path)
self._dvi_machine.run_page(page_index, dpi=dpi, png_path=png_path, tight=tight)

####################################################################################################
#
Expand Down
94 changes: 94 additions & 0 deletions bin/diff-image
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#! /usr/bin/env python
# -*- python -*-

####################################################################################################
#
# PyDvi - A Python Library to Process DVI Stream
# Copyright (C) 2014 Fabrice Salvaire
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
####################################################################################################

####################################################################################################

import argparse

import numpy as np

from PIL import Image

####################################################################################################
#
# Options
#

parser = argparse.ArgumentParser(description='Diff PNG image.')

parser.add_argument('png_file1', metavar='FILE1.png',
help='PNG File 1')

parser.add_argument('png_file2', metavar='FILE2.png',
help='PNG File 2')

parser.add_argument('diff_file', metavar='DIFF.png',
help='Diff PNG File')

args = parser.parse_args()

####################################################################################################

image1 = Image.open(args.png_file1)
image2 = Image.open(args.png_file2)

buffer1 = np.array(image1)
buffer2 = np.array(image2)

dimensions1 = buffer1.shape
dimensions2 = buffer2.shape

if dimensions1 != dimensions2:
print "Shape mismatch {} versus {}".format(dimensions1, dimensions2)
height1, width1, depth1 = dimensions1
height2, width2, depth2 = dimensions2
if depth1 != depth2:
raise NameError("Depth don't match")
depth = depth1
height = min(height1, height2)
width = min(width1, width2)
buffer1_ = buffer1
buffer2_ = buffer2
buffer1 = np.zeros((height, width, depth), dtype=np.uint8)
buffer2 = np.zeros((height, width, depth), dtype=np.uint8)
buffer1 = buffer1_[:height,:width]
buffer2 = buffer2_[:height,:width]
else:
height, width, depth = dimensions1

diff_buffer = np.zeros((height, width, depth), dtype=np.uint8)
diff_buffer[:,:,0] = (buffer1 - buffer2)[:,:,0]
diff_buffer[:,:,1] = (buffer2 - buffer1)[:,:,1]
# diff_buffer = np.abs(buffer1 - buffer2)
# diff_buffer = np.xor(buffer1, buffer2)

mode = 'RGB'
size = width, height
diff_image = Image.frombuffer(mode, size, diff_buffer, 'raw', mode, 0, 1)
diff_image.save(args.diff_file)

####################################################################################################
#
# End
#
####################################################################################################
12 changes: 8 additions & 4 deletions bin/dvi-to-png
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,24 @@ parser.add_argument('png_file', metavar='FILE.png',
help='PNG File')

parser.add_argument('--page',
type=int, default=0,
help='page')
type=int, default=1,
help='page index from 1')

parser.add_argument('--dpi',
type=int, default=300,
help='resolution')
help='resolution in dpi')

parser.add_argument('--tight',
action='store_true', default=False,
help='crop the page to the bounding box')

args = parser.parse_args()

####################################################################################################

dvi_png = DviPng()
dvi_png.process_dvi_stream(args.dvi_file)
dvi_png.run_page(args.png_file, args.page, args.dpi)
dvi_png.run_page(args.png_file, args.page -1, args.dpi, args.tight)

####################################################################################################
#
Expand Down
49 changes: 49 additions & 0 deletions bin/run-and-compare
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#! /bin/bash

####################################################################################################
#
# PyDvi - A Python Library to Process DVI Stream
# Copyright (C) 2014 Fabrice Salvaire
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
####################################################################################################

####################################################################################################

root_dir=`realpath $0`
root_dir=`dirname ${root_dir}`
root_dir=`dirname ${root_dir}`

dvi_file=`realpath $1`
dpi=600

tmp_dir=`mktemp -d`
pushd ${tmp_dir}

dvipng --truecolor -D ${dpi} -T tight ${dvi_file} -o out-ref.png
${root_dir}/bin/dvi-to-png --tight --dpi=${dpi} ${dvi_file} out.png
${root_dir}/bin/diff-image out-ref.png out.png diff.png

geeqie diff.png

rm -rf *.png
popd
rmdir ${tmp_dir}

####################################################################################################
#
# End
#
####################################################################################################
20 changes: 10 additions & 10 deletions test/test-dvi-machine
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,16 @@ print
dvi_program.print_summary()

dvi_machine.load_dvi_program(dvi_program)
print line
dvi_program[0].print_program()
print line
dvi_machine.simplify_dvi_program()
print line
dvi_program[0].print_program()
print line

print 'Compute bounding box of the first page:'
dvi_machine.compute_page_bounding_box(0)
# print line
# dvi_program[0].print_program()
# print line
# dvi_machine.simplify_dvi_program()
# print line
# dvi_program[0].print_program()
# print line

# print 'Compute bounding box of the first page:'
# dvi_machine.compute_page_bounding_box(0)

print line
print 'Run the first page:'
Expand Down

0 comments on commit 43e82a7

Please sign in to comment.