Added cinema2k/48 support. #139
This commit is contained in:
parent
80326718a5
commit
9a74109501
2 changed files with 190 additions and 2 deletions
|
|
@ -39,7 +39,15 @@ from .lib import openjp2 as opj2
|
|||
from . import version
|
||||
from .lib import c as libc
|
||||
|
||||
# Codestream lengths for 24fps, 48fps
|
||||
CINEMA_24_CS = 1302083
|
||||
CINEMA_48_CS = 651041
|
||||
|
||||
# Maximum size per color components for 2K and 4K at 24 fps
|
||||
COMP_24_CS = 1041666
|
||||
|
||||
# Maximum size per color components for 2K at 48 fps
|
||||
COMP_48_CS = 520833
|
||||
|
||||
JP2_IDS = ['colr', 'cdef', 'cmap', 'jp2c', 'ftyp', 'ihdr', 'jp2h', 'jP ',
|
||||
'pclr', 'res ', 'resc', 'resd', 'xml ', 'ulst', 'uinf', 'url ',
|
||||
|
|
@ -295,6 +303,10 @@ class Jp2k(Jp2kBox):
|
|||
self._set_cinema_params(cparams, kwargs['cinema2k'])
|
||||
return cparams
|
||||
|
||||
if 'cinema4k' in kwargs:
|
||||
self._set_cinema_params(cparams, kwargs['cinema2k'])
|
||||
return cparams
|
||||
|
||||
if 'cbsize' in kwargs:
|
||||
cparams.cblockw_init = kwargs['cbsize'][1]
|
||||
cparams.cblockh_init = kwargs['cbsize'][0]
|
||||
|
|
@ -555,7 +567,7 @@ class Jp2k(Jp2kBox):
|
|||
cparams.cp_disto_alloc = 1
|
||||
|
||||
if cparams.cp_cinema in [CINEMA_MODE['cinema2k_24'],
|
||||
CINEMA_MODE['cinema2k_48']]:
|
||||
CINEMA_MODE['cinema4k_24']]:
|
||||
num_pixels = image.contents.comps[0].w * image.contents.comps[0].h
|
||||
num_samples = num_pixels * image.contents.numcomps
|
||||
rate_numerator = num_samples * image.contents.comps[0].prec
|
||||
|
|
@ -574,7 +586,28 @@ class Jp2k(Jp2kBox):
|
|||
# TODO warning
|
||||
pass
|
||||
|
||||
cparams.max_comp_size = CINEMA_24_CS
|
||||
cparams.max_comp_size = COMP_24_CS
|
||||
|
||||
else:
|
||||
num_pixels = image.contents.comps[0].w * image.contents.comps[0].h
|
||||
num_samples = num_pixels * image.contents.numcomps
|
||||
rate_numerator = num_samples * image.contents.comps[0].prec
|
||||
rate_denominator = CINEMA_48_CS * 8
|
||||
rate_denominator *= image.contents.comps[0].dx
|
||||
rate_denominator *= image.contents.comps[0].dy
|
||||
max_rate = rate_numerator / rate_denominator
|
||||
if cparams.tcp_rates[0] == 0:
|
||||
cparams.tcp_rates[0] = max_rate
|
||||
else:
|
||||
temp_rate = rate_numerator / (cparams.tcp_rates[0] * 8 * num_pixels)
|
||||
if temp_rate > CINEMA_48_CS:
|
||||
# TODO warning, reset
|
||||
cparams.tcp_rates[0] = max_rate
|
||||
else:
|
||||
# TODO warning
|
||||
pass
|
||||
|
||||
cparams.max_comp_size = COMP_48_CS
|
||||
|
||||
def _write_openjp2(self, img_array, verbose=False, **kwargs):
|
||||
"""
|
||||
|
|
@ -597,6 +630,8 @@ class Jp2k(Jp2kBox):
|
|||
|
||||
if 'cinema2k' in kwargs:
|
||||
self._set_cinema_rate(cparams, image)
|
||||
if 'cinema4k' in kwargs:
|
||||
self._set_cinema_rate(cparams, image)
|
||||
|
||||
codec = opj2.create_compress(cparams.codec_fmt)
|
||||
stack.callback(opj2.destroy_codec, codec)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,108 @@ class TestSuiteWrite(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||
"Cannot read input image without scikit-image/freeimage")
|
||||
def test_NR_ENC_X_5_2K_24_235_CBR_STEM24_000_tif_19_encode(self):
|
||||
relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_000.tif'
|
||||
infile = opj_data_file(relfile)
|
||||
data = skimage.io.imread(infile)
|
||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||
j = Jp2k(tfile.name, 'wb')
|
||||
j.write(data, cinema2k=48)
|
||||
|
||||
codestream = j.get_codestream()
|
||||
|
||||
# SIZ: Image and tile size
|
||||
# Profile: "3" means cinema2K
|
||||
self.assertEqual(codestream.segment[1].rsiz, 3)
|
||||
# Reference grid size
|
||||
self.assertEqual((codestream.segment[1].xsiz,
|
||||
codestream.segment[1].ysiz),
|
||||
(2048, 857))
|
||||
# Reference grid offset
|
||||
self.assertEqual((codestream.segment[1].xosiz,
|
||||
codestream.segment[1].yosiz), (0, 0))
|
||||
# Tile size
|
||||
self.assertEqual((codestream.segment[1].xtsiz,
|
||||
codestream.segment[1].ytsiz),
|
||||
(2048, 857))
|
||||
# Tile offset
|
||||
self.assertEqual((codestream.segment[1].xtosiz,
|
||||
codestream.segment[1].ytosiz),
|
||||
(0, 0))
|
||||
# bitdepth
|
||||
self.assertEqual(codestream.segment[1].bitdepth, (12, 12, 12))
|
||||
# signed
|
||||
self.assertEqual(codestream.segment[1].signed,
|
||||
(False, False, False))
|
||||
# subsampling
|
||||
self.assertEqual(list(zip(codestream.segment[1].xrsiz,
|
||||
codestream.segment[1].yrsiz)),
|
||||
[(1, 1)] * 3)
|
||||
|
||||
# COD: Coding style default
|
||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||
self.assertFalse(codestream.segment[2].scod & 4) # no eph
|
||||
self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL)
|
||||
self.assertEqual(codestream.segment[2].layers, 1)
|
||||
self.assertEqual(codestream.segment[2].spcod[3], 1) # mct
|
||||
self.assertEqual(codestream.segment[2].spcod[4], 5) # levels
|
||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||
(32, 32)) # cblksz
|
||||
|
||||
|
||||
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||
"Cannot read input image without scikit-image/freeimage")
|
||||
def test_NR_ENC_X_6_2K_24_FULL_CBR_CIRCLE_000_tif_20_encode(self):
|
||||
relfile = 'input/nonregression/X_6_2K_24_FULL_CBR_CIRCLE_000.tif'
|
||||
infile = opj_data_file(relfile)
|
||||
data = skimage.io.imread(infile)
|
||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||
j = Jp2k(tfile.name, 'wb')
|
||||
j.write(data, cinema2k=48)
|
||||
|
||||
codestream = j.get_codestream()
|
||||
|
||||
# SIZ: Image and tile size
|
||||
# Profile: "3" means cinema2K
|
||||
self.assertEqual(codestream.segment[1].rsiz, 3)
|
||||
# Reference grid size
|
||||
self.assertEqual((codestream.segment[1].xsiz,
|
||||
codestream.segment[1].ysiz),
|
||||
(2048, 1080))
|
||||
# Reference grid offset
|
||||
self.assertEqual((codestream.segment[1].xosiz,
|
||||
codestream.segment[1].yosiz), (0, 0))
|
||||
# Tile size
|
||||
self.assertEqual((codestream.segment[1].xtsiz,
|
||||
codestream.segment[1].ytsiz),
|
||||
(2048, 1080))
|
||||
# Tile offset
|
||||
self.assertEqual((codestream.segment[1].xtosiz,
|
||||
codestream.segment[1].ytosiz),
|
||||
(0, 0))
|
||||
# bitdepth
|
||||
self.assertEqual(codestream.segment[1].bitdepth, (12, 12, 12))
|
||||
# signed
|
||||
self.assertEqual(codestream.segment[1].signed,
|
||||
(False, False, False))
|
||||
# subsampling
|
||||
self.assertEqual(list(zip(codestream.segment[1].xrsiz,
|
||||
codestream.segment[1].yrsiz)),
|
||||
[(1, 1)] * 3)
|
||||
|
||||
# COD: Coding style default
|
||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||
self.assertFalse(codestream.segment[2].scod & 4) # no eph
|
||||
self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL)
|
||||
self.assertEqual(codestream.segment[2].layers, 1)
|
||||
self.assertEqual(codestream.segment[2].spcod[3], 1) # mct
|
||||
self.assertEqual(codestream.segment[2].spcod[4], 5) # levels
|
||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||
(32, 32)) # cblksz
|
||||
|
||||
|
||||
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||
"Cannot read input image without scikit-image/freeimage")
|
||||
def test_NR_ENC_X_6_2K_24_FULL_CBR_CIRCLE_000_tif_17_encode(self):
|
||||
|
|
@ -146,6 +248,57 @@ class TestSuiteWrite(unittest.TestCase):
|
|||
(32, 32)) # cblksz
|
||||
|
||||
|
||||
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||
"Cannot read input image without scikit-image/freeimage")
|
||||
def test_NR_ENC_X_4_2K_24_185_CBR_WB_000_tif_18_encode(self):
|
||||
relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif'
|
||||
infile = opj_data_file(relfile)
|
||||
data = skimage.io.imread(infile)
|
||||
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
|
||||
j = Jp2k(tfile.name, 'wb')
|
||||
j.write(data, cinema2k=48)
|
||||
|
||||
codestream = j.get_codestream()
|
||||
|
||||
# SIZ: Image and tile size
|
||||
# Profile: "3" means cinema2K
|
||||
self.assertEqual(codestream.segment[1].rsiz, 3)
|
||||
# Reference grid size
|
||||
self.assertEqual((codestream.segment[1].xsiz,
|
||||
codestream.segment[1].ysiz),
|
||||
(1998, 1080))
|
||||
# Reference grid offset
|
||||
self.assertEqual((codestream.segment[1].xosiz,
|
||||
codestream.segment[1].yosiz), (0, 0))
|
||||
# Tile size
|
||||
self.assertEqual((codestream.segment[1].xtsiz,
|
||||
codestream.segment[1].ytsiz),
|
||||
(1998, 1080))
|
||||
# Tile offset
|
||||
self.assertEqual((codestream.segment[1].xtosiz,
|
||||
codestream.segment[1].ytosiz),
|
||||
(0, 0))
|
||||
# bitdepth
|
||||
self.assertEqual(codestream.segment[1].bitdepth, (12, 12, 12))
|
||||
# signed
|
||||
self.assertEqual(codestream.segment[1].signed,
|
||||
(False, False, False))
|
||||
# subsampling
|
||||
self.assertEqual(list(zip(codestream.segment[1].xrsiz,
|
||||
codestream.segment[1].yrsiz)),
|
||||
[(1, 1)] * 3)
|
||||
|
||||
# COD: Coding style default
|
||||
self.assertFalse(codestream.segment[2].scod & 2) # no sop
|
||||
self.assertFalse(codestream.segment[2].scod & 4) # no eph
|
||||
self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL)
|
||||
self.assertEqual(codestream.segment[2].layers, 1)
|
||||
self.assertEqual(codestream.segment[2].spcod[3], 1) # mct
|
||||
self.assertEqual(codestream.segment[2].spcod[4], 5) # levels
|
||||
self.assertEqual(tuple(codestream.segment[2].code_block_size),
|
||||
(32, 32)) # cblksz
|
||||
|
||||
|
||||
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
|
||||
"Cannot read input image without scikit-image/freeimage")
|
||||
def test_NR_ENC_X_4_2K_24_185_CBR_WB_000_tif_15_encode(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue