mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-10 19:56:47 +03:00
Added support for jpeg2000 comments and PLT marker segments
This commit is contained in:
parent
fcf5b7ef83
commit
de43bc99c8
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import re
|
||||
import struct
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
@ -371,3 +372,46 @@ def test_crashes(test_file):
|
|||
im.load()
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def test_custom_comment():
|
||||
output_stream = BytesIO()
|
||||
unique_comment = "This is a unique comment, which should be found below"
|
||||
test_card.save(output_stream, "JPEG2000", comment=unique_comment)
|
||||
output_stream.seek(0)
|
||||
data = output_stream.read()
|
||||
# Lazy method to determine if the comment is in the image generated
|
||||
assert(bytes(unique_comment, "utf-8") in data)
|
||||
|
||||
|
||||
def test_plt_marker():
|
||||
# Search the start of the codesteam for the PLT box (id 0xFF58)
|
||||
opj_version = re.search(r"(\d+\.\d+)\.\d+$", features.version_codec("jpg_2000"))
|
||||
assert opj_version is not None
|
||||
|
||||
if float(opj_version[1]) >= 2.4:
|
||||
out = BytesIO()
|
||||
test_card.save(out, "JPEG2000", no_jp2=True, add_plt=True)
|
||||
out.seek(0)
|
||||
while True:
|
||||
box_bytes = out.read(2)
|
||||
if len(box_bytes) == 0:
|
||||
# End of steam encounterd and no PLT or SOD
|
||||
break
|
||||
jp2_boxid = struct.unpack(">H", box_bytes)[0]
|
||||
|
||||
if jp2_boxid == 0xff4f:
|
||||
# No length specifier for main header
|
||||
continue
|
||||
elif jp2_boxid == 0xff58:
|
||||
# This is the PLT box we're looking for
|
||||
return
|
||||
elif jp2_boxid == 0xff93:
|
||||
break
|
||||
# SOD box encountered and no PLT, so it wasn't found
|
||||
|
||||
jp2_boxlength = struct.unpack(">H", out.read(2))[0]
|
||||
out.seek(jp2_boxlength - 2, os.SEEK_CUR)
|
||||
|
||||
# The PLT box wasn't found
|
||||
raise ValueError
|
||||
|
|
|
@ -589,6 +589,19 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options:
|
|||
|
||||
.. versionadded:: 9.1.0
|
||||
|
||||
**comment**
|
||||
Adds a custom comment to the file, replacing the default
|
||||
"Created by OpenJPEG version" comment.
|
||||
|
||||
.. versionadded:: 9.5.0
|
||||
|
||||
**add_plt**
|
||||
If ``True`` then include a PLT (packet length, tile-part header) marker
|
||||
segment in the produced file.
|
||||
The default is to not include it.
|
||||
|
||||
.. versionadded:: 9.5.0
|
||||
|
||||
.. note::
|
||||
|
||||
To enable JPEG 2000 support, you need to build and install the OpenJPEG
|
||||
|
|
|
@ -328,6 +328,8 @@ def _save(im, fp, filename):
|
|||
mct = info.get("mct", 0)
|
||||
signed = info.get("signed", False)
|
||||
fd = -1
|
||||
comment = info.get("comment", None)
|
||||
add_plt = info.get("add_plt", False)
|
||||
|
||||
if hasattr(fp, "fileno"):
|
||||
try:
|
||||
|
@ -350,6 +352,8 @@ def _save(im, fp, filename):
|
|||
mct,
|
||||
signed,
|
||||
fd,
|
||||
comment,
|
||||
add_plt
|
||||
)
|
||||
|
||||
ImageFile._save(im, fp, [("jpeg2k", (0, 0) + im.size, 0, kind)])
|
||||
|
|
|
@ -97,6 +97,12 @@ typedef struct {
|
|||
/* PRIVATE CONTEXT (set by decoder) */
|
||||
const char *error_msg;
|
||||
|
||||
/* Custom comment */
|
||||
char * comment;
|
||||
|
||||
/* Include PLT marker segment */
|
||||
int add_plt;
|
||||
|
||||
} JPEG2KENCODESTATE;
|
||||
|
||||
/*
|
||||
|
|
|
@ -439,6 +439,10 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) {
|
|||
params.tcp_mct = context->mct;
|
||||
}
|
||||
|
||||
if (context->comment) {
|
||||
params.cp_comment = context->comment;
|
||||
}
|
||||
|
||||
params.prog_order = context->progression;
|
||||
|
||||
params.cp_cinema = context->cinema_mode;
|
||||
|
@ -492,6 +496,14 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) {
|
|||
opj_set_warning_handler(codec, j2k_warn, context);
|
||||
opj_setup_encoder(codec, ¶ms, image);
|
||||
|
||||
/* Enabling PLT markers only supported in OpenJPEG 2.4.0 and up */
|
||||
#if ((OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR >= 4) || OPJ_VERSION_MAJOR > 2)
|
||||
if (context->add_plt) {
|
||||
const char * plt_option[2] = {"PLT=YES", NULL};
|
||||
opj_encoder_set_extra_options(codec, plt_option);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Start encoding */
|
||||
if (!opj_start_compress(codec, image, stream)) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
|
@ -624,7 +636,12 @@ ImagingJpeg2KEncodeCleanup(ImagingCodecState state) {
|
|||
free((void *)context->error_msg);
|
||||
}
|
||||
|
||||
if (context->comment) {
|
||||
free((void *)context->comment);
|
||||
}
|
||||
|
||||
context->error_msg = NULL;
|
||||
context->comment = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user