jp2: rudimentary support for raw jpeg2000 without jp2 boxes
This commit is contained in:
parent
2f736d7891
commit
09064e8e70
2 changed files with 42 additions and 12 deletions
|
@ -37,7 +37,7 @@ if hasattr(GifImagePlugin, "LoadingStrategy"):
|
|||
# TiffImagePlugin.DEBUG = True
|
||||
from PIL.ExifTags import TAGS
|
||||
from datetime import datetime, timezone
|
||||
from jp2 import parsejp2
|
||||
import jp2
|
||||
from enum import Enum
|
||||
from io import BytesIO
|
||||
import logging
|
||||
|
@ -1301,7 +1301,7 @@ def get_imgmetadata(
|
|||
if imgformat == ImageFormat.JPEG2000 and rawdata is not None and imgdata is None:
|
||||
# this codepath gets called if the PIL installation is not able to
|
||||
# handle JPEG2000 files
|
||||
imgwidthpx, imgheightpx, ics, hdpi, vdpi, channels, bpp = parsejp2(rawdata)
|
||||
imgwidthpx, imgheightpx, ics, hdpi, vdpi, channels, bpp = jp2.parse(rawdata)
|
||||
|
||||
if hdpi is None:
|
||||
hdpi = default_dpi
|
||||
|
@ -1843,7 +1843,7 @@ def read_images(
|
|||
cleanup()
|
||||
depth = 8
|
||||
if imgformat == ImageFormat.JPEG2000:
|
||||
_, _, _, _, _, _, depth = parsejp2(rawdata)
|
||||
*_, depth = jp2.parse(rawdata)
|
||||
return [
|
||||
(
|
||||
color,
|
||||
|
@ -2241,7 +2241,7 @@ def read_images(
|
|||
r, g, b, a = newimg.convert(mode="RGBA").split()
|
||||
newimg = Image.merge("RGB", (r, g, b))
|
||||
|
||||
smaskidat, _, _ = to_png_data(a)
|
||||
smaskidat, *_ = to_png_data(a)
|
||||
logger.warning(
|
||||
"Image contains an alpha channel. Computing a separate "
|
||||
"soft mask (/SMask) image to store transparency in PDF."
|
||||
|
|
40
src/jp2.py
40
src/jp2.py
|
@ -101,7 +101,9 @@ def parsejp2(data):
|
|||
while byteStart < noBytes and boxLengthValue != 0:
|
||||
boxLengthValue, boxType, byteEnd, boxContents = getBox(data, byteStart, noBytes)
|
||||
if boxType == b"jp2h":
|
||||
width, height, colorspace, hdpi, vdpi, channels, bpp = parse_jp2h(boxContents)
|
||||
width, height, colorspace, hdpi, vdpi, channels, bpp = parse_jp2h(
|
||||
boxContents
|
||||
)
|
||||
break
|
||||
byteStart = byteEnd
|
||||
if not width:
|
||||
|
@ -114,10 +116,38 @@ def parsejp2(data):
|
|||
return (width, height, colorspace, hdpi, vdpi, channels, bpp)
|
||||
|
||||
|
||||
def parsej2k(data):
|
||||
lsiz, rsiz, xsiz, ysiz, xosiz, yosiz, _, _, _, _, csiz = struct.unpack(
|
||||
">HHIIIIIIIIH", data[4:42]
|
||||
)
|
||||
ssiz = [None] * csiz
|
||||
xrsiz = [None] * csiz
|
||||
yrsiz = [None] * csiz
|
||||
for i in range(csiz):
|
||||
ssiz[i], xrsiz[i], yrsiz[i] = struct.unpack(
|
||||
"BBB", data[42 + 3 * i : 42 + 3 * (i + 1)]
|
||||
)
|
||||
assert ssiz == [7, 7, 7]
|
||||
return xsiz - xosiz, ysiz - yosiz, None, None, None, csiz, 8
|
||||
|
||||
|
||||
def parse(data):
|
||||
if data[:4] == b"\xff\x4f\xff\x51":
|
||||
return parsej2k(data)
|
||||
else:
|
||||
return parsejp2(data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
width, height, colorspace = parsejp2(open(sys.argv[1]).read())
|
||||
sys.stdout.write("width = %d" % width)
|
||||
sys.stdout.write("height = %d" % height)
|
||||
sys.stdout.write("colorspace = %s" % colorspace)
|
||||
width, height, colorspace, hdpi, vdpi, channels, bpp = parse(
|
||||
open(sys.argv[1], "rb").read()
|
||||
)
|
||||
print("width = %d" % width)
|
||||
print("height = %d" % height)
|
||||
print("colorspace = %s" % colorspace)
|
||||
print("hdpi = %s" % hdpi)
|
||||
print("vdpi = %s" % vdpi)
|
||||
print("channels = %s" % channels)
|
||||
print("bpp = %s" % bpp)
|
||||
|
|
Loading…
Reference in a new issue