diff options
author | Hans Hagen <pragma@wxs.nl> | 2018-12-17 18:19:48 +0100 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2018-12-17 18:19:48 +0100 |
commit | 15b67b20aa0d6c508578d0ca8cbdcd9cff9829a8 (patch) | |
tree | d656b4161487a8c54d954458084914c7d408aca7 /tex/context/base/mkiv/grph-img.lua | |
parent | 5bb786877a5617fb8fbe3fd0e7b54fbcea3ce002 (diff) | |
download | context-15b67b20aa0d6c508578d0ca8cbdcd9cff9829a8.tar.gz |
2018-12-17 16:49:00
Diffstat (limited to 'tex/context/base/mkiv/grph-img.lua')
-rw-r--r-- | tex/context/base/mkiv/grph-img.lua | 746 |
1 files changed, 0 insertions, 746 deletions
diff --git a/tex/context/base/mkiv/grph-img.lua b/tex/context/base/mkiv/grph-img.lua deleted file mode 100644 index c76733cbf..000000000 --- a/tex/context/base/mkiv/grph-img.lua +++ /dev/null @@ -1,746 +0,0 @@ -if not modules then modules = { } end modules ['grph-img'] = { - version = 1.001, - comment = "companion to grph-inc.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- The jpg identification and inclusion code is based on the code in \LUATEX\ but as we --- use \LUA\ we can do it a bit cleaner. We can also use some helpers for reading from --- file. We could make it even more lean and mean. When all works out ok I will clean --- up this code a bit as we can divert more from luatex. - -local lower, strip = string.lower, string.strip -local round = math.round -local concat = table.concat -local suffixonly = file.suffix - -local files = utilities.files -local getsize = files.getsize -local readbyte = files.readbyte -local readstring = files.readstring -local readcardinal = files.readcardinal -local readcardinal2 = files.readcardinal2 -local readcardinal4 = files.readcardinal4 -local readcardinal2le = files.readcardinal2le -local readcardinal4le = files.readcardinal4le -local skipbytes = files.skip -local setposition = files.setposition -local getposition = files.getposition - -local setmetatableindex = table.setmetatableindex -local setmetatablecall = table.setmetatablecall - -local lpdf = lpdf or { } -local pdfmajorversion = lpdf.majorversion -local pdfminorversion = lpdf.minorversion - -local graphics = graphics or { } -local identifiers = { } -graphics.identifiers = identifiers - -do - - local colorspaces = { - [1] = 1, -- gray - [3] = 2, -- rgb - [4] = 3, -- cmyk - } - - local tags = { - [0xC0] = { name = "SOF0", }, -- baseline DCT - [0xC1] = { name = "SOF1", }, -- extended sequential DCT - [0xC2] = { name = "SOF2", }, -- progressive DCT - [0xC3] = { name = "SOF3", supported = false }, -- lossless (sequential) - - [0xC5] = { name = "SOF5", supported = false }, -- differential sequential DCT - [0xC6] = { name = "SOF6", supported = false }, -- differential progressive DCT - [0xC7] = { name = "SOF7", supported = false }, -- differential lossless (sequential) - - [0xC8] = { name = "JPG", }, -- reserved for JPEG extensions - [0xC9] = { name = "SOF9", }, -- extended sequential DCT - [0xCA] = { name = "SOF10", supported = false }, -- progressive DCT - [0xCB] = { name = "SOF11", supported = false }, -- lossless (sequential) - - [0xCD] = { name = "SOF13", supported = false }, -- differential sequential DCT - [0xCE] = { name = "SOF14", supported = false }, -- differential progressive DCT - [0xCF] = { name = "SOF15", supported = false }, -- differential lossless (sequential) - - [0xC4] = { name = "DHT" }, -- define Huffman table(s) - - [0xCC] = { name = "DAC" }, -- define arithmetic conditioning table - - [0xD0] = { name = "RST0", zerolength = true }, -- restart - [0xD1] = { name = "RST1", zerolength = true }, -- restart - [0xD2] = { name = "RST2", zerolength = true }, -- restart - [0xD3] = { name = "RST3", zerolength = true }, -- restart - [0xD4] = { name = "RST4", zerolength = true }, -- restart - [0xD5] = { name = "RST5", zerolength = true }, -- restart - [0xD6] = { name = "RST6", zerolength = true }, -- restart - [0xD7] = { name = "RST7", zerolength = true }, -- restart - - [0xD8] = { name = "SOI", zerolength = true }, -- start of image - [0xD9] = { name = "EOI", zerolength = true }, -- end of image - [0xDA] = { name = "SOS" }, -- start of scan - [0xDB] = { name = "DQT" }, -- define quantization tables - [0xDC] = { name = "DNL" }, -- define number of lines - [0xDD] = { name = "DRI" }, -- define restart interval - [0xDE] = { name = "DHP" }, -- define hierarchical progression - [0xDF] = { name = "EXP" }, -- expand reference image(s) - - [0xE0] = { name = "APP0" }, -- application marker, used for JFIF - [0xE1] = { name = "APP1" }, -- application marker - [0xE2] = { name = "APP2" }, -- application marker - [0xE3] = { name = "APP3" }, -- application marker - [0xE4] = { name = "APP4" }, -- application marker - [0xE5] = { name = "APP5" }, -- application marker - [0xE6] = { name = "APP6" }, -- application marker - [0xE7] = { name = "APP7" }, -- application marker - [0xE8] = { name = "APP8" }, -- application marker - [0xE9] = { name = "APP9" }, -- application marker - [0xEA] = { name = "APP10" }, -- application marker - [0xEB] = { name = "APP11" }, -- application marker - [0xEC] = { name = "APP12" }, -- application marker - [0xED] = { name = "APP13" }, -- application marker - [0xEE] = { name = "APP14" }, -- application marker, used by Adobe - [0xEF] = { name = "APP15" }, -- application marker - - [0xF0] = { name = "JPG0" }, -- reserved for JPEG extensions - [0xFD] = { name = "JPG13" }, -- reserved for JPEG extensions - [0xFE] = { name = "COM" }, -- comment - - [0x01] = { name = "TEM", zerolength = true }, -- temporary use - } - - -- More can be found in http://www.exif.org/Exif2-2.PDF but basically we have - -- good old tiff tags here. - - local function read_APP1_Exif(f, xres, yres, orientation) -- untested - local position = false - local readcardinal2 = readcardinal2 - local readcardinal4 = readcardinal4 - -- endian II|MM - while true do - position = getposition(f) - local b = readbyte(f) - if b == 0 then - -- next one - elseif b == 0x4D and readbyte(f) == 0x4D then -- M - -- big endian - break - elseif b == 0x49 and readbyte(f) == 0x49 then -- I - -- little endian - readcardinal2 = readcardinal2le - readcardinal4 = readcardinal4le - break - else - -- warning "bad exif data" - return xres, yres, orientation - end - end - -- version - local version = readcardinal2(f) - if version ~= 42 then - return xres, yres, orientation - end - -- offset to records - local offset = readcardinal4(f) - if not offset then - return xres, yres, orientation - end - setposition(f,position + offset) - local entries = readcardinal2(f) - if not entries or entries == 0 then - return xres, yres, orientation - end - local x_res, y_res, x_res_ms, y_res_ms, x_temp, y_temp - local res_unit, res_unit_ms - for i=1,entries do - local tag = readcardinal2(f) - local kind = readcardinal2(f) - local size = readcardinal4(f) - local value = 0 - local num = 0 - local den = 0 - if kind == 1 or kind == 7 then -- byte | undefined - value = readbyte(f) - skipbytes(f,3) - elseif kind == 3 or kind == 8 then -- (un)signed short - value = readcardinal2(f) - skipbytes(f,2) - elseif kind == 4 or kind == 9 then -- (un)signed long - value = readcardinal4(f) - elseif kind == 5 or kind == 10 then -- (s)rational - local offset = readcardinal4(f) - local saved = getposition(f) - setposition(f,position+offset) - num = readcardinal4(f) - den = readcardinal4(f) - setposition(f,saved) - else -- 2 -- ascii - skipbytes(f,4) - end - if tag == 274 then -- orientation - orientation = value - elseif tag == 282 then -- x resolution - if den ~= 0 then - x_res = num/den - end - elseif tag == 283 then -- y resolution - if den ~= 0 then - y_res = num/den - end - elseif tag == 296 then -- resolution unit - if value == 2 then - res_unit = 1 - elseif value == 3 then - res_unit = 2.54 - end - elseif tag == 0x5110 then -- pixel unit - res_unit_ms = value == 1 - elseif tag == 0x5111 then -- x pixels per unit - x_res_ms = value - elseif tag == 0x5112 then -- y pixels per unit - y_res_ms = value - end - end - if x_res and y_res and res_unit and res_unit > 0 then - x_temp = round(x_res * res_unit) - y_temp = round(y_res * res_unit) - elseif x_res_ms and y_res_ms and res_unit_ms then - x_temp = round(x_res_ms * 0.0254) -- in meters - y_temp = round(y_res_ms * 0.0254) -- in meters - end - if x_temp and a_temp and x_temp > 0 and y_temp > 0 then - if (x_temp ~= x_res or y_temp ~= y_res) and x_res ~= 0 and y_res ~= 0 then - -- exif resolution differs from already found resolution - elseif x_temp == 1 or y_temp == 1 then - -- exif resolution is kind of weird - else - return x_temp, y_temp, orientation - end - end - return round(xres), round(yres), orientation - end - - function identifiers.jpg(filename) - local specification = { - filename = filename, - filetype = "jpg", - } - if not filename or filename == "" then - specification.error = "invalid filename" - return specification -- error - end - local f = io.open(filename,"rb") - if not f then - specification.error = "unable to open file" - return specification -- error - end - specification.xres = 0 - specification.yres = 0 - specification.orientation = 1 - specification.totalpages = 1 - specification.pagenum = 1 - specification.length = 0 - local banner = readcardinal2(f) - if banner ~= 0xFFD8 then - specification.error = "no jpeg file" - return specification -- error - end - local xres = 0 - local yres = 0 - local orientation = 1 - local okay = false - local filesize = getsize(f) -- seek end - local majorversion = pdfmajorversion and pdfmajorversion() or 2 - local minorversion = pdfminorversion and pdfminorversion() or 2 - while getposition(f) < filesize do - local b = readbyte(f) - if not b then - break - elseif b ~= 0xFF then - if not okay then - -- or check for size - specification.error = "incomplete file" - end - break - end - local category = readbyte(f) - local position = getposition(f) - local length = 0 - local tagdata = tags[category] - if not tagdata then - specification.error = "invalid tag" - break - elseif tagdata.supported == false then - specification.error = "unsupported " .. tagdata.comment - break - end - local name = tagdata.name - if name == "SOF2" then - if majorversion < 2 or minorversion <= 2 then - specification.error = "no progressive DCT in PDF <= 1.2" - break - end - elseif name == "SOF0" or name == "SOF1" then - length = readcardinal2(f) - specification.colordepth = readcardinal(f) - specification.ysize = readcardinal2(f) - specification.xsize = readcardinal2(f) - specification.colorspace = colorspaces[readcardinal(f)] - if not specification.colorspace then - specification.error = "unsupported color space" - break - end - okay = true - elseif name == "APP0" then - length = readcardinal2(f) - if length > 6 then - local format = readstring(f,5) - if format == "JFIF\000" then - skipbytes(f,2) - units = readcardinal(f) - xres = readcardinal2(f) - yres = readcardinal2(f) - if units == 1 then - -- pixels per inch - if xres == 1 or yres == 1 then - -- warning - end - elseif units == 2 then - -- pixels per cm */ - xres = xres * 2.54 - yres = yres * 2.54 - else - xres = 0 - yres = 0 - end - end - end - elseif name == "APP1" then - length = readcardinal2(f) - if length > 7 then - local format = readstring(f,5) - if format == "Exif\000" then - xres, yres, orientation = read_APP1_Exif(f,xres,yres,orientation) - end - end - elseif not tagdata.zerolength then - length = readcardinal2(f) - end - if length > 0 then - setposition(f,position+length) - end - end - f:close() - if not okay then - specification.error = "invalid file" - elseif not specification.error then - if xres == 0 and yres ~= 0 then - xres = yres - end - if yres == 0 and xres ~= 0 then - yres = xres - end - end - specification.xres = xres - specification.yres = yres - specification.orientation = orientation - specification.length = filesize - return specification - end - -end - -do - - local function read_boxhdr(specification,f) - local size = readcardinal4(f) - local kind = readstring(f,4) - if kind then - kind = strip(lower(kind)) - else - kind = "" - end - if size == 1 then - size = readcardinal4(f) * 0xFFFF0000 + readcardinal4(f) - end - if size == 0 and kind ~= "jp2c" then -- move this - specification.error = "invalid size" - end - return kind, size - end - - local function scan_ihdr(specification,f) - specification.ysize = readcardinal4(f) - specification.xsize = readcardinal4(f) - skipbytes(f,2) -- nc - specification.colordepth = readcardinal(f) + 1 - skipbytes(f,3) -- c unkc ipr - end - - local function scan_resc_resd(specification,f) - local vr_n = readcardinal2(f) - local vr_d = readcardinal2(f) - local hr_n = readcardinal2(f) - local hr_d = readcardinal2(f) - local vr_e = readcardinal(f) - local hr_e = readcardinal(f) - specification.xres = math.round((hr_n / hr_d) * math.exp(hr_e * math.log(10.0)) * 0.0254) - specification.yres = math.round((vr_n / vr_d) * math.exp(vr_e * math.log(10.0)) * 0.0254) - end - - local function scan_res(specification,f,last) - local pos = getposition(f) - while true do - local kind, size = read_boxhdr(specification,f) - pos = pos + size - if kind == "resc" then - if specification.xres == 0 and specification.yres == 0 then - scan_resc_resd(specification,f) - if getposition(f) ~= pos then - specification.error = "invalid resc" - return - end - end - elseif tpos == "resd" then - scan_resc_resd(specification,f) - if getposition(f) ~= pos then - specification.error = "invalid resd" - return - end - elseif pos > last then - specification.error = "invalid res" - return - elseif pos == last then - break - end - if specification.error then - break - end - setposition(f,pos) - end - end - - local function scan_jp2h(specification,f,last) - local okay = false - local pos = getposition(f) - while true do - local kind, size = read_boxhdr(specification,f) - pos = pos + size - if kind == "ihdr" then - scan_ihdr(specification,f) - if getposition(f) ~= pos then - specification.error = "invalid ihdr" - return false - end - okay = true - elseif kind == "res" then - scan_res(specification,f,pos) - elseif pos > last then - specification.error = "invalid jp2h" - return false - elseif pos == last then - break - end - if specification.error then - break - end - setposition(f,pos) - end - return okay - end - - function identifiers.jp2(filename) - local specification = { - filename = filename, - filetype = "jp2", - } - if not filename or filename == "" then - specification.error = "invalid filename" - return specification -- error - end - local f = io.open(filename,"rb") - if not f then - specification.error = "unable to open file" - return specification -- error - end - specification.xres = 0 - specification.yres = 0 - specification.orientation = 1 - specification.totalpages = 1 - specification.pagenum = 1 - specification.length = 0 - local xres = 0 - local yres = 0 - local orientation = 1 - local okay = false - local filesize = getsize(f) -- seek end - local majorversion = pdfmajorversion and pdfmajorversion() or 2 - local minorversion = pdfminorversion and pdfminorversion() or 2 - -- - local pos = 0 - -- signature - local kind, size = read_boxhdr(specification,f) - pos = pos + size - setposition(f,pos) - -- filetype - local kind, size = read_boxhdr(specification,f) - if kind ~= "ftyp" then - specification.error = "missing ftyp box" - return specification - end - pos = pos + size - setposition(f,pos) - while not okay do - local kind, size = read_boxhdr(specification,f) - pos = pos + size - if kind == "jp2h" then - okay = scan_jp2h(specification,f,pos) - elseif kind == "jp2c" and not okay then - specification.error = "no ihdr box found" - return specification - end - setposition(f,pos) - end - -- - f:close() - if not okay then - specification.error = "invalid file" - elseif not specification.error then - if xres == 0 and yres ~= 0 then - xres = yres - end - if yres == 0 and xres ~= 0 then - yres = xres - end - end - specification.xres = xres - specification.yres = yres - specification.orientation = orientation - specification.length = filesize - return specification - end - -end - -do - - -- 0 = gray "image b" - -- 2 = rgb "image c" - -- 3 = palette "image c" + "image i" - -- 4 = gray + alpha "image b" - -- 6 = rgb + alpha "image c" - - -- for i=1,length/3 do - -- palette[i] = readstring(f,3) - -- end - - local function grab(t,f,once) - if once then - for i=1,#t do - local l = t[i] - setposition(f,l.offset) - t[i] = readstring(f,l.length) - end - local data = concat(t) - return data - else - local data = { } - for i=1,#t do - local l = t[i] - setposition(f,l.offset) - data[i] = readstring(f,l.length) - end - return concat(data) - end - end - - function identifiers.png(filename) - local specification = { - filename = filename, - filetype = "png", - } - if not filename or filename == "" then - specification.error = "invalid filename" - return specification -- error - end - local f = io.open(filename,"rb") - if not f then - specification.error = "unable to open file" - return specification -- error - end - specification.xres = 0 - specification.yres = 0 - specification.orientation = 1 - specification.totalpages = 1 - specification.pagenum = 1 - specification.offset = 0 - specification.length = 0 - local filesize = getsize(f) -- seek end - local tables = { } - local banner = readstring(f,8) - if banner ~= "\137PNG\013\010\026\010" then - specification.error = "no png file" - return specification -- error - end - while true do - local position = getposition(f) - if position >= filesize then - break - end - local length = readcardinal4(f) - if not length then - break - end - local kind = readstring(f,4) - if kind then - kind = lower(kind) - else - break - end - if kind == "ihdr" then -- metadata - specification.xsize = readcardinal4(f) - specification.ysize = readcardinal4(f) - specification.colordepth = readcardinal(f) - specification.colorspace = readcardinal(f) - specification.compression = readcardinal(f) - specification.filter = readcardinal(f) - specification.interlace = readcardinal(f) - tables[kind] = true - elseif kind == "iend" then - tables[kind] = true - break - elseif kind == "phys" then - local x = readcardinal4(f) - local y = readcardinal4(f) - local u = readcardinal(f) - if u == 1 then -- meters - -- x = round(0.0254 * x) - -- y = round(0.0254 * y) - end - specification.xres = x - specification.yres = y - tables[kind] = true - elseif kind == "idat" or kind == "plte" or kind == "gama" or kind == "trns" then - local t = tables[kind] - if not t then - t = setmetatablecall(grab) - tables[kind] = t - end - t[#t+1] = { - offset = getposition(f), - length = length, - } - else - tables[kind] = true - end - setposition(f,position+length+12) -- #size #kind #crc - end - specification.tables = tables - return specification - end - -end - -do - - local function gray(t,k) - local v = 0 - t[k] = v - return v - end - - local function rgb(t,k) - local v = { 0, 0, 0 } - t[k] = v - return v - end - - local function cmyk(t,k) - local v = { 0, 0, 0, 0 } - t[k] = v - return v - end - - function identifiers.bitmap(specification) - local xsize = specification.xsize or 0 - local ysize = specification.ysize or 0 - local width = specification.width or xsize * 65536 - local height = specification.height or ysize * 65536 - local colordepth = specification.colordepth or 1 -- 1 .. 2 - local colorspace = specification.colorspace or 1 -- 1 .. 3 - local pixel = false - local data = specification.data - local mask = specification.mask - if colorspace == 1 or colorspace == "gray" then - pixel = gray - colorspace = 1 - elseif colorspace == 2 or colorspace == "rgb" then - pixel = rgb - colorspace = 2 - elseif colorspace == 3 or colorspace == "cmyk" then - pixel = cmyk - colorspace = 3 - else - return - end - if colordepth == 8 then - colordepth = 1 - elseif colordepth == 16 then - colordepth = 2 - end - if colordepth > 1 then - -- not yet - return - end - if data then - -- assume correct data - else - data = { } - for i=1,ysize do - data[i] = setmetatableindex(pixel) - end - end - if mask == true then - mask = { } - for i=1,ysize do - mask[i] = setmetatableindex(gray) - end - end - local specification = { - xsize = xsize, - ysize = ysize, - width = width, - height = height, - colordepth = colordepth, - colorspace = colorspace, - data = data, - mask = mask, - } - return specification - end - -end - -function graphics.identify(filename,filetype) - local identify = filetype and identifiers[filetype] - if identify then - return identify(filename) - end - local identify = identifiers[suffixonly(filename)] - if identify then - return identify(filename) - end - -- auto - return { - filename = filename, - filetype = filetype, - error = "identification failed", - } -end - --- inspect(identifiers.jpg("t:/sources/hacker.jpg")) --- inspect(identifiers.png("t:/sources/mill.png")) |