Cinema4K seems to be working. #139

This commit is contained in:
John Evans 2014-03-07 11:00:20 -05:00
commit d68b1aacb1
5 changed files with 108 additions and 17 deletions

View file

@ -1,4 +1,4 @@
Mar 06, 2014 - Added Cinema2K write support.
Mar 06, 2014 - Added Cinema2K, Cinema4K write support.
Changed constructor for ChannelDefinition box. Removed support
for Python 2.6. Added write support for JP2 UUID, DataEntryURL,
Palette and Component Mapping boxes, JPX Association, NumberList

View file

@ -5,7 +5,7 @@ ChangeLog
0.6.0 (pending)
===============
* Added Cinema2K write support.
* Added Cinema2K, Cinema4K write support.
* Added lxml requirement.
* added set_printoptions, get_printoptions function
* dropped support for Python 2.6, added support for Python 3.4

View file

@ -13,7 +13,7 @@ both read and write JPEG 2000 files, but you may wish to install version 2.0
or the 2.0+ version from OpenJPEG's development trunk for better performance.
If you do that, you should compile it as a shared library (named *openjp2*
instead of *openjpeg*) from the developmental source that you can retrieve
via subversion. As of this time of writing, svn revision r2366 works.
via subversion. As of this time of writing, svn revision r2369 works.
You should also download the test data for the purpose of configuring
and running OpenJPEG's test suite, check their instructions for all this.
You should set the **OPJ_DATA_ROOT** environment variable for the purpose

View file

@ -163,22 +163,32 @@ class Jp2k(Jp2kBox):
msg += "profile if the file type box brand is 'jp2 '."
warnings.warn(msg)
def _set_cinema_params(self, cparams, fps):
def _set_cinema_params(self, cparams, cinema_mode, fps):
"""Populate compression parameters structure for cinema2K.
Parameters
----------
params : ctypes struct
Corresponds to compression parameters structure used by the
library.
cinema_mode : str
Either 'cinema2k' or 'cinema4k'
fps : int
Frames per second, should be either 24 or 48.
"""
if fps == 24:
cparams.cp_cinema = CINEMA_MODE['cinema2k_24']
elif fps == 48:
cparams.cp_cinema = CINEMA_MODE['cinema2k_48']
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:
raise IOError('Cinema2K frame rate must be either 24 or 48.')
cparams.cp_rsiz = RSIZ['CINEMA2K']
else:
raise IOError('Cinema2K frame rate must be either 24 or 48.')
cparams.cp_cinema = CINEMA_MODE['cinema4k_24']
cparams.cp_rsiz = RSIZ['CINEMA4K']
cparams.cp_rsiz = RSIZ['CINEMA2K']
# No tiling
cparams.tile_size_on = opj2.FALSE
cparams.cp_tdx = 1
@ -216,9 +226,17 @@ class Jp2k(Jp2kBox):
# TODO: warning or error
cparams.tcp_numlayers = 1
if cparams.numresolution > 6: #TODO only for cinema2k
# TODO: warning or error
cparams.numresolution = 6
if cinema_mode == 'cinema2k':
if cparams.numresolution > 6:
# TODO: warning or error
cparams.numresolution = 6
else:
if cparams.numresolution < 2:
# TODO: warning or error
cparams.numresolution = 1
elif cparams.numresolution > 7:
cparams.numresolution = 7
# precincts
cparams.csty |= 0x01
@ -230,8 +248,25 @@ class Jp2k(Jp2kBox):
# Progression order shall be CPRL
cparams.prog_order = PROGRESSION_ORDER['CPRL']
# progression order changes not allowed for 2K # TODO not for 4K:
cparams.numpocs = 0
# progression order changes not allowed for 2K
if cinema_mode == 'cinema2k':
cparams.numpocs = 0
else:
cparams.poc[0].tile = 1
cparams.poc[0].resno0 = 0
cparams.poc[0].compno0 = 0
cparams.poc[0].layno1 = 1
cparams.poc[0].resno1 = cparams.numresolution - 1
cparams.poc[0].compno1 = 3
cparams.poc[0].prg1 = PROGRESSION_ORDER['CPRL']
cparams.poc[1].tile = 1
cparams.poc[1].resno0 = 0
cparams.poc[1].compno0 = 0
cparams.poc[1].layno1 = 1
cparams.poc[1].resno1 = cparams.numresolution
cparams.poc[1].compno1 = 3
cparams.poc[1].prg1 = PROGRESSION_ORDER['CPRL']
cparams.numpocs = 2
def _populate_cparams(self, **kwargs):
"""Populate compression parameters structure from input arguments.
@ -300,11 +335,11 @@ class Jp2k(Jp2kBox):
cparams.cp_disto_alloc = 1
if 'cinema2k' in kwargs:
self._set_cinema_params(cparams, kwargs['cinema2k'])
self._set_cinema_params(cparams, 'cinema2k', kwargs['cinema2k'])
return cparams
if 'cinema4k' in kwargs:
self._set_cinema_params(cparams, kwargs['cinema2k'])
self._set_cinema_params(cparams, 'cinema4k', kwargs['cinema4k'])
return cparams
if 'cbsize' in kwargs:

View file

@ -44,6 +44,48 @@ class TestSuiteWrite(unittest.TestCase):
def tearDown(self):
pass
def check_cinema4k_codestream(self, codestream, image_size):
"""Common out for cinema2k tests."""
# SIZ: Image and tile size
# Profile: "3" means cinema2K
self.assertEqual(codestream.segment[1].rsiz, 4)
# Reference grid size
self.assertEqual((codestream.segment[1].xsiz,
codestream.segment[1].ysiz),
image_size)
# 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),
image_size)
# 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
def check_cinema2k_codestream(self, codestream, image_size):
"""Common out for cinema2k tests."""
# SIZ: Image and tile size
@ -86,6 +128,20 @@ class TestSuiteWrite(unittest.TestCase):
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
"Cannot read input image without scikit-image/freeimage")
def test_NR_ENC_ElephantDream_4K_tif_21_encode(self):
relfile = 'input/nonregression/ElephantDream_4K.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, cinema4k=True)
codestream = j.get_codestream()
self.check_cinema4k_codestream(codestream, (4096, 2160))
@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):