Skip to content
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ their contents.
the JPEG XS file format. Additionally supported flags:

```-C```, ```--ignore-codestream```: Don't parse the Codestream boxes.
```-B <limit>```, ```--buffer-print-limit (limit)```: Output hex dump of
application boxes larger than the specified size (default 256 bytes)

* ```jp2box.py```

Expand Down
24 changes: 14 additions & 10 deletions icc.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env python

# -*- coding: utf-8 -*-
"""
JPEG codestream-parser (All-JPEG Codestream/File Format Parser Tools)
Expand Down Expand Up @@ -362,13 +364,13 @@ def print_sf32(buf, indent):

def print_tag(buf, size, indent):
sign = buf[0:4]
print_indent("Tag type: %s" % sign, indent)
print_indent("Tag type: %s" % sign.decode('ascii'), indent)
print_indent("Reserved: %d" % ordl(buf[4:8]), indent)
if sign == "desc":
size = ordl(buf[8:12])
print_indent("Profile description: %s" % buf[12:12 + size - 1], indent)
print_indent("Profile description: %s" % buf[12:12 + size - 1].decode('ascii'), indent)
elif sign == "text":
print_indent("Text: %s" % buf[8:len(buf) - 1], indent)
print_indent("Text: %s" % buf[8:len(buf) - 1].decode('ascii'), indent)
elif sign == "XYZ ":
count = (len(buf) - 8) // 12
off = 8
Expand Down Expand Up @@ -405,21 +407,21 @@ def print_tag(buf, size, indent):

def print_desctag(buf, indent):
size = ordl(buf[8:12])
print_indent("Profile description: %s" % buf[12:12 + size])
print_indent("Profile description: %s" % buf[12:12 + size].decode('ascii'))


def parse_icc(indent, buf):
indent += 1
print_indent("ICC profile size : %d bytes" % ordl(buf[0:4]), indent)
print_indent("Preferred CMM type : %d" % ordl(buf[0:8]), indent)
print_indent("Preferred CMM type : %d" % ordl(buf[4:8]), indent)
print_indent("ICC major version : %d" % ordb(buf[8]), indent)
print_indent("ICC minor version : %d" % ordb(buf[9]), indent)
print_indent("Profile class : %s" % buf[12:16], indent)
print_indent("Canonical input space : %s" % buf[16:20], indent)
print_indent("Profile connection space: %s" % buf[20:24], indent)
print_indent("Profile class : %s" % buf[12:16].decode('ascii'), indent)
print_indent("Canonical input space : %s" % buf[16:20].decode('ascii'), indent)
print_indent("Profile connection space: %s" % buf[20:24].decode('ascii'), indent)
print_indent("Creation date :", indent)
print_datetime(buf[24:36], indent + 1)
print_indent("Profile signature : %s" % buf[36:40], indent)
print_indent("Profile signature : %s" % buf[36:40].decode('ascii'), indent)
print_indent("Platform singature : %s" % readsignature(buf[40:44]), indent)
print_indent("Profile flags : 0x%08x" % ordl(buf[44:48]), indent)
print_indent("Device manufacturer : %s" % readsignature(buf[48:52]), indent)
Expand Down Expand Up @@ -448,7 +450,9 @@ def parse_icc(indent, buf):
for i in range(count):
offset = ordl(buf[off + 4:off + 8])
size = ordl(buf[off + 8:off + 12])
print_indent("ICC tag %s at offset %d size %d:" % (buf[off:off + 4], offset, size), indent + 1)
print_indent("ICC tag %s at offset %d size %d:" %
(buf[off:off + 4].decode('ascii'), offset, size),
indent + 1)
print_tag(buf[offset:offset + size], size, indent + 2)
off += 12

Expand Down
8 changes: 5 additions & 3 deletions jp2box.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env python

# -*- coding: utf-8 -*-
"""
JPEG codestream-parser (All-JPEG Codestream/File Format Parser Tools)
Expand Down Expand Up @@ -34,9 +36,9 @@ def print_versflags(self, buf):

