Bump patch version post tag.
[asdcplib.git] / src / JP2K.cpp
1 /*
2 Copyright (c) 2005-2014, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
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.
15
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.
26 */
27 /*! \file    JP2K.cpp
28     \version $Id$
29     \brief   JPEG 2000 parser implementation
30
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.
33 */
34
35 #include <JP2K.h>
36 #include <KM_log.h>
37 using Kumu::DefaultLogSink;
38
39
40 //
41 ASDCP::Result_t
42 ASDCP::JP2K::GetNextMarker(const byte_t** buf, JP2K::Marker& Marker)
43 {
44   assert((buf != 0) && (*buf != 0 ));
45   
46   if (*(*buf)++ != 0xff )
47     return ASDCP::RESULT_FAIL;
48
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;
51
52   if ( Marker.m_IsSegment )
53     {
54       Marker.m_DataSize = *(*buf)++ << 8;
55       Marker.m_DataSize |= *(*buf)++;
56       Marker.m_DataSize -= 2;
57       Marker.m_Data = *buf;
58       *buf += Marker.m_DataSize;
59     }
60
61   /* TODO: why is this here?
62   if ( Marker.m_DataSize != 0 && Marker.m_DataSize < 3 )
63     {
64       DefaultLogSink().Error("Illegal data size: %u\n", Marker.m_DataSize);
65       return ASDCP::RESULT_FAIL;
66     }
67         */
68   return ASDCP::RESULT_OK;
69 }
70
71
72 //-------------------------------------------------------------------------------------------------------
73 //
74
75 //
76 void
77 ASDCP::JP2K::Accessor::SIZ::ReadComponent(const ui32_t index, ASDCP::JP2K::ImageComponent_t& IC) const
78 {
79   assert ( index < Csize() );
80   const byte_t* p = m_MarkerData + 36 + (index * 3);
81   IC.Ssize = *p++;
82   IC.XRsize = *p++;
83   IC.YRsize = *p;
84 }
85
86 //
87 void
88 ASDCP::JP2K::Accessor::SIZ::Dump(FILE* stream) const
89 {
90   if ( stream == 0 )
91     stream = stderr;
92
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());
104
105   if ( Csize() > 0 )
106     {
107       fprintf(stream, "Components\n");
108
109       for ( ui32_t i = 0; i < Csize(); i++ )
110         {
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);
115         }
116     }
117 }
118
119 //
120 void
121 ASDCP::JP2K::Accessor::COD::Dump(FILE* stream) const
122 {
123   if ( stream == 0 )
124     stream = stderr;
125
126   fprintf(stream, "COD: \n");
127   const char* prog_order_str = "RESERVED";
128   const char* transformations_str = prog_order_str;
129
130   switch ( ProgOrder() )
131     {
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;
137     }
138
139   switch ( Transformation() )
140     {
141     case 0: transformations_str = "9/7"; break;
142     case 1: transformations_str = "5/3"; break;
143     }
144
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);
152 }
153
154 //
155 const char*
156 ASDCP::JP2K::Accessor::GetQuantizationTypeString(const Accessor::QuantizationType_t t)
157 {
158   switch ( t )
159     {
160     case QT_NONE: return "none";
161     case QT_DERIVED: return "scalar derived";
162     case QT_EXP: return "scalar expounded";
163     }
164
165   return "**UNKNOWN**";
166 }
167
168 //
169 void
170 ASDCP::JP2K::Accessor::QCD::Dump(FILE* stream) const
171 {
172   if ( stream == 0 )
173     stream = stderr;
174
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);
180 }
181
182 //
183 void
184 ASDCP::JP2K::Accessor::COM::Dump(FILE* stream) const
185 {
186   if ( stream == 0 )
187     stream = stderr;
188
189   if ( IsText() )
190     {
191       std::string tmp_str;
192       tmp_str.assign((char*)CommentData(), CommentSize());
193       fprintf(stream, "COM:%s\n", tmp_str.c_str());
194     }
195   else
196     {
197       fprintf(stream, "COM:\n");
198       Kumu::hexdump(CommentData(), CommentSize(), stream);
199     }
200 }
201
202 //
203 void
204 ASDCP::JP2K::Accessor::PRF::Dump(FILE* stream) const
205 {
206   if ( stream == 0 )
207     stream = stderr;
208
209   fprintf(stream, "PRF: \n");
210
211   if (N() == 0) {
212
213           fprintf(stream, "     N/A");
214
215   } else {
216
217           for (ui16_t i = 1; i <= N(); i++) {
218                   fprintf(stream, "pprf(%d): %d\n", i, pprf(i));
219           }
220
221   }
222 }
223
224 //
225 void
226 ASDCP::JP2K::Accessor::CPF::Dump(FILE* stream) const
227 {
228   if ( stream == 0 )
229     stream = stderr;
230
231   fprintf(stream, "CPF: \n");
232
233   if (N() == 0) {
234
235           fprintf(stream, "     N/A");
236
237   } else {
238
239           for (ui16_t i = 1; i <= N(); i++) {
240                   fprintf(stream, "pcpf(%d): %d\n", i, pcpf(i));
241           }
242
243   }
244 }
245
246
247 //
248 void
249 ASDCP::JP2K::Accessor::CAP::Dump(FILE* stream) const
250 {
251   if ( stream == 0 )
252     stream = stderr;
253
254   fprintf(stream, "CAP: \n");
255
256   ui32_t pcap = this->pcap();
257
258   if (pcap == 0) {
259
260           fprintf(stream, "     None");
261
262   } else {
263
264           for (i32_t b = 32, i = 1; b > 0; b--) {
265
266                   if ((pcap >> (32 - b)) & 0x1) {
267
268                           fprintf(stream, "     ccap(%d): %d\n", b, this->ccap(i++));
269
270                   }
271           }
272   }
273 }
274
275 //-------------------------------------------------------------------------------------------------------
276 //
277
278
279 //
280 void
281 ASDCP::JP2K::Marker::Dump(FILE* stream) const
282 {
283   if ( stream == 0 )
284     stream = stderr;
285
286   fprintf(stream, "Marker%s 0x%04x: %s", (m_IsSegment ? " segment" : ""), m_Type, GetMarkerString(m_Type));  
287
288   if ( m_IsSegment )
289     fprintf(stream, ", 0x%0x bytes", m_DataSize);
290
291   fputc('\n', stream);
292 }
293
294 //
295 const char*
296 ASDCP::JP2K::GetMarkerString(Marker_t m)
297 {
298   switch ( m )
299     {
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;
324     }
325
326   return "Unknown marker code";
327 }
328
329 //
330 // end JP2K.cpp
331 //