Merge branch 'issue104' into devel

Conflicts:
	CHANGES.txt
	docs/source/how_do_i.rst
	glymur/codestream.py
	glymur/jp2box.py
	glymur/test/test_jp2box.py
	glymur/test/test_jp2k.py
This commit is contained in:
jevans 2014-02-08 20:29:52 -05:00
commit 79d2969acc
20 changed files with 1358 additions and 993 deletions

View file

@ -71,7 +71,7 @@ The **append** method can add an XML box as shown below::
An existing raw codestream (or JP2 file) can be wrapped (re-wrapped) in a
user-defined set of JP2 boxes. To get just a minimal JP2 jacket on the
codestream provided by `goodstuff.j2k` (a file consisting of a raw codestream),
you can use the **wrap** method with no box argument: ::
you can use the :py:meth:`wrap` method with no box argument: ::
>>> import glymur
>>> jfile = glymur.data.goodstuff()
@ -108,8 +108,9 @@ JP2 header superbox.
XML boxes are not in the minimal set of box requirements for the JP2 format, so
in order to add an XML box into the mix before the codestream box, we'll need to
re-specify all of the boxes. If you already have a JP2 jacket in place, you can just reuse that,
though. Take the following example content in an XML file `favorites.xml` : ::
re-specify all of the boxes. If you already have a JP2 jacket in place,
you can just reuse that, though. Take the following example content in
an XML file `favorites.xml` : ::
<?xml version="1.0"?>
<favorite_things>
@ -152,10 +153,10 @@ the following will work. ::
. (truncated)
.
As to the question of which method you should use, **append** or **wrap**,
to add metadata, you should keep in mind that **wrap** produces a new JP2 file,
while **append** modifies an existing file and is currently limited to XML
boxes.
As to the question of which method you should use, :py:meth:`append` or
:py:meth:`wrap`, to add metadata, you should keep in mind that :py:meth:`wrap`
produces a new JP2 file, while :py:meth:`append` modifies an existing file and
is currently limited to XML and UUID boxes.
... create an image with an alpha layer?
========================================
@ -219,32 +220,142 @@ Here's how the Preview application on the mac shows the RGBA image.
.. image:: goodstuff_alpha.png
work with XMP UUIDs?
====================
... work with XMP UUIDs?
========================
The example JP2 file shipped with glymur has an XMP UUID. ::
>>> import glymur
>>> j = glymur.Jp2k(glymur.data.nemo())
>>> print(j.box[4])
UUID Box (uuid) @ (715, 2412)
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
UUID Data:
<ns0:xmpmeta xmlns:ns0="adobe:ns:meta/" xmlns:ns2="http://ns.adobe.com/xap/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ns0:xmptk="XMP Core 4.4.0-Exiv2">
>>> print(j.box[3]) # formatting added to the XML below
<ns0:xmpmeta xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:ns0="adobe:ns:meta/"
xmlns:ns2="http://ns.adobe.com/xap/1.0/"
xmlns:ns3="http://ns.adobe.com/tiff/1.0/"
xmlns:ns4="http://ns.adobe.com/exif/1.0/"
xmlns:ns5="http://ns.adobe.com/photoshop/1.0/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
ns0:xmptk="Exempi + XMP Core 5.1.2">
<rdf:RDF>
<rdf:Description ns2:CreatorTool="glymur" rdf:about="" />
</rdf:RDF>
</ns0:xmpmeta>
<rdf:Description rdf:about="">
<ns2:CreatorTool>Google</ns2:CreatorTool>
<ns2:CreateDate>2013-02-09T14:47:53</ns2:CreateDate>
</rdf:Description>
Since the UUID data in this case is returned as an ElementTree instance, one can
use ElementTree to access the data. For example, to extract the
**CreatorTool** attribute value, the following would work::
.
.
.
</ns0:xmpmeta>
>>> xmp = j.box[4].data
>>> ns0 = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}'
>>> ns1 = '{http://ns.adobe.com/xap/1.0/}'
>>> name = '{0}RDF/{0}Description'.format(ns0)
Since the UUID data in this case is returned as an ElementTree instance,
one can use ElementTree from the standard library to access the data.
For example, to extract the **CreatorTool** attribute value, one could do the
following
>>> xmp = j.box[3].data.packet
>>> rdf = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}'
>>> ns2 = '{http://ns.adobe.com/xap/1.0/}'
>>> name = '{0}RDF/{0}Description/{1}CreatorTool'.format(rdf, ns2)
>>> elt = xmp.find(name)
>>> elt
<Element '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Description' at 0xb4baa93c>
>>> elt.attrib['{0}CreatorTool'.format(ns1)]
'glymur'
<Element '{http://ns.adobe.com/xap/1.0/#}CreatorTool' at 0xb50684a4>
>>> elt.text
'Google'
But that would be painful. A better solution is to install the Python XMP
Toolkit (make sure it is version 2.0)::
>>> from libxmp import XMPMeta
>>> from libxmp.consts import XMP_NS_XMP as NS_XAP
>>> meta = XMPMeta()
>>> meta.parse_from_str(j.box[3].raw_data.decode('utf-8'))
>>> meta.get_property(NS_XAP, 'CreatorTool')
'Google'
Where the Python XMP Toolkit can really shine, though, is when you are
converting an image from another format such as TIFF or JPEG into JPEG 2000.
For example, if you were to be converting the TIFF image found at
http://photojournal.jpl.nasa.gov/tiff/PIA17145.tif info JPEG 2000::
>>> import skimage.io
>>> image = skimage.io.imread('PIA17145.tif')
>>> from glymur import Jp2k
>>> jp2 = Jp2k('PIA17145.jp2', 'wb')
>>> jp2.write(image)
Next you can extract the XMP metadata.
>>> from libxmp import XMPFiles
>>> xf = XMPFiles()
>>> xf.open_file('PIA17145.tif')
>>> xmp = xf.get_xmp()
>>> print(xmp)
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Exempi + XMP Core 5.1.2">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:tiff="http://ns.adobe.com/tiff/1.0/">
<tiff:ImageWidth>1016</tiff:ImageWidth>
<tiff:ImageLength>1016</tiff:ImageLength>
<tiff:BitsPerSample>
<rdf:Seq>
<rdf:li>8</rdf:li>
</rdf:Seq>
</tiff:BitsPerSample>
<tiff:Compression>1</tiff:Compression>
<tiff:PhotometricInterpretation>1</tiff:PhotometricInterpretation>
<tiff:SamplesPerPixel>1</tiff:SamplesPerPixel>
<tiff:PlanarConfiguration>1</tiff:PlanarConfiguration>
<tiff:ResolutionUnit>2</tiff:ResolutionUnit>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:description>
<rdf:Alt>
<rdf:li xml:lang="x-default">converted PNM file</rdf:li>
</rdf:Alt>
</dc:description>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>
If you are familiar with TIFF, you can verify that there's no XMP tag in the
TIFF file, but the Python XMP Toolkit takes advantage of the TIFF header
structure to populate an XMP packet for you. If you were working with a JPEG
file with Exif metadata, that information would be included in the XMP packet
as well. Now you can append the XMP packet in a UUIDBox. In order to do this,
though, you have to know the UUID that signifies XMP data.::
>>> import uuid
>>> xmp_uuid = uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')
>>> box = glymur.jp2box.UUIDBox(xmp_uuid, str(xmp).encode())
>>> jp2.append(box)
>>> print(jp2.box[-1])
UUID Box (uuid) @ (592316, 1053)
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
UUID Data:
<ns0:xmpmeta xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ns0="adobe:ns:meta/" xmlns:ns2="http://ns.adobe.com/tiff/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ns0:xmptk="Exempi + XMP Core 5.1.2">
<rdf:RDF>
<rdf:Description rdf:about="">
<ns2:ImageWidth>1016</ns2:ImageWidth>
<ns2:ImageLength>1016</ns2:ImageLength>
<ns2:BitsPerSample>
<rdf:Seq>
<rdf:li>8</rdf:li>
</rdf:Seq>
</ns2:BitsPerSample>
<ns2:Compression>1</ns2:Compression>
<ns2:PhotometricInterpretation>1</ns2:PhotometricInterpretation>
<ns2:SamplesPerPixel>1</ns2:SamplesPerPixel>
<ns2:PlanarConfiguration>1</ns2:PlanarConfiguration>
<ns2:ResolutionUnit>2</ns2:ResolutionUnit>
</rdf:Description>
<rdf:Description rdf:about="">
<dc:description>
<rdf:Alt>
<rdf:li xml:lang="x-default">converted PNM file</rdf:li>
</rdf:Alt>
</dc:description>
</rdf:Description>
</rdf:RDF>
</ns0:xmpmeta>

