Merge branch 'issue221' into devel
This commit is contained in:
commit
3fbeacc581
4 changed files with 139 additions and 63 deletions
|
|
@ -44,6 +44,63 @@ CINEMA_MODE = {
|
|||
'cinema2k_48': CINEMA2K_48,
|
||||
'cinema4k_24': CINEMA4K_24, }
|
||||
|
||||
PROFILE = {
|
||||
# no profile, conform to 15444-1
|
||||
'none': 0x0000,
|
||||
# profile 0 as described in 15444-1,Table A.45
|
||||
'0': 0x0001,
|
||||
'zero': 0x0001,
|
||||
0: 0x0001,
|
||||
# profile 1 as described in 15444-1,Table A.45
|
||||
'1': 0x0002,
|
||||
'one': 0x0002,
|
||||
1: 0x0002,
|
||||
# at least 1 extension defined in 15444-2 (Part-2)
|
||||
'2': 0x8000,
|
||||
2: 0x8000,
|
||||
'two': 0x8000,
|
||||
# 2K cinema profile defined in 15444-1 AMD1
|
||||
'cinema_2k': 0x0003,
|
||||
# 4K cinema profile defined in 15444-1 AMD1
|
||||
'cinema_4k': 0x0004,
|
||||
# scalable 2K cinema profile defined in 15444-1 AMD2
|
||||
'cinema_s2k': 0x0005,
|
||||
# scalable 4K cinema profile defined in 15444-1 AMD2
|
||||
'cinema_s4k': 0x0006,
|
||||
# long term storage cinema profile defined in 15444-1 AMD2
|
||||
'cinema_lts': 0x0007,
|
||||
# Single Multi Tile Broadcast profile defined in 15444-1 AMD3
|
||||
'bc_single': 0x0100,
|
||||
# Multi Tile Broadcast profile defined in 15444-1 AMD3
|
||||
'bc_multi': 0x0200,
|
||||
# Multi Tile Reversible Broadcast profile defined in 15444-1 AMD3
|
||||
'bc_multi_r': 0x0300,
|
||||
# 2K Single Tile Lossy IMF profile defined in 15444-1 AMD 8
|
||||
'imf_2k': 0x0400,
|
||||
# 4K Single Tile Lossy IMF profile defined in 15444-1 AMD 8
|
||||
'imf_4k': 0x0401,
|
||||
# 8K Single Tile Lossy IMF profile defined in 15444-1 AMD 8
|
||||
'imf_8k': 0x0402,
|
||||
# 2K Single/Multi Tile Reversible IMF profile defined in 15444-1 AMD 8
|
||||
'imf_2k_r': 0x0403,
|
||||
# 4K Single/Multi Tile Reversible IMF profile defined in 15444-1 AMD 8
|
||||
'imf_4k_r': 0x0800,
|
||||
# 8K Single/Multi Tile Reversible IMF profile defined in 15444-1 AMD 8
|
||||
'imf_8k_r': 0x0801,
|
||||
}
|
||||
|
||||
# JPEG 2000 codestream and component size limits in cinema profiles
|
||||
#
|
||||
# Maximum codestream length for 24fps
|
||||
OPJ_CINEMA_24_CS = 1302083
|
||||
# Maximum codestream length for 48fps
|
||||
OPJ_CINEMA_48_CS = 651041
|
||||
# Maximum size per color component for 2K & 4K @ 24fps
|
||||
OPJ_CINEMA_24_COMP = 1041666
|
||||
# Maximum size per color component for 2K @ 48fps
|
||||
OPJ_CINEMA_48_COMP = 520833
|
||||
|
||||
|
||||
PROGRESSION_ORDER = {
|
||||
'LRCP': LRCP,
|
||||
'RLCP': RLCP,
|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@ import numpy as np
|
|||
|
||||
from .codestream import Codestream
|
||||
from .core import SRGB, GREYSCALE
|
||||
from .core import PROGRESSION_ORDER, CINEMA_MODE
|
||||
from .core import PROGRESSION_ORDER
|
||||
from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE
|
||||
from . import core
|
||||
from .jp2box import Jp2kBox
|
||||
from .jp2box import JPEG2000SignatureBox, FileTypeBox, JP2HeaderBox
|
||||
from .jp2box import ColourSpecificationBox, ContiguousCodestreamBox
|
||||
|
|
@ -173,14 +174,34 @@ class Jp2k(Jp2kBox):
|
|||
raise IOError(msg)
|
||||
|
||||
if cinema_mode == 'cinema2k':
|
||||
if fps == 24:
|
||||
cparams.cp_cinema = CINEMA_MODE['cinema2k_24']
|
||||
elif fps == 48:
|
||||
cparams.cp_cinema = CINEMA_MODE['cinema2k_48']
|
||||
else:
|
||||
if fps not in [24, 48]:
|
||||
raise IOError('Cinema2K frame rate must be either 24 or 48.')
|
||||
|
||||
if re.match("2.0", version.openjpeg_version) is not None:
|
||||
# 2.0 API
|
||||
if fps == 24:
|
||||
cparams.cp_cinema = core.CINEMA_MODE['cinema2k_24']
|
||||
else:
|
||||
cparams.cp_cinema = core.CINEMA_MODE['cinema2k_48']
|
||||
else:
|
||||
# 2.1 API
|
||||
if fps == 24:
|
||||
cparams.rsiz = core.PROFILE['cinema_2k']
|
||||
cparams.max_comp_size = core.CINEMA_24_COMP
|
||||
cparams.max_cs_size = core.CINEMA_24_CS
|
||||
else:
|
||||
cparams.rsiz = core.PROFILE['cinema_2k']
|
||||
cparams.max_comp_size = core.CINEMA_48_COMP
|
||||
cparams.max_cs_size = core.CINEMA_48_CS
|
||||
|
||||
else:
|
||||
cparams.cp_cinema = CINEMA_MODE['cinema4k_24']
|
||||
# cinema4k
|
||||
if re.match("2.0", version.openjpeg_version) is not None:
|
||||
# 2.0 API
|
||||
cparams.cp_cinema = core.CINEMA_MODE['cinema4k_24']
|
||||
else:
|
||||
# 2.1 API
|
||||
cparams.rsiz = core.PROFILE['cinema_4k']
|
||||
|
||||
return
|
||||
|
||||
|
|
@ -554,9 +575,9 @@ class Jp2k(Jp2kBox):
|
|||
stack.callback(libc.fclose, fptr)
|
||||
else:
|
||||
# Introduced in 2.1 devel series.
|
||||
strm = opj2.stream_create_default_file_stream_v3(self.filename,
|
||||
False)
|
||||
stack.callback(opj2.stream_destroy_v3, strm)
|
||||
strm = opj2.stream_create_default_file_stream(self.filename,
|
||||
False)
|
||||
stack.callback(opj2.stream_destroy, strm)
|
||||
|
||||
opj2.start_compress(codec, image, strm)
|
||||
opj2.encode(codec, strm)
|
||||
|
|
@ -909,12 +930,10 @@ class Jp2k(Jp2kBox):
|
|||
layer=layer, tile=tile, area=area)
|
||||
|
||||
with ExitStack() as stack:
|
||||
if hasattr(opj2.OPENJP2,
|
||||
'opj_stream_create_default_file_stream_v3'):
|
||||
if re.match("2.1", version.openjpeg_version):
|
||||
filename = self.filename
|
||||
stream = opj2.stream_create_default_file_stream_v3(filename,
|
||||
True)
|
||||
stack.callback(opj2.stream_destroy_v3, stream)
|
||||
stream = opj2.stream_create_default_file_stream(filename, True)
|
||||
stack.callback(opj2.stream_destroy, stream)
|
||||
else:
|
||||
fptr = libc.fopen(self.filename, 'rb')
|
||||
stack.callback(libc.fclose, fptr)
|
||||
|
|
@ -1080,17 +1099,16 @@ class Jp2k(Jp2kBox):
|
|||
layer=layer, tile=tile, area=area)
|
||||
|
||||
with ExitStack() as stack:
|
||||
if re.match("2.0", version.openjpeg_version):
|
||||
if re.match("2.1", version.openjpeg_version):
|
||||
# API change in 2.1
|
||||
filename = self.filename
|
||||
stream = opj2.stream_create_default_file_stream(filename, True)
|
||||
stack.callback(opj2.stream_destroy, stream)
|
||||
else:
|
||||
fptr = libc.fopen(self.filename, 'rb')
|
||||
stack.callback(libc.fclose, fptr)
|
||||
stream = opj2.stream_create_default_file_stream(fptr, True)
|
||||
stack.callback(opj2.stream_destroy, stream)
|
||||
else:
|
||||
# API change in 2.1+
|
||||
filename = self.filename
|
||||
stream = opj2.stream_create_default_file_stream_v3(filename,
|
||||
True)
|
||||
stack.callback(opj2.stream_destroy_v3, stream)
|
||||
codec = opj2.create_decompress(self._codec_format)
|
||||
stack.callback(opj2.destroy_codec, codec)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ Wraps individual functions in openjp2 library.
|
|||
# pylint: disable=C0302,R0903,W0201
|
||||
|
||||
import ctypes
|
||||
import re
|
||||
import sys
|
||||
|
||||
from .config import glymur_config
|
||||
|
|
@ -12,7 +13,11 @@ OPENJP2, OPENJPEG = glymur_config()
|
|||
|
||||
def version():
|
||||
"""Wrapper for opj_version library routine."""
|
||||
OPENJP2.opj_version.restype = ctypes.c_char_p
|
||||
try:
|
||||
OPENJP2.opj_version.restype = ctypes.c_char_p
|
||||
except:
|
||||
return "0.0.0"
|
||||
|
||||
library_version = OPENJP2.opj_version()
|
||||
if sys.hexversion >= 0x03000000:
|
||||
return library_version.decode('utf-8')
|
||||
|
|
@ -43,6 +48,13 @@ JPWL_MAX_NO_TILESPECS = 16
|
|||
TRUE = 1
|
||||
FALSE = 0
|
||||
|
||||
#PROFILE = {'none': 0, # No profile
|
||||
# 0: 1, # Profile 0
|
||||
# 1: 2, # Profile 1
|
||||
# 'part2': 0x8000, # At least one extension
|
||||
# 'Cinema2K': 0x0003, # 2K cinema profile
|
||||
# 'Cinema4K': 0x0004, # 4K cinema profile
|
||||
|
||||
# supported color spaces
|
||||
CLRSPC_UNKNOWN = -1
|
||||
CLRSPC_UNSPECIFIED = 0
|
||||
|
|
@ -368,6 +380,16 @@ class CompressionParametersType(ctypes.Structure):
|
|||
# based encoding without offset concerning all the components.
|
||||
("mct_data", ctypes.c_void_p)]
|
||||
|
||||
if _MINOR == '1':
|
||||
# Maximum size (in bytes) for the whole codestream.
|
||||
# If == 0, codestream size limitation is not considered.
|
||||
# If it does not comply with tcp_rates, max_cs_size prevails and a
|
||||
# warning is issued.
|
||||
_fields_.append(("max_cs_size", ctypes.c_int32))
|
||||
|
||||
# To be used to combine OPJ_PROFILE_*, OPJ_EXTENSION_* and (sub)levels
|
||||
# values.
|
||||
_fields_.append(("rsiz", ctypes.c_uint16))
|
||||
|
||||
class ImageCompType(ctypes.Structure):
|
||||
"""Defines a single image component.
|
||||
|
|
@ -1278,7 +1300,7 @@ def start_compress(codec, image, stream):
|
|||
OPENJP2.opj_start_compress(codec, image, stream)
|
||||
|
||||
|
||||
def stream_create_default_file_stream(fptr, isa_read_stream):
|
||||
def _stream_create_default_file_stream_2p0(fptr, isa_read_stream):
|
||||
"""Wraps openjp2 library function opj_stream_create_default_vile_stream.
|
||||
|
||||
Sets the stream to be a file stream. This is valid only for version 2.0.0
|
||||
|
|
@ -1303,12 +1325,11 @@ def stream_create_default_file_stream(fptr, isa_read_stream):
|
|||
stream = OPENJP2.opj_stream_create_default_file_stream(fptr, read_stream)
|
||||
return stream
|
||||
|
||||
|
||||
def stream_create_default_file_stream_v3(fname, isa_read_stream):
|
||||
"""Wraps openjp2 library function opj_stream_create_default_vile_stream_v3.
|
||||
def _stream_create_default_file_stream_2p1(fname, isa_read_stream):
|
||||
"""Wraps openjp2 library function opj_stream_create_default_vile_stream.
|
||||
|
||||
Sets the stream to be a file stream. This function is only valid for the
|
||||
trunk/development 2.0+ version of the openjp2 library.
|
||||
2.1 version of the openjp2 library.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -1323,13 +1344,18 @@ def stream_create_default_file_stream_v3(fname, isa_read_stream):
|
|||
An OpenJPEG file stream.
|
||||
"""
|
||||
ARGTYPES = [ctypes.c_char_p, ctypes.c_int32]
|
||||
OPENJP2.opj_stream_create_default_file_stream_v3.argtypes = ARGTYPES
|
||||
OPENJP2.opj_stream_create_default_file_stream_v3.restype = STREAM_TYPE_P
|
||||
OPENJP2.opj_stream_create_default_file_stream.argtypes = ARGTYPES
|
||||
OPENJP2.opj_stream_create_default_file_stream.restype = STREAM_TYPE_P
|
||||
read_stream = 1 if isa_read_stream else 0
|
||||
file_argument = ctypes.c_char_p(fname.encode())
|
||||
stream = OPENJP2.opj_stream_create_default_file_stream_v3(file_argument,
|
||||
read_stream)
|
||||
stream = OPENJP2.opj_stream_create_default_file_stream(file_argument,
|
||||
read_stream)
|
||||
return stream
|
||||
|
||||
if re.match(r'''2.0''', version()):
|
||||
stream_create_default_file_stream = _stream_create_default_file_stream_2p0
|
||||
else:
|
||||
stream_create_default_file_stream = _stream_create_default_file_stream_2p1
|
||||
|
||||
|
||||
def stream_destroy(stream):
|
||||
|
|
@ -1347,21 +1373,6 @@ def stream_destroy(stream):
|
|||
OPENJP2.opj_stream_destroy(stream)
|
||||
|
||||
|
||||
def stream_destroy_v3(stream):
|
||||
"""Wraps openjp2 library function opj_stream_destroy_v3.
|
||||
|
||||
Destroys the stream created by create_stream_v3.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
stream : STREAM_TYPE_P
|
||||
The file stream.
|
||||
"""
|
||||
OPENJP2.opj_stream_destroy_v3.argtypes = [STREAM_TYPE_P]
|
||||
OPENJP2.opj_stream_destroy_v3.restype = ctypes.c_void_p
|
||||
OPENJP2.opj_stream_destroy_v3(stream)
|
||||
|
||||
|
||||
def write_tile(codec, tile_index, data, data_size, stream):
|
||||
"""Wraps openjp2 library function opj_write_tile.
|
||||
|
||||
|
|
@ -1403,13 +1414,3 @@ def write_tile(codec, tile_index, data, data_size, stream):
|
|||
def set_error_message(msg):
|
||||
"""The openjpeg error handler has recorded an error message."""
|
||||
ERROR_MSG_LST.append(msg)
|
||||
|
||||
|
||||
def version():
|
||||
"""Wrapper for opj_version library routine."""
|
||||
OPENJP2.opj_version.restype = ctypes.c_char_p
|
||||
library_version = OPENJP2.opj_version()
|
||||
if sys.hexversion >= 0x03000000:
|
||||
return library_version.decode('utf-8')
|
||||
else:
|
||||
return library_version
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class TestOpenJP2(unittest.TestCase):
|
|||
openjp2.set_warning_handler(codec, None)
|
||||
openjp2.set_error_handler(codec, None)
|
||||
|
||||
stream = openjp2.stream_create_default_file_stream_v3(filename, True)
|
||||
stream = openjp2.stream_create_default_file_stream(filename, True)
|
||||
|
||||
openjp2.setup_decoder(codec, dparam)
|
||||
image = openjp2.read_header(stream, codec)
|
||||
|
|
@ -100,7 +100,7 @@ class TestOpenJP2(unittest.TestCase):
|
|||
|
||||
openjp2.end_decompress(codec, stream)
|
||||
openjp2.destroy_codec(codec)
|
||||
openjp2.stream_destroy_v3(stream)
|
||||
openjp2.stream_destroy(stream)
|
||||
openjp2.image_destroy(image)
|
||||
|
||||
def test_tte0(self):
|
||||
|
|
@ -308,7 +308,7 @@ def tile_encoder(**kwargs):
|
|||
|
||||
openjp2.setup_encoder(codec, l_param, l_image)
|
||||
|
||||
stream = openjp2.stream_create_default_file_stream_v3(kwargs['filename'],
|
||||
stream = openjp2.stream_create_default_file_stream(kwargs['filename'],
|
||||
False)
|
||||
openjp2.start_compress(codec, l_image, stream)
|
||||
|
||||
|
|
@ -316,7 +316,7 @@ def tile_encoder(**kwargs):
|
|||
openjp2.write_tile(codec, j, data, tile_size, stream)
|
||||
|
||||
openjp2.end_compress(codec, stream)
|
||||
openjp2.stream_destroy_v3(stream)
|
||||
openjp2.stream_destroy(stream)
|
||||
openjp2.destroy_codec(codec)
|
||||
openjp2.image_destroy(l_image)
|
||||
|
||||
|
|
@ -325,7 +325,7 @@ def tile_decoder(**kwargs):
|
|||
|
||||
Reads a tile. That's all it does.
|
||||
"""
|
||||
stream = openjp2.stream_create_default_file_stream_v3(kwargs['filename'],
|
||||
stream = openjp2.stream_create_default_file_stream(kwargs['filename'],
|
||||
True)
|
||||
dparam = openjp2.set_default_decoder_parameters()
|
||||
|
||||
|
|
@ -361,7 +361,7 @@ def tile_decoder(**kwargs):
|
|||
|
||||
openjp2.end_decompress(codec, stream)
|
||||
openjp2.destroy_codec(codec)
|
||||
openjp2.stream_destroy_v3(stream)
|
||||
openjp2.stream_destroy(stream)
|
||||
openjp2.image_destroy(image)
|
||||
|
||||
def ttx0_setup(filename):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue