This commit is contained in:
John Evans 2013-06-25 07:04:24 -04:00
commit 881132fbef
3 changed files with 62 additions and 7 deletions

View file

@ -142,7 +142,7 @@ class Jp2k(Jp2kBox):
def write(self, img_array, cratios=None, eph=False, psnr=None, numres=None,
cbsize=None, psizes=None, grid_offset=None, sop=False,
subsam=None, tilesize=None, prog=None, modesw=None,
colorspace=None, verbose=False):
colorspace=None, verbose=False, mct=None):
"""Write image data to a JP2/JPX/J2k file. Intended usage of the
various parameters follows that of OpenJPEG's opj_compress utility.
@ -168,6 +168,9 @@ class Jp2k(Jp2kBox):
If true, write SOP marker after each header packet.
grid_offset : tuple, optional
Offset (DY, DX) of the origin of the image in the reference grid.
mct : bool, optional
Specifies usage of the multi component transform. If not
specified, defaults to True if the colorspace is RGB.
modesw : int, optional
Mode switch.
1 = BYPASS(LAZY)
@ -337,6 +340,18 @@ class Jp2k(Jp2kBox):
else:
colorspace = _cspace_map[colorspace]
if mct is None:
if colorspace == opj2._CLRSPC_SRGB:
cparams.tcp_mct = 1
else:
cparams.tcp_mct = 0
else:
if mct and colorspace == opj2._CLRSPC_GRAY:
msg = "Cannot specify usage of the multi component transform "
msg += "if the colorspace is gray."
raise IOError(msg)
cparams.tcp_mct = 1 if mct else 0
if img_array.dtype == np.uint8:
comp_prec = 8
elif img_array.dtype == np.uint16:
@ -373,12 +388,6 @@ class Jp2k(Jp2kBox):
src = layer.ctypes.data
ctypes.memmove(dest, src, layer.nbytes)
# set multi-component transform?
if image.contents.numcomps == 3:
cparams.tcp_mct = 1
else:
cparams.tcp_mct = 0
codec = opj2._create_compress(codec_fmt)
if verbose:
@ -435,6 +444,11 @@ class Jp2k(Jp2kBox):
jp2h_lst = [idx for (idx, box) in enumerate(boxes) if box.id == 'jp2h']
jp2h_idx = jp2h_lst[0]
jp2c_lst = [idx for (idx, box) in enumerate(boxes) if box.id == 'jp2c']
if len(jp2c_lst) == 0:
msg = "A codestream box must be defined in the outermost "
msg += "list of boxes."
raise IOError(msg)
jp2c_idx = jp2c_lst[0]
if jp2h_idx >= jp2c_idx:
msg = "The codestream box must be preceeded by a jp2 header box."

View file

@ -310,6 +310,24 @@ class TestJp2Boxes(unittest.TestCase):
with self.assertRaises(IOError):
j2k.wrap(tfile.name, boxes=boxes)
def test_missing_codestream(self):
j2k = Jp2k(self.raw_codestream)
c = j2k.get_codestream()
height = c.segment[1].Ysiz
width = c.segment[1].Xsiz
num_components = len(c.segment[1].XRsiz)
jP = JPEG2000SignatureBox()
ftyp = FileTypeBox()
jp2h = JP2HeaderBox()
ihdr = ImageHeaderBox(height=height, width=width,
num_components=num_components)
jp2h.box = [ihdr]
boxes = [jP, ftyp, jp2h]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
with self.assertRaises(IOError):
j2k.wrap(tfile.name, boxes=boxes)
def test_missing_colr_box(self):
j2k = Jp2k(self.raw_codestream)
c = j2k.get_codestream()

View file

@ -76,6 +76,8 @@ class TestJp2k(unittest.TestCase):
def setUp(self):
self.jp2file = pkg_resources.resource_filename(glymur.__name__,
"data/nemo.jp2")
self.j2kfile = pkg_resources.resource_filename(glymur.__name__,
"data/goodstuff.j2k")
def tearDown(self):
pass
@ -152,6 +154,27 @@ class TestJp2k(unittest.TestCase):
subsetdata = j.read(area=(0, 0, 512, 512))
np.testing.assert_array_equal(tiledata, subsetdata)
def test_write_srgb_without_mct(self):
j2k = Jp2k(self.j2kfile)
expdata = j2k.read()
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb')
ofile.write(expdata, mct=False)
actdata = ofile.read()
np.testing.assert_array_equal(actdata, expdata)
c = ofile.get_codestream()
self.assertEqual(c.segment[2].SPcod[3], 0) # no mct
def test_write_grayscale_with_mct(self):
# MCT usage makes no sense for grayscale images.
j2k = Jp2k(self.j2kfile)
expdata = j2k.read()
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError):
ofile.write(expdata[:,:,0], mct=True)
def test_write_cprl(self):
# Issue 17
j = Jp2k(self.jp2file)