def parse_scan(self, file): self._new_marker("SOS", "Start of Scan") if len(self.buffer) < 2 + 2 + 1 + 1: raise InvalidSizedMarker("SOS") ns = ordb(self.buffer[4]) if len(self.buffer) != 2 + 6 + 2 * ns: raise InvalidSizedMarker("SOS") self._print_indent("Number of Components : %d" % ns) self.pos = 5 for i in range(ns): self._print_indent("Component % d : %d" % (i, ordb(self.buffer[self.pos]))) self.pos = self.pos + 1 table = ordb(self.buffer[self.pos]) if self.frametype == 0xfff7: self._print_indent("Mapping %d : %d" % (i, table)) else: dc = table >> 4 ac = table & 0x0f self._print_indent("DC table %d : %d" % (i, dc)) if self.frametype in [0xffc3, 0xffc7, 0xffcb, 0xffcf]: self._print_indent("Reserved %d : %d" % (i, ac)) else: self._print_indent("AC table %d : %d" % (i, ac)) self.pos += 1 sstart = ordb(self.buffer[self.pos]) sstop = ordb(self.buffer[self.pos + 1]) self.pos += 2 if self.frametype == 0xfff7: self._print_indent("Near : %d" % sstart) if sstop == 0: scantype = "plane interleaved" elif sstop == 1: scantype = "line interleaved" elif sstop == 2: scantype = "sample interleaved" else: scantype = "invalid, type %d" % sstop self._print_indent("Scan type : %s" % scantype) elif self.frametype in [0xffc3, 0xffc7, 0xffcb, 0xffcf]: self._print_indent("Predictor : %d" % sstart) self._print_indent("Reserved : %d" % sstop) else: self._print_indent("Scan start : %d" % sstart) self._print_indent("Scan stop : %d" % sstop) ah = ordb(self.buffer[self.pos]) al = ah & 0x0f ah >>= 4 self._print_indent("Shift high : %d" % ah) self._print_indent("Shift low : %d" % al) marker = self.parse_data(file, self.frametype == 0xfff7) self._end_marker() return marker
def read_MCO(self): self._new_marker("MCO", "Multiple component transform ordering") if self.size < 3: raise InvalidSizedMarker("MCO") nmco = ordb(self.buffer[self.pos + 2]) if self.size != nmco + 3: raise InvalidSizedMarker("MCO") self.print_header("Number of component collections", "%d" % nmco) self.pos += 3 for i in range(nmco): self.print_header("MCC collection %d" % i, str(ordb(self.buffer[self.pos]))) self.pos += 1 self._end_marker()
def read_QCC(self): self._new_marker("QCC", "Quantization component") if self.size < 4: raise InvalidSizedMarker("QCC") if self.csiz <= 256: index = ordb(self.buffer[self.pos + 2]) self.pos += 3 else: index = ordw(self.buffer[self.pos + 2:self.pos + 4]) self.pos += 4 self.print_header("Index", str(index)) sqcc = ordb(self.buffer[self.pos + 0]) self.pos += 1 if sqcc & 0x1f == 0: s = "none" elif sqcc & 0x1f == 1: s = "scalar derived" elif sqcc & 0x1f == 2: s = "scalar expounded" else: s = "unknown" self.print_header("Quantization Type", s) self.print_header("Guard Bits", str(sqcc >> 5)) if self.csiz <= 256: subbands = self.size - 4 else: subbands = self.size - 5 if sqcc & 0x1f == 1 or sqcc & 0x1f == 2: if subbands % 2 != 0: raise InvalidSizedMarker("QCC") subbands = int(subbands / 2) for i in range(subbands): mantissa = 1.0 if sqcc & 0x1f == 1 or sqcc & 0x1f == 2: spqcd = ordw(self.buffer[self.pos + 0:self.pos + 2]) self.pos += 2 mantissa = 1.0 + ((spqcd & 0x7ff) / 2048.0) self.print_header("Mantissa #%d" % i, str(spqcd & 0x7ff)) exponent = spqcd >> 11 else: spqcd = ordb(self.buffer[self.pos + 0]) self.pos += 1 exponent = spqcd >> 3 self.print_header("Exponent #%d" % i, str(exponent)) self.print_header("Delta #%d" % i, mantissa * pow(2.0, -exponent)) self._end_marker()
def parse_CWD(self): self._new_marker("CWD", "Component Dependent Wavelet Decomposition Marker") if len(self.buffer) != 2 + 2 + 1: raise InvalidSizedMarker("Size of the CWD marker shall be 3 bytes") sd = ord(self.buffer[4:5]) self.excluded = sd self._print_indent("Components excluded from DWT : %s" % sd) self._end_marker()
def read_SOP(self): self._new_marker("SOP", "Start of packet") if self.size != 4: raise InvalidSizedMarker("SOP") self.print_header("Sequence", str(ordw(self.buffer[self.pos + 2:self.pos + 4]))) self._end_marker() self.pos += self.size
def parse_SLC(self): self._new_marker("SLC", "Slice Header") if len(self.buffer) != 2 + 4: raise InvalidSizedMarker("Size of the SLC marker shall be 4 bytes") self._print_indent("Slice index : %s" % ordw(self.buffer[4:6])) self.check_profile() self.check_level() self._end_marker()
def read_QCD(self): self._new_marker("QCD", "Quantization default") if self.size < 4: raise InvalidSizedMarker("QCD") sqcd = ordb(self.buffer[self.pos + 2]) if sqcd & 0x1f == 0: s = "none" elif sqcd & 0x1f == 1: s = "scalar derived" elif sqcd & 0x1f == 2: s = "scalar expounded" elif sqcd & 0x1f == 3: s = "variable deadzone scalar derived" elif sqcd & 0x1f == 4: s = "variable deadzone scalar expounded" elif sqcd & 0x1f == 5: s = "variable deadzone scalar expounded" elif sqcd & 0x1f == 9: s = "trellis quantization derived" elif sqcd & 0x1f == 10: s = "trellis quantization expounded" else: s = "unknown" self.print_header("Quantization Type", s) self.print_header("Guard Bits", str(sqcd >> 5)) subbands = self.size - 3 if sqcd & 0x1f == 1 or sqcd & 0x1f == 2: if subbands % 2 != 0: raise InvalidSizedMarker("QCD") subbands = int(subbands / 2) for i in range(subbands): mantissa = 1.0 if sqcd & 0x1f == 1 or sqcd & 0x1f == 2: spqcd = ordw(self.buffer[self.pos + i * 2 + 3:self.pos + i * 2 + 5]) mantissa = 1.0 + ((spqcd & 0x7ff) / 2048.0) self.print_header("Mantissa #%d" % i, str(spqcd & 0x7ff)) exponent = spqcd >> 11 else: spqcd = ordb(self.buffer[self.pos + i + 3]) exponent = spqcd >> 3 self.print_header("Exponent #%d" % i, str(exponent)) self.print_header("Delta #%d" % i, str(mantissa * pow(2.0, -exponent))) self._end_marker() self.pos += self.size
def read_PPM(self): self._new_marker("PPM", "Packed packet headers, main header") if self.size < 3: raise InvalidSizedMarker("PPM") self.print_header("Index Zppm", str(ordb(self.buffer[self.pos + 2]))) self.print_header("Marker Length Lppm", str(self.size)) self._end_marker() self.pos += self.size
def read_PLT(self): self._new_marker("PLT", "Packet length, tile-part header") if self.size < 3: raise InvalidSizedMarker("PLT") self.print_header("Index Zplt", str(ordb(self.buffer[self.pos + 2]))) self.print_header("Marker size Lplt", "%d bytes" % self.size) self._end_marker() self.pos += self.size
def read_SOT(self): self._new_marker("SOT", "Start of tile-part") if len(self.buffer) - self.pos < 10: raise InvalidSizedMarker("SOT") size = ordw(self.buffer[self.pos + 0:self.pos + 2]) if size != 10: raise InvalidSizedMarker("SOT") self.print_header("Tile", str(ordw(self.buffer[self.pos + 2:self.pos + 4]))) length = ordl(self.buffer[self.pos + 4:self.pos + 8]) self.print_header("Length", str(length)) self.print_header("Index", str(ordb(self.buffer[self.pos + 8]))) if ordb(self.buffer[self.pos + 9]) == 0: s = "unknown" else: s = str(ordb(self.buffer[self.pos + 9])) self.print_header("Tile-Parts", s) self._end_marker() self.pos += 10
def read_PLM(self): self._new_marker("PLM", "Packet length, main header") if self.size < 3: raise InvalidSizedMarker("PLM") self.print_header("Index", str(ordb(self.buffer[self.pos + 2]))) self.pos += 3 self.size -= 3 self.print_header("Length", str(self.size)) self._end_marker() self.pos += self.size
def read_POC(self): self._new_marker("POC", "Progression order change") if self.size < 9: raise InvalidSizedMarker("POC") if self.csiz <= 256: if (self.size - 2) % 7 != 0: raise InvalidSizedMarker("POC") num = (self.size - 2) / 7 else: if (self.size - 2) % 9 != 0: raise InvalidSizedMarker("POC") num = (self.size - 2) / 9 self.pos += 2 for i in range(num): self.print_header("Resolution Level Index #%d (Start)" % i, str(ordb(self.buffer[self.pos]))) if self.csiz <= 256: rspoc = ordb(self.buffer[self.pos + 1]) self.pos += 2 else: rspoc = ordw(self.buffer[self.pos + 1:self.pos + 3]) self.pos += 3 self.print_header("Component Index #%d (Start)" % i, str(rspoc)) lyepoc = ordw(self.buffer[self.pos + 0:self.pos + 2]) self.print_header("Layer Index #%d (End)" % i, str(lyepoc)) self.print_header("Resolution Level Index #%d (End)" % i, str(ordb(self.buffer[self.pos + 2]))) if self.csiz <= 256: cepoc = ordb(self.buffer[self.pos + 3]) if cepoc == 0: cepoc = 256 self.pos += 4 else: cepoc = ordw(self.buffer[self.pos + 3:self.pos + 5]) if cepoc == 0: cepoc = 16384 self.pos += 5 self.print_header("Component Index #%d (End)" % i, str(cepoc)) po = self.progression_order(ordb(self.buffer[self.pos])) self.print_header("Progression Order #%d" % i, po) self.pos += 1 self._end_marker()
def read_TLM(self): self._new_marker("TLM", "Tile-part length") if self.size < 4: raise InvalidSizedMarker("TLM") self.print_header("Index", str(ordb(self.buffer[self.pos + 2]))) stlm = ordb(self.buffer[self.pos + 3]) >> 4 st = stlm & 0x03 sp = (stlm >> 2) & 0x1 if st == 3: raise InvalidMarkerField("TLM", "Stlm") if st == 0: if sp == 0: if (self.size - 4) % 2 != 0: raise InvalidSizedMarker("TLM") tileparts = (self.size - 4) / 2 else: if (self.size - 4) % 4 != 0: raise InvalidSizedMarker("TLM") tileparts = (self.size - 4) / 4 elif st == 1: if sp == 0: if (self.size - 4) % 3 != 0: raise InvalidSizedMarker("TLM") tileparts = (self.size - 4) / 3 else: if (self.size - 4) % 5 != 0: raise InvalidSizedMarker("TLM") tileparts = (self.size - 4) / 5 else: if sp == 0: if (self.size - 4) % 4 != 0: raise InvalidSizedMarker("TLM") tileparts = (self.size - 4) / 4 else: if (self.size - 4) % 6 != 0: raise InvalidSizedMarker("TLM") tileparts = (self.size - 4) / 6 self.pos += 4 ttlm = "" for i in range(tileparts): if st == 0: ttlm = "in order" if st == 1: ttlm = str(ordb(self.buffer[self.pos + 0])) self.pos += 1 elif st == 2: ttlm = str(ordw(self.buffer[self.pos + 0:self.pos + 2])) self.pos += 2 self.print_header("Tile index #%d" % i, ttlm) if sp == 0: length = ordw(self.buffer[self.pos + 0:self.pos + 2]) self.pos += 2 else: length = ordl(self.buffer[self.pos + 0:self.pos + 4]) self.pos += 4 self.print_header("Length #%d" % i, str(length)) self._end_marker()
def read_CRG(self): self._new_marker("CRG", "Component registration") if self.size != self.csiz * 4 + 2: raise InvalidSizedMarker("CRG") self.pos += 2 for i in range(self.csiz): x = ordw(self.buffer[self.pos + 0:self.pos + 2]) y = ordw(self.buffer[self.pos + 2:self.pos + 4]) self.print_header("Offset #%d" % i, "%dx%d" % (x, y)) self.pos += 4 self._end_marker()
def read_CAP(self): self._new_marker("CAP", "Extended Capabilities Marker") pcap = ordl(self.buffer[self.pos + 2:self.pos + 6]) offs = self.pos + 6 for i in range(32): if pcap & (1 << (32 - i)): if offs >= self.pos + self.size: raise InvalidSizedMarker("CAP") self.print_header("Extended capabilities for part %d" % i, "0x%x" % (ordw(self.buffer[offs:offs + 2]))) offs += 2 self._end_marker() self.pos += self.size
def parse_NLT(self): self._new_marker("NLT", "Nonlinearity Marker") tnlt = ordb(self.buffer[4]) if tnlt == 1: self.nlt = "quadratic" self._print_indent("NLT Type : quadratic") if len(self.buffer) != 2 + 2 + 1 + 2: raise InvalidSizedMarker("Size of the NLT marker shall be 5 bytes") t1 = ordw(self.buffer[5:7]) self._print_indent("DC Offset : %s" % t1) elif tnlt == 2: self.nlt = "extended" self._print_indent("NLT Type : extended") if len(self.buffer) != 2 + 12: raise InvalidSizedMarker("Size of NLT marker shall be 12 bytes") t1 = ordl(self.buffer[5:9]) t2 = ordl(self.buffer[9:13]) e = ordb(self.buffer[13]) self._print_indent("Threshold t1 : %s" % t1) self._print_indent("Threshold t2 : %s" % t2) self._print_indent("Slope exponent : %s" % e) self._end_marker()
def read_COC(self): self._new_marker("COC", "Coding style component") if self.csiz <= 256 and self.size < 9 or \ self.csiz > 256 and self.size < 10: raise InvalidSizedMarker("COC") self.pos += 2 # Print Ccoc if self.csiz <= 256: component = ordb(self.buffer[self.pos + 0]) self.pos += 1 else: component = ordw(self.buffer[self.pos + 0:self.pos + 2]) self.pos += 2 self.print_header("Component", str(component)) # Print Scoc prec = ordb(self.buffer[self.pos + 0]) self.pos += 1 if prec == 0: s = "default" elif prec == 1: s = "custom" else: s = "unknown" self.print_header("Precincts", s) # Print SPcoc if prec == 0: if self.csiz <= 256 and self.size != 9 or \ self.csiz > 256 and self.size != 10: raise InvalidSizedMarker("COC") precincts = self.size - 9 if self.csiz > 256: precincts -= 1 self.read_SPco(precincts) self._end_marker()
def read_PPT(self): self._new_marker("PPT", "Packed packet headers, tile-part header") if self.size < 3: raise InvalidSizedMarker("PPT") self.print_header("Index", str(ordb(self.buffer[self.pos + 2]))) self.print_header("Contents", "") self._flush_marker() restlen = self.size - 3 self.pos += 3 cs = JP2Codestream(self._indent + 1) cs.parse_data(self.buffer[self.pos:self.pos + restlen]) self.datacount = self.datacount + cs.datacount self._end_marker() self.pos += restlen
def read_COD(self): self._new_marker("COD", "Coding style default") if self.size < 3: raise InvalidSizedMarker("COD") cod = ordb(self.buffer[self.pos + 2]) self.print_header("Default Precincts of 2^15x2^15", "no" if cod & 0x01 else "yes") self.print_header("SOP Marker Segments", "yes" if cod & 0x02 else "no") self.print_header("EPH Marker Segments", "yes" if cod & 0x04 else "no") self.print_header("Codeblock X offset", "1" if cod & 0x08 else "0") self.print_header("Codeblock Y offset", "1" if cod & 0x10 else "0") self.print_header("All Flags", "%08x" % cod) self.pos += 3 self.read_SGco() self.read_SPco(self.size - 12) self._end_marker()
def parse_CTS(self): self._new_marker("CTS", "Colour Transformation Specification Marker") if len(self.buffer) != 2 + 4: raise InvalidSizedMarker("Size of the CTS marker shall be 4 bytes") cf = ordb(self.buffer[4]) ex = ordb(self.buffer[5]) if cf == 0: xfo = "full" elif cf == 3: xfo = "in-line" else: xfo = "invalid (%d)" % cf self.extent = xfo self._print_indent("Transformation type : %s" % xfo) self._print_indent("Red exponent : %s" % (ex >> 4)) self._print_indent("Blue exponent : %s" % (ex & 0x0f)) self._end_marker()
def load_marker(self, file, marker): mrk = ordw(marker) if 0xff10 <= mrk <= 0xff11: self.buffer = marker elif mrk == 0xff12 or mrk == 0xff13 or mrk == 0xff14 or mrk == 0xff15 or mrk == 0xff16 \ or mrk == 0xff17 or mrk == 0xff18 or mrk == 0xff19 or mrk == 0xff20 or mrk == 0xff50: size = file.read(2) ln = ordw(size) if ln < 2: raise InvalidSizedMarker("Marker too short") self.buffer = marker + size + file.read(ln - 2) if len(self.buffer) != ln + 2: raise UnexpectedEOC() else: raise MisplacedData() self.bytecount += len(self.buffer) self.pos = 0
def load_marker(self, file, marker): mrk = ordw(marker[0:2]) if 0xff30 <= mrk <= 0xff3f: self.buffer = marker elif mrk in [0xff93, 0xff4f, 0xffd9, 0xff92]: self.buffer = marker elif 0xff4f <= mrk <= 0xff93: size = file.read(2) ln = ((ordb(size[0]) << 8) + (ordb(size[1]) << 0)) if ln < 2: raise InvalidSizedMarker("Marker too short") self.buffer = marker + size + file.read(ln - 2) if len(self.buffer) != ln + 2: raise UnexpectedEOC() else: raise MisplacedData() self.bytecount += len(self.buffer) self.pos = 0
def load_marker(self, file, marker): mrk = ordw(marker[0:2]) if 0xffd0 <= mrk <= 0xffd9: self.buffer = marker elif mrk >= 0xffc0 or mrk in [ 0xffb1, 0xffb2, 0xffb3, 0xffb9, 0xffba, 0xffbb ]: size = file.read(2) ln = ordw(size[0:2]) if ln < 2: raise InvalidSizedMarker("Marker too short") self.buffer = marker + size + file.read(ln - 2) if len(self.buffer) != ln + 2: raise UnexpectedEOC() else: raise MisplacedData() self.bytecount += len(self.buffer) self.pos = 0
def read_CPF(self): self._new_marker("CPF", "Corresponding Profile Marker") offs = self.pos + 2 pcan = self.size - 2 if pcan < 0 or pcan & 1: raise InvalidSizedMarker("CPF") cpfnum = -1 bpos = 1 for i in range(0, pcan / 2): cpfnum += ordw(self.buffer[offs:offs + 2]) * bpos bpos *= 65536 offs += 2 if cpfnum == 4095: self.print_header("Corresponding Profile", "to be found in the PRF marker") else: self.print_header("Corresponding Profile", "0x%x" % cpfnum) self._end_marker() self.pos += self.size
def read_NSI(self): self._new_marker("NSI", "Additional Dimension Image and Tile Size") size = ordw(self.buffer[self.pos + 0:self.pos + 2]) if size < 20 or size > 16403: raise InvalidSizedMarker("NSI") ndim = ordb(self.buffer[self.pos + 2]) zsiz = ordl(self.buffer[self.pos + 3:self.pos + 7]) osiz = ordl(self.buffer[self.pos + 7:self.pos + 11]) tsiz = ordl(self.buffer[self.pos + 11:self.pos + 15]) tosz = ordl(self.buffer[self.pos + 15:self.pos + 19]) self.print_header("Dimensionality", "%d" % ndim) self.print_header("Image Depth", "%d" % zsiz) self.print_header("Image Depth Offset", "%d" % osiz) self.print_header("Tile Depth", "%d" % tsiz) self.print_header("Tile Depth Offset", "%d" % tosz) for i in range(size - 19): self.print_header("Z Sample Separation for component %d" % i, "%d" % ordb(self.buffer[self.pos + 19 + i])) self.pos += size self._end_marker()
def read_COM(self): self._new_marker("COM", "Comment") if self.size < 4: raise InvalidSizedMarker("COM") reg = ordw(self.buffer[self.pos + 2:self.pos + 4]) if reg == 0: s = "binary" elif reg == 1: s = "ISO-8859-15" else: s = "unknown" self.print_header("Registration", s) if reg == 1: self.print_header( "Comment", self.buffer[self.pos + 4:self.pos + self.size].decode('utf-8')) else: self.print_header("Comment", "...") self._end_marker() self.pos += self.size
def read_SPco(self, precincts): if len(self.buffer) - self.pos < 5 + precincts: raise InvalidSizedMarker("SPco") levels = ordb(self.buffer[self.pos + 0]) if levels <= 32: self.print_header("Decomposition Levels", str(levels)) else: self.print_header("Downsampling factor style", str(levels)) self.print_header("Code-block size", "%dx%d" % \ (1 << (ordb(self.buffer[self.pos + 1]) + 2), 1 << (ordb(self.buffer[self.pos + 2]) + 2))) x = ordb(self.buffer[self.pos + 3]) self.print_header("Selective Arithmetic Coding Bypass", "yes" if x & 0x01 else "no") self.print_header("Reset Context Probabilities", "yes" if x & 0x02 else "no") self.print_header("Termination on Each Coding Pass", "yes" if x & 0x04 else "no") self.print_header("Vertically Causal Context", "yes" if x & 0x08 else "no") self.print_header("Predictable Termination", "yes" if x & 0x10 else "no") self.print_header("Segmentation Symbols", "yes" if x & 0x20 else "no") self.print_header("Entropy Coding", "FBCOT (Part 15)" if x & 0x40 else "EBCOT") if x & 0x40: self.print_header("Mixing of FBCOT and EBCOT", "yes" if x & 0x80 else "no") if ordb(self.buffer[self.pos + 4]) == 0x00: s = "9-7 irreversible" elif ordb(self.buffer[self.pos + 4]) == 0x01: s = "5-3 reversible" else: s = "arbitrary ATK specified transform" self.print_header("Wavelet Transformation", s) for i in range(precincts): x = ordb(self.buffer[self.pos + i + 5]) self.print_header("Precinct #%d Size Exponents" % i, "%dx%d" % (x & 0x0f, x >> 4)) self.pos += 5 + precincts
def read_unknown_marker(self): if self.marker == 0x00 or self.marker == 0x01 or self.marker == 0xfe or \ 0xc0 <= self.marker <= 0xdf: type = "ISO/IEC 10918-1" elif 0xf0 <= self.marker <= 0xf6: type = "ISO/IEC 10918-3" elif 0xf7 <= self.marker <= 0xf8: type = "ISO/IEC 14495-1" elif 0x30 <= self.marker <= 0x3f: type = "segment-less" elif 0x50 <= self.marker <= 0xff: type = "invalid ISO/IEC 15444-xx" else: raise InvalidMarker("%02x" % self.marker) self._new_marker("0xff%02x" % self.marker, "unknown %s" % type) self._end_marker() if self.size is not None: if self.size < 2: raise InvalidSizedMarker("unknown") self._end_marker() self.pos += self.size
def read_SGco(self): if len(self.buffer) - self.pos < 4: raise InvalidSizedMarker("SGco") self.print_header( "Progression Order", self.progression_order(ordb(self.buffer[self.pos + 0]))) self.print_header("Layers", str(ordw(self.buffer[self.pos + 1:self.pos + 3]))) trafo = ordb(self.buffer[self.pos + 3]) if trafo == 0: s = "none" elif trafo == 1: s = "components 0,1,2" elif trafo == 2: s = "generic array based transform" elif trafo == 4: s = "wavelet based transform" elif trafo == 6: s = "array and wavelet based transform" else: s = str(ordb(self.buffer[self.pos + 3])) self.print_header("Multiple Component Transformation", s) self.pos += 4
def read_CBD(self): self._new_marker("CBD", "Component bit depth definition") if self.size < 5: raise InvalidSizedMarker("CBD") nbcd = ordw(self.buffer[self.pos + 2:self.pos + 4]) if nbcd & (1 << 15): nbcd -= 1 << 15 self.print_header("Definition style", "Identical depth and signs") count = 1 else: self.print_header("Definition style", "Individual depths and signs") count = nbcd self.print_header("Number of generated components", str(nbcd)) self.pos += 4 for i in range(count): if ordb(self.buffer[self.pos]) & (1 << 7): self.print_header("Component %d sign" % i, "signed") else: self.print_header("Component %d sign" % i, "unsigned") self.print_header("Component %d Bit Depth" % i, str(1 + (ordb(self.buffer[self.pos]) & 0x7f))) self.pos += 1 self._end_marker()