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;
42 ASDCP::JP2K::GetNextMarker(const byte_t** buf, JP2K::Marker& Marker)
44 assert((buf != 0) && (*buf != 0 ));
46 if (*(*buf)++ != 0xff )
47 return ASDCP::RESULT_FAIL;
49 Marker.m_Type = (Marker_t)(0xff00 | *(*buf)++);
50 Marker.m_IsSegment = Marker.m_Type != MRK_SOC && Marker.m_Type != MRK_SOD && Marker.m_Type != MRK_EOC;
52 if ( Marker.m_IsSegment )
54 Marker.m_DataSize = *(*buf)++ << 8;
55 Marker.m_DataSize |= *(*buf)++;
56 Marker.m_DataSize -= 2;
58 *buf += Marker.m_DataSize;
61 /* TODO: why is this here?
62 if ( Marker.m_DataSize != 0 && Marker.m_DataSize < 3 )
64 DefaultLogSink().Error("Illegal data size: %u\n", Marker.m_DataSize);
65 return ASDCP::RESULT_FAIL;
68 return ASDCP::RESULT_OK;
72 //-------------------------------------------------------------------------------------------------------
77 ASDCP::JP2K::Accessor::SIZ::ReadComponent(const ui32_t index, ASDCP::JP2K::ImageComponent_t& IC) const
79 assert ( index < Csize() );
80 const byte_t* p = m_MarkerData + 36 + (index * 3);
88 ASDCP::JP2K::Accessor::SIZ::Dump(FILE* stream) const
93 fprintf(stream, "SIZ: \n");
94 fprintf(stream, " Rsize: %hu\n", Rsize());
95 fprintf(stream, " Xsize: %u\n", Xsize());
96 fprintf(stream, " Ysize: %u\n", Ysize());
97 fprintf(stream, " XOsize: %u\n", XOsize());
98 fprintf(stream, " YOsize: %u\n", YOsize());
99 fprintf(stream, " XTsize: %u\n", XTsize());
100 fprintf(stream, " YTsize: %u\n", YTsize());
101 fprintf(stream, "XTOsize: %u\n", XTOsize());
102 fprintf(stream, "YTOsize: %u\n", YTOsize());
103 fprintf(stream, " Csize: %u\n", Csize());
107 fprintf(stream, "Components\n");
109 for ( ui32_t i = 0; i < Csize(); i++ )
111 ImageComponent_t TmpComp;
112 ReadComponent(i, TmpComp);
113 fprintf(stream, "%u: ", i);
114 fprintf(stream, "%u, %u, %u\n", TmpComp.Ssize, TmpComp.XRsize, TmpComp.YRsize);
121 ASDCP::JP2K::Accessor::COD::Dump(FILE* stream) const
126 fprintf(stream, "COD: \n");
127 const char* prog_order_str = "RESERVED";
128 const char* transformations_str = prog_order_str;
130 switch ( ProgOrder() )
132 case 0: prog_order_str = "LRCP"; break;
133 case 1: prog_order_str = "RLCP"; break;
134 case 2: prog_order_str = "RPCL"; break;
135 case 3: prog_order_str = "PCRL"; break;
136 case 4: prog_order_str = "CPRL"; break;
139 switch ( Transformation() )
141 case 0: transformations_str = "9/7"; break;
142 case 1: transformations_str = "5/3"; break;
145 fprintf(stream, " ProgOrder: %s\n", prog_order_str);
146 fprintf(stream, " Layers: %hu\n", Layers());
147 fprintf(stream, " DecompLevels: %hhu\n", DecompLevels());
148 fprintf(stream, " CodeBlockWidth: %d\n", 1 << CodeBlockWidth());
149 fprintf(stream, "CodeBlockHeight: %d\n", 1 << CodeBlockHeight());
150 fprintf(stream, " CodeBlockStyle: %d\n", CodeBlockStyle());
151 fprintf(stream, " Transformation: %s\n", transformations_str);
156 ASDCP::JP2K::Accessor::GetQuantizationTypeString(const Accessor::QuantizationType_t t)
160 case QT_NONE: return "none";
161 case QT_DERIVED: return "scalar derived";
162 case QT_EXP: return "scalar expounded";
165 return "**UNKNOWN**";
170 ASDCP::JP2K::Accessor::QCD::Dump(FILE* stream) const
175 fprintf(stream, "QCD: \n");
176 fprintf(stream, "QuantizationType: %s\n", GetQuantizationTypeString(QuantizationType()));
177 fprintf(stream, " GuardBits: %d\n", GuardBits());
178 fprintf(stream, " SPqcd: %d\n", GuardBits());
179 Kumu::hexdump(m_MarkerData, m_DataSize, stream);
184 ASDCP::JP2K::Accessor::COM::Dump(FILE* stream) const
192 tmp_str.assign((char*)CommentData(), CommentSize());
193 fprintf(stream, "COM:%s\n", tmp_str.c_str());
197 fprintf(stream, "COM:\n");
198 Kumu::hexdump(CommentData(), CommentSize(), stream);
204 ASDCP::JP2K::Accessor::PRF::Dump(FILE* stream) const
209 fprintf(stream, "PRF: \n");
213 fprintf(stream, " N/A");
217 for (ui16_t i = 1; i <= N(); i++) {
218 fprintf(stream, "pprf(%d): %d\n", i, pprf(i));
226 ASDCP::JP2K::Accessor::CPF::Dump(FILE* stream) const
231 fprintf(stream, "CPF: \n");
235 fprintf(stream, " N/A");
239 for (ui16_t i = 1; i <= N(); i++) {
240 fprintf(stream, "pcpf(%d): %d\n", i, pcpf(i));
249 ASDCP::JP2K::Accessor::CAP::Dump(FILE* stream) const
254 fprintf(stream, "CAP: \n");
256 ui32_t pcap = this->pcap();
260 fprintf(stream, " None");
264 for (i32_t b = 32, i = 1; b > 0; b--) {
266 if ((pcap >> (32 - b)) & 0x1) {
268 fprintf(stream, " ccap(%d): %d\n", b, this->ccap(i++));
275 //-------------------------------------------------------------------------------------------------------
281 ASDCP::JP2K::Marker::Dump(FILE* stream) const
286 fprintf(stream, "Marker%s 0x%04x: %s", (m_IsSegment ? " segment" : ""), m_Type, GetMarkerString(m_Type));
289 fprintf(stream, ", 0x%0x bytes", m_DataSize);
296 ASDCP::JP2K::GetMarkerString(Marker_t m)
300 case MRK_NIL: return "NIL"; break;
301 case MRK_SOC: return "SOC: Start of codestream"; break;
302 case MRK_SOT: return "SOT: Start of tile-part"; break;
303 case MRK_SOD: return "SOD: Start of data"; break;
304 case MRK_EOC: return "EOC: End of codestream"; break;
305 case MRK_SIZ: return "SIZ: Image and tile size"; break;
306 case MRK_COD: return "COD: Coding style default"; break;
307 case MRK_COC: return "COC: Coding style component"; break;
308 case MRK_RGN: return "RGN: Region of interest"; break;
309 case MRK_QCD: return "QCD: Quantization default"; break;
310 case MRK_QCC: return "QCC: Quantization component"; break;
311 case MRK_POC: return "POC: Progression order change"; break;
312 case MRK_TLM: return "TLM: Tile-part lengths"; break;
313 case MRK_PLM: return "PLM: Packet length, main header"; break;
314 case MRK_PLT: return "PLT: Packet length, tile-part header"; break;
315 case MRK_PPM: return "PPM: Packed packet headers, main header"; break;
316 case MRK_PPT: return "PPT: Packed packet headers, tile-part header"; break;
317 case MRK_SOP: return "SOP: Start of packet"; break;
318 case MRK_EPH: return "EPH: End of packet header"; break;
319 case MRK_CRG: return "CRG: Component registration"; break;
320 case MRK_COM: return "COM: Comment"; break;
321 case MRK_CPF: return "CPF: Corresponding profile"; break;
322 case MRK_CAP: return "CAP: Capabilities"; break;
323 case MRK_PRF: return "PRF: Profile"; break;
326 return "Unknown marker code";