View file

@ -7,11 +7,9 @@ which allows one to read and write JPEG 2000 files from within Python.
Glymur supports both reading and writing of JPEG 2000 images, but writing
JPEG 2000 images is currently limited to images that can fit in memory
Of particular focus is retrieval of metadata. Reading Exif UUIDs is supported,
as is reading XMP UUIDs as the XMP data packet is just XML. There is
some very limited support for reading JPX metadata. For instance,
**asoc** and **labl** boxes are recognized, so GMLJP2 metadata can
be retrieved from such JPX files.
In regards to metadata, most JP2 boxes are properly interpreted.
Certain optional JP2 boxes can also be written, including XML boxes and
XMP UUIDs. There is some very limited support for reading JPX metadata.
Glymur 0.6 works on Python versions 2.7, 3.3 and 3.4. If you have 2.6, you should
use the 0.5 series.
@ -21,8 +19,8 @@ OpenJPEG Installation
Glymur will read JPEG 2000 images with versions 1.3, 1.4, 1.5, 2.0,
and the trunk/development version of OpenJPEG. Writing images is
only supported with the 1.5 or better, however, and the trunk/development
version is strongly recommended. For more information about OpenJPEG,
please consult http://www.openjpeg.org.
version of OpenJPEG is strongly recommended. For more information about
OpenJPEG, please consult http://www.openjpeg.org.
If you use MacPorts or if you have a sufficiently recent version of
Linux, your package manager should already provide you with a version of