Closes #57
This commit is contained in:
parent
f70dd87608
commit
881132fbef
3 changed files with 62 additions and 7 deletions
|
|
@ -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."
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue