Added cinema2k/48 support. #139

This commit is contained in:
John Evans 2014-03-07 07:00:02 -05:00
commit 9a74109501
2 changed files with 190 additions and 2 deletions

View file

@ -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)

View file

@ -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):