luametalatex/luametalatex-pdf-image-pdf.lua

117 lines
3.4 KiB
Lua

local box_fallback = {
BleedBox = "CropBox",
TrimBox = "CropBox",
ArtBox = "CropBox",
CropBox = "MediaBox",
}
local boxmap = {
media = "MediaBox",
crop = "CropBox",
bleed = "BleedBox",
trim = "TrimBox",
art = "ArtBox",
}
local utils = require'luametalatex-pdf-utils'
local strip_floats = utils.strip_floats
local to_sp = utils.to_sp
local to_bp = utils.to_bp
local function get_box(page, box)
box = boxmap[box]
while box do
local found = pdfe.getbox(page, box)
if found then
return {to_sp(found[1]), to_sp(found[2]), to_sp(found[3]), to_sp(found[4])}
end
box = box_fallback[box]
end
end
local pdf_functions = {}
local function open_pdfe(img, f)
local file
if f and f.file then
file = pdfe.openfile(f.file)
f.file = nil
elseif img.filedata then
file = pdfe.new(img.filedata, #img.filedata)
elseif img.filepath then
file = pdfe.open(img.filepath)
end
do
local userpassword = img.userpassword
local ownerpassword = img.ownerpassword
if userpassword or ownerpassword then
pdfe.unencrypt(file, userpassword, ownerpassword)
end
end
local status = pdfe.getstatus(file)
if status >= 0 then
return file
elseif status == -1 then
error[[PDF image is encrypted. Please provide the decryption key.]]
elseif status == -2 then
error[[PDF image could not be opened.]]
else
assert(false)
end
end
function pdf_functions.scan(img, f)
local file = open_pdfe(img, f)
img.pages = pdfe.getnofpages(file)
img.page = img.page or 1
if img.page > img.pages then
error[[Not enough pages in PDF image]]
end
local page = pdfe.getpage(file, img.page)
local bbox = img.bbox or get_box(page, img.pagebox or 'crop') or {0, 0, 0, 0}
img.bbox = bbox
img.rotation = (360 - (page.Rotate or 0)) % 360
assert(img.rotation % 90 == 0, "Invalid /Rotate")
img.rotation = img.rotation / 90
if img.rotation < 0 then img.rotation = img.rotation + 4 end
img.xsize = bbox[3] - bbox[1]
img.ysize = bbox[4] - bbox[2]
img.xres, img.yres = nil, nil
end
local pdfe_deepcopy = require'luametalatex-pdfe-deepcopy'
function pdf_functions.write(pfile, img)
local file = open_pdfe(img)
local page = pdfe.getpage(file, img.page)
local bbox = img.bbox
local dict = strip_floats(string.format("/Subtype/Form/BBox[%f %f %f %f]/Resources ", to_bp(bbox[1]), to_bp(bbox[2]), to_bp(bbox[3]), to_bp(bbox[4])))
dict = dict .. pdfe_deepcopy(file, img.filepath, pfile, pdfe.getfromdictionary(page, 'Resources'))
local content, raw = page.Contents
-- Three cases: Contents is a stream, so copy the stream (Remember to copy filter if necessary)
-- Contents is an array of streams, so append all the streams as a new stream
-- Contents is missing. Then create an empty stream.
local type = pdfe.type(content)
if type == 'pdfe.stream' then
raw = true
for i=1,#content do
local key, type, value, detail = pdfe.getfromstream(content, i)
dict = dict .. pdfe_deepcopy(file, img.filepath, pfile, 5, key) .. ' ' .. pdfe_deepcopy(file, img.filepath, pfile, type, value, detail)
end
content = content(false)
elseif type == 'pdfe.array' then
local array = content
content = ''
for i=1,#array do
content = content .. array[i](true)
end
else
content = ''
end
local attr = img.attr
if attr then
dict = dict .. attr
end
pfile:stream(img.objnum, dict, content, nil, raw)
end
return pdf_functions