def new_box(self, description):
if self.indent == 0:
self.print_indent("%-8s: New Box: %s" % (str(self.offset - self.hdrsize), description), False)
self.print_indent("%-8s: New Box: %s " % (str(self.offset - self.hdrsize), description), False)
else:
self.print_indent("%-8s: Sub Box: %s" % (str(self.offset - self.hdrsize), description), False)
self.print_indent("%-8s: Sub Box: %s " % (str(self.offset - self.hdrsize), description), False)
self.indent += 1

def end_box(self):
Expand Down Expand Up @@ -89,7 +91,7 @@ def parse_header(self):
elif len(length) < 4:
raise UnexpectedEOF()
length = ordl(length)
id = self.infile.read(4)
id = self.infile.read(4).decode('ascii')
if len(id) < 4:
raise UnexpectedEOF
self.offset += 8
Expand Down
26 changes: 15 additions & 11 deletions jp2codestream.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env python

# -*- coding: utf-8 -*-
"""
JPEG codestream-parser (All-JPEG Codestream/File Format Parser Tools)
Expand Down Expand Up @@ -44,13 +46,13 @@ def parse(self, buf, startpos):
self.offset = startpos

# Read SOC Marker
if (len(self.buffer) - self.pos < 2) or ordw(self.buffer[self.pos + 0:self.pos + 1]) != 0xff4f:
if (len(self.buffer) - self.pos < 2) or ordw(self.buffer[self.pos + 0:self.pos + 2]) != 0xff4f:
raise RequiredMarkerMissing("SOC")
self.pos += 2
self.read_SOC()

# Read SIZ Marker
if (len(self.buffer) - self.pos < 2) or ordw(self.buffer[self.pos + 0:self.pos + 1]) != 0xff51:
if (len(self.buffer) - self.pos < 2) or ordw(self.buffer[self.pos + 0:self.pos + 2]) != 0xff51:
raise RequiredMarkerMissing("SIZ")
self.pos += 2
self.read_SIZ()
Expand Down Expand Up @@ -99,7 +101,7 @@ def parse(self, buf, startpos):
self._print_indent("Overhead : %d bytes (%d%%)" % (oh, 100 * oh / l))

def load_marker(self, file, marker):
mrk = ordw(marker[0:1])
mrk = ordw(marker[0:2])
if 0xff30 <= mrk <= 0xff3f:
self.buffer = marker
elif mrk in [0xff93, 0xff4f, 0xffd9, 0xff92]:
Expand Down Expand Up @@ -135,15 +137,15 @@ def stream_parse(self, file, startpos):

# Read SOC Marker
self.load_buffer(file)
if ordw(self.buffer[self.pos + 0:self.pos + 1]) != 0xff4f:
if ordw(self.buffer[self.pos + 0:self.pos + 2]) != 0xff4f:
raise RequiredMarkerMissing("SOC")
self.pos += 2
self.read_SOC()
self.offset += len(self.buffer)

# Read SIZ Marker
self.load_buffer(file)
if ordw(self.buffer[self.pos + 0:self.pos + 1]) != 0xff51:
if ordw(self.buffer[self.pos + 0:self.pos + 2]) != 0xff51:
raise RequiredMarkerMissing("SIZ")
self.pos += 2
self.read_SIZ()
Expand All @@ -162,7 +164,7 @@ def stream_parse(self, file, startpos):
self.load_buffer(file)

# Read Tile Parts
while len(self.buffer) >= 2 and ordw(self.buffer[0:1]) == 0xff90:
while len(self.buffer) >= 2 and ordw(self.buffer[0:2]) == 0xff90:
self.pos += 2
self.read_SOT()
self.offset += len(self.buffer)
Expand Down Expand Up @@ -331,7 +333,7 @@ def read_SIZ(self):
raise InvalidSizedMarker("SIZ")

# Read Csiz
components = (size - 38) / 3
components = (size - 38) // 3
self.csiz = ordw(self.buffer[self.pos + 36:self.pos + 38])
if self.csiz != components:
raise InvalidSizedMarker("SIZ")
Expand Down Expand Up @@ -523,7 +525,7 @@ def read_QCD(self):
if sqcd & 0x1f == 1 or sqcd & 0x1f == 2:
if subbands % 2 != 0:
raise InvalidSizedMarker("QCD")
subbands /= 2
subbands = int(subbands / 2)
for i in range(subbands):
mantissa = 1.0
if sqcd & 0x1f == 1 or sqcd & 0x1f == 2:
Expand Down Expand Up @@ -569,7 +571,7 @@ def read_QCC(self):
if sqcc & 0x1f == 1 or sqcc & 0x1f == 2:
if subbands % 2 != 0:
raise InvalidSizedMarker("QCC")
subbands /= 2
subbands = int(subbands / 2)
for i in range(subbands):
mantissa = 1.0
if sqcc & 0x1f == 1 or sqcc & 0x1f == 2:
Expand Down Expand Up @@ -960,7 +962,7 @@ def read_MCT(self):
len -= 2
if len % l != 0:
raise InvalidSizedMarker("MCT")
count = len / l
count = int(len / l)
self.print_header("Number of entries", str(count))
for i in range(count):
if type & 12 == 0:
Expand Down Expand Up @@ -1092,7 +1094,9 @@ def read_COM(self):
s = "unknown"
self.print_header("Registration", s)
if reg == 1:
self.print_header("Comment", self.buffer[self.pos + 4:self.pos + self.size])
self.print_header(
"Comment",
self.buffer[self.pos + 4:self.pos + self.size].decode('utf-8'))
else:
self.print_header("Comment", "...")
self._end_marker()
Expand Down
45 changes: 26 additions & 19 deletions jp2file.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env python

# -*- coding: utf-8 -*-
"""
JPEG codestream-parser (All-JPEG Codestream/File Format Parser Tools)
Expand Down Expand Up @@ -93,7 +95,7 @@ def parse_rreq_box(box, buf):
for i in range(nsf):
sf = ordw(buf[off:off + 2])
off += 2
box.print_indent(" Standard flag :", False)
box.print_indent(" Standard flag : ", False)
if sf == 0:
print("writer could not fully understand file")
elif sf == 1:
Expand Down Expand Up @@ -334,7 +336,7 @@ def parse_filetype_box(box, buffer):
# Print MinV (minor version)
box.print_indent("Minor version: %d" % ordl(buffer[4:8]))
# Print CL (Compatibility List)
box.print_indent("Compatibility:", False)
box.print_indent("Compatibility: ", False)
clsize = (len(buffer) - 8) // 4
for i in range(clsize):
offset = i * 4 + 8
Expand Down Expand Up @@ -391,12 +393,12 @@ def parse_image_header_box(box, buf):
box.print_indent("Components : %d" % ordw(buf[8:10]))
box.print_indent("Bits Per Component : %d" %
((ordb(buf[10]) & 0x7f) + 1))
box.print_indent("Signed Components :", 0)
box.print_indent("Signed Components : ", 0)
if ordb(buf[10]) & 0x80:
print("yes")
else:
print("no")
box.print_indent("Compression Type :", 0)
box.print_indent("Compression Type : ", 0)
if ordb(buf[11]) == 0:
print("uncompressed")
elif ordb(buf[11]) == 1:
Expand All @@ -422,15 +424,15 @@ def parse_image_header_box(box, buf):
elif ordb(buf[11]) == 12:
print("JPEG XS")
else:
print("unknown (%s)" % ordb(buf[11]))
box.print_indent("Unknown Colourspace :", 0)
print("unknown (%d)" % ordb(buf[11]))
box.print_indent("Unknown Colourspace : ", 0)
if ordb(buf[12]) == 0:
print("no")
elif ordb(buf[12]) == 1:
print("yes")
else:
print("invalid value")
box.print_indent("Intellectual Property:", 0)
box.print_indent("Intellectual Property: ", 0)
if ordb(buf[13]) == 0:
print("no")
elif ordb(buf[13]) == 1:
Expand Down Expand Up @@ -475,7 +477,7 @@ def parse_colorspec_box(box, buffer):
else:
method = ordb(buffer[0])
offset = 3
box.print_indent("Colour Specification Method:", 0)
box.print_indent("Colour Specification Method: ", 0)
if method == 1:
print("enumerated colourspace")
elif method == 2:
Expand All @@ -499,7 +501,7 @@ def parse_colorspec_box(box, buffer):
if len(buffer) != 7 and cs != 19 and cs != 14:
box.print_indent("invalid box")
return
box.print_indent("Colourspace :", 0)
box.print_indent("Colourspace : ", 0)
if cs == 16:
print("sRGB")
elif cs == 17:
Expand Down Expand Up @@ -938,7 +940,7 @@ def parse_cref_box(box, buf):
# size = buffer[4:8]
type = buf[8:12]
if type == "flst":
box.new_box("\"%s\"" % (type))
box.new_box("\"%s\"" % type)
parse_flst_box(box, buf[12:len(buf)])
box.end_box()
else:
Expand All @@ -960,7 +962,7 @@ def parse_xml_box(box, buf):
s = buf
if s[len(s) - 1] == "\0":
s = s[:len(s) - 2]
box.print_indent(s)
box.print_indent(s.decode('utf-8'))


