undo, j2c-test
[asdcplib.git] / src / JP2K.cpp
1 /*
2 Copyright (c) 2005-2009, 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 // when indexed with the second byte of a marker code, this table will procuce one of
41 // two values:
42 //   0 - the marker is a standalone marker
43 //   1 - the marker designates a marker segment
44 //
45 const byte_t MarkerSegmentMap[] =
46   {
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 */
65   };
66
67
68 //
69 ASDCP::Result_t
70 ASDCP::JP2K::GetNextMarker(const byte_t** buf, JP2K::Marker& Marker)
71 {
72   assert((buf != 0) && (*buf != 0 ));
73   
74   if ( **buf != 0xff )
75     return ASDCP::RESULT_FAIL;
76
77   Marker.m_IsSegment = (MarkerSegmentMap[*(++(*buf))] == 1);
78   Marker.m_Type = (Marker_t)(0xff00 | *(*buf)++);
79
80   if ( Marker.m_IsSegment )
81     {
82       Marker.m_DataSize = *(*buf)++ << 8;
83       Marker.m_DataSize |= *(*buf)++;
84       Marker.m_DataSize -= 2;
85       Marker.m_Data = *buf;
86       *buf += Marker.m_DataSize;
87     }
88
89
90   if ( Marker.m_DataSize != 0 && Marker.m_DataSize < 3 )
91     {
92       DefaultLogSink().Error("Illegal data size: %u\n", Marker.m_DataSize);
93       return ASDCP::RESULT_FAIL;
94     }
95
96   return ASDCP::RESULT_OK;
97 }
98
99
100 //-------------------------------------------------------------------------------------------------------
101 //
102
103 //
104 void
105 ASDCP::JP2K::Accessor::SIZ::ReadComponent(ui32_t index, ASDCP::JP2K::ImageComponent_t& IC)
106 {
107   assert ( index < Csize() );
108   const byte_t* p = m_MarkerData + 36 + (index * 3);
109   IC.Ssize = *p++;
110   IC.XRsize = *p++;
111   IC.YRsize = *p;
112 }
113
114 //
115 void
116 ASDCP::JP2K::Accessor::SIZ::Dump(FILE* stream)
117 {
118   if ( stream == 0 )
119     stream = stderr;
120
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",  Xsize());
125   fprintf(stream, " XOsize: %u\n",  XOsize());
126   fprintf(stream, " YOsize: %u\n",  XOsize());
127   fprintf(stream, " XTsize: %u\n",  XTsize());
128   fprintf(stream, " YTsize: %u\n",  XTsize());
129   fprintf(stream, "XTOsize: %u\n",  XTOsize());
130   fprintf(stream, "YTOsize: %u\n",  YTOsize());
131   fprintf(stream, "  Csize: %u\n",  Csize());
132
133   if ( Csize() > 0 )
134     {
135       fprintf(stream, "Components\n");
136
137       for ( ui32_t i = 0; i < Csize(); i++ )
138         {
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);
143         }
144     }
145 }
146
147 //
148 void
149 ASDCP::JP2K::Accessor::COM::Dump(FILE* stream)
150 {
151   if ( stream == 0 )
152     stream = stderr;
153
154   if ( IsText() )
155     {
156       char* t_str = (char*)malloc(CommentSize() + 1);
157       assert( t_str != 0 );
158       ui32_t cs = CommentSize();
159       memcpy(t_str, CommentData(), cs);
160       t_str[cs] = 0;
161       fprintf(stream, "COM:%s\n", t_str);
162     }
163   else
164     {
165       fprintf(stream, "COM:\n");
166       Kumu::hexdump(CommentData(), CommentSize(), stream);
167     }
168 }
169
170
171 //-------------------------------------------------------------------------------------------------------
172 //
173
174
175 //
176 void
177 ASDCP::JP2K::Marker::Dump(FILE* stream) const
178 {
179   if ( stream == 0 )
180     stream = stderr;
181
182   fprintf(stream, "Marker%s 0x%04x: %s", (m_IsSegment ? " segment" : ""), m_Type, GetMarkerString(m_Type));  
183
184   if ( m_IsSegment )
185     fprintf(stream, ", 0x%0x bytes", m_DataSize);
186
187   fputc('\n', stream);
188 }
189
190 //
191 const char*
192 ASDCP::JP2K::GetMarkerString(Marker_t m)
193 {
194   switch ( m )
195     {
196     case MRK_NIL: return "NIL"; break;
197     case MRK_SOC: return "SOC: Start of codestream"; break;
198     case MRK_SOT: return "SOT: Start of tile-part"; break;
199     case MRK_SOD: return "SOD: Start of data"; break;
200     case MRK_EOC: return "EOC: End of codestream"; break;
201     case MRK_SIZ: return "SIZ: Image and tile size"; break;
202     case MRK_COD: return "COD: Coding style default"; break;
203     case MRK_COC: return "COC: Coding style component"; break;
204     case MRK_RGN: return "RGN: Region of interest"; break;
205     case MRK_QCD: return "QCD: Quantization default"; break;
206     case MRK_QCC: return "QCC: Quantization component"; break;
207     case MRK_POC: return "POC: Progression order change"; break;
208     case MRK_TLM: return "TLM: Tile-part lengths"; break;
209     case MRK_PLM: return "PLM: Packet length, main header"; break;
210     case MRK_PLT: return "PLT: Packet length, tile-part header"; break;
211     case MRK_PPM: return "PPM: Packed packet headers, main header"; break;
212     case MRK_PPT: return "PPT: Packed packet headers, tile-part header"; break;
213     case MRK_SOP: return "SOP: Start of packet"; break;
214     case MRK_EPH: return "EPH: End of packet header"; break;
215     case MRK_CRG: return "CRG: Component registration"; break;
216     case MRK_COM: return "COM: Comment"; break;
217     }
218
219   return "Unknown marker code";
220 }
221
222 //
223 // end JP2K.cpp
224 //