Cinema4K seems to be working. #139
This commit is contained in:
parent
af4b6e64bf
commit
d68b1aacb1
5 changed files with 108 additions and 17 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue