2 Copyright (c) 2005-2014, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 \brief JPEG 2000 parser implementation
31 This is not a complete implementation of all things JP2K. There is just enough here to
32 support parsing picture metadata from a codestream header.
37 using Kumu::DefaultLogSink;
40 // when indexed with the second byte of a marker code, this table will procuce one of
42 // 0 - the marker is a standalone marker
43 // 1 - the marker designates a marker segment
45 const byte_t MarkerSegmentMap[] =
47 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
48 /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
49 /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
50 /* 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
51 /* 3 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
52 /* 4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
53 /* 5 */ 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, // 5
54 /* 6 */ 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
55 /* 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
56 /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
57 /* 9 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
58 /* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a
59 /* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // b
60 /* c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // c
61 /* d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // d
62 /* e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // e
63 /* f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // f
64 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
70 ASDCP::JP2K::GetNextMarker(const byte_t** buf, JP2K::Marker& Marker)
72 assert((buf != 0) && (*buf != 0 ));
75 return ASDCP::RESULT_FAIL;
77 Marker.m_IsSegment = (MarkerSegmentMap[*(++(*buf))] == 1);
78 Marker.m_Type = (Marker_t)(0xff00 | *(*buf)++);
80 if ( Marker.m_IsSegment )
82 Marker.m_DataSize = *(*buf)++ << 8;
83 Marker.m_DataSize |= *(*buf)++;
84 Marker.m_DataSize -= 2;
86 *buf += Marker.m_DataSize;
90 if ( Marker.m_DataSize != 0 && Marker.m_DataSize < 3 )
92 DefaultLogSink().Error("Illegal data size: %u\n", Marker.m_DataSize);
93 return ASDCP::RESULT_FAIL;
96 return ASDCP::RESULT_OK;
100 //-------------------------------------------------------------------------------------------------------
105 ASDCP::JP2K::Accessor::SIZ::ReadComponent(const ui32_t index, ASDCP::JP2K::ImageComponent_t& IC) const
107 assert ( index < Csize() );
108 const byte_t* p = m_MarkerData + 36 + (index * 3);
116 ASDCP::JP2K::Accessor::SIZ::Dump(FILE* stream) const
121 fprintf(stream, "SIZ: \n");
122 fprintf(stream, " Rsize: %hu\n", Rsize());
123 fprintf(stream, " Xsize: %u\n", Xsize());
124 fprintf(stream, " Ysize: %u\n", Ysize());
125 fprintf(stream, " XOsize: %u\n", XOsize());
126 fprintf(stream, " YOsize: %u\n", YOsize());
127 fprintf(stream, " XTsize: %u\n", XTsize());
128 fprintf(stream, " YTsize: %u\n", YTsize());
129 fprintf(stream, "XTOsize: %u\n", XTOsize());
130 fprintf(stream, "YTOsize: %u\n", YTOsize());
131 fprintf(stream, " Csize: %u\n", Csize());
135 fprintf(stream, "Components\n");
137 for ( ui32_t i = 0; i < Csize(); i++ )
139 ImageComponent_t TmpComp;
140 ReadComponent(i, TmpComp);
141 fprintf(stream, "%u: ", i);
142 fprintf(stream, "%u, %u, %u\n", TmpComp.Ssize, TmpComp.XRsize, TmpComp.YRsize);
149 ASDCP::JP2K::Accessor::COD::Dump(FILE* stream) const
154 fprintf(stream, "COD: \n");
155 const char* prog_order_str = "RESERVED";
156 const char* transformations_str = prog_order_str;
158 switch ( ProgOrder() )
160 case 0: prog_order_str = "LRCP"; break;
161 case 1: prog_order_str = "RLCP"; break;
162 case 2: prog_order_str = "RPCL"; break;
163 case 3: prog_order_str = "PCRL"; break;
164 case 4: prog_order_str = "CPRL"; break;
167 switch ( Transformation() )
169 case 0: transformations_str = "9/7"; break;
170 case 1: transformations_str = "5/3"; break;
173 fprintf(stream, " ProgOrder: %s\n", prog_order_str);
174 fprintf(stream, " Layers: %hu\n", Layers());
175 fprintf(stream, " DecompLevels: %hhu\n", DecompLevels());
176 fprintf(stream, " CodeBlockWidth: %d\n", 1 << CodeBlockWidth());
177 fprintf(stream, "CodeBlockHeight: %d\n", 1 << CodeBlockHeight());
178 fprintf(stream, " CodeBlockStyle: %d\n", CodeBlockStyle());
179 fprintf(stream, " Transformation: %s\n", transformations_str);
184 ASDCP::JP2K::Accessor::GetQuantizationTypeString(const Accessor::QuantizationType_t t)
188 case QT_NONE: return "none";
189 case QT_DERIVED: return "scalar derived";
190 case QT_EXP: return "scalar expounded";
193 return "**UNKNOWN**";
198 ASDCP::JP2K::Accessor::QCD::Dump(FILE* stream) const
203 fprintf(stream, "QCD: \n");
204 fprintf(stream, "QuantizationType: %s\n", GetQuantizationTypeString(QuantizationType()));
205 fprintf(stream, " GuardBits: %d\n", GuardBits());
206 fprintf(stream, " SPqcd: %d\n", GuardBits());
207 Kumu::hexdump(m_MarkerData, m_DataSize, stream);
212 ASDCP::JP2K::Accessor::COM::Dump(FILE* stream) const
220 tmp_str.assign((char*)CommentData(), CommentSize());
221 fprintf(stream, "COM:%s\n", tmp_str.c_str());
225 fprintf(stream, "COM:\n");
226 Kumu::hexdump(CommentData(), CommentSize(), stream);
231 //-------------------------------------------------------------------------------------------------------
237 ASDCP::JP2K::Marker::Dump(FILE* stream) const
242 fprintf(stream, "Marker%s 0x%04x: %s", (m_IsSegment ? " segment" : ""), m_Type, GetMarkerString(m_Type));
245 fprintf(stream, ", 0x%0x bytes", m_DataSize);
252 ASDCP::JP2K::GetMarkerString(Marker_t m)
256 case MRK_NIL: return "NIL"; break;
257 case MRK_SOC: return "SOC: Start of codestream"; break;
258 case MRK_SOT: return "SOT: Start of tile-part"; break;
259 case MRK_SOD: return "SOD: Start of data"; break;
260 case MRK_EOC: return "EOC: End of codestream"; break;
261 case MRK_SIZ: return "SIZ: Image and tile size"; break;
262 case MRK_COD: return "COD: Coding style default"; break;
263 case MRK_COC: return "COC: Coding style component"; break;
264 case MRK_RGN: return "RGN: Region of interest"; break;
265 case MRK_QCD: return "QCD: Quantization default"; break;
266 case MRK_QCC: return "QCC: Quantization component"; break;
267 case MRK_POC: return "POC: Progression order change"; break;
268 case MRK_TLM: return "TLM: Tile-part lengths"; break;
269 case MRK_PLM: return "PLM: Packet length, main header"; break;
270 case MRK_PLT: return "PLT: Packet length, tile-part header"; break;
271 case MRK_PPM: return "PPM: Packed packet headers, main header"; break;
272 case MRK_PPT: return "PPT: Packed packet headers, tile-part header"; break;
273 case MRK_SOP: return "SOP: Start of packet"; break;
274 case MRK_EPH: return "EPH: End of packet header"; break;
275 case MRK_CRG: return "CRG: Component registration"; break;
276 case MRK_COM: return "COM: Comment"; break;
279 return "Unknown marker code";