def parse_uuidlist_box(box, buf):
Expand Down Expand Up @@ -1193,7 +1195,7 @@ def parse_hdlr_box(box, buf):
print("Handler reference box")

box.print_versflags(buf)
htyp = buf[8:12]
htyp = buf[8:12].decode('ascii')
if htyp == "vide":
htyp = "video track"
elif htyp == "soun":
Expand Down Expand Up @@ -2106,7 +2108,7 @@ def parse_json_box(box, buf):
s = buf
if s[len(s) - 1] == "\0":
s = s[:len(s) - 2]
box.print_indent(s)
box.print_indent(s.decode('utf-8'))


def parse_superbox(box, boxtype):
Expand Down Expand Up @@ -2135,13 +2137,15 @@ def superbox_hook(box, id, length):
else:
type = box.infile.read(2)
box.infile.seek(box.offset)
if ordw(type[0:1]) == 0x574d:
if ordw(type[0:2]) == 0x574d:
jxr = JXRCodestream(box.infile, 1)
jxr.parse()
elif ordw(type[0:1]) == 0xffd8:
cs = JPGCodestream(indent=box.indent + 1, hook=superbox_hook)
elif ordw(type[0:2]) == 0xffd8:
cs = JPGCodestream(
indent=box.indent + 1, hook=superbox_hook,
buffer_print_limit=buffer_print_limit)
cs.stream_parse(box.infile, box.offset)
elif ordw(type[0:1]) == 0xff10:
elif ordw(type[0:2]) == 0xff10:
cs = JXSCodestream(indent=box.indent + 1)
cs.stream_parse(box.infile, box.offset)
else:
Expand Down Expand Up @@ -2373,12 +2377,15 @@ def superbox_hook(box, id, length):


ignore_codestream = False
buffer_print_limit = 256
if __name__ == "__main__":
# Read Arguments
args, files = getopt.getopt(sys.argv[1:], "C", "ignore-codestream")
args, files = getopt.getopt(sys.argv[1:], "CB:", ["ignore-codestream", "buffer-print-limit="])
for (o, a) in args:
if o in ("-C", "--ignore-codestream"):
ignore_codestream = True
if o in ("-B", "--buffer-print-limit"):
buffer_print_limit = int(a)

if len(files) != 1:
print("Usage: [OPTIONS] %s FILE" % (sys.argv[0]))
Expand All @@ -2398,7 +2405,7 @@ def superbox_hook(box, id, length):
jp2 = JP2Codestream()
jp2.stream_parse(file, 0)
elif ordw(type) == 0xffd8:
jpg = JPGCodestream(hook=superbox_hook)
jpg = JPGCodestream(hook=superbox_hook, buffer_print_limit=buffer_print_limit)
jpg.stream_parse(file, 0)
elif ordw(type) == 0xff10:
jxs = JXSCodestream()
Expand Down
Loading