[trunk] Remove bool.h, use opj_bool instead
[openjpeg.git] / src / lib / openjpip / j2kheader_manager.c
1 /*
2  * $Id$
3  *
4  * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2011, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara 
7  * Copyright (c) 2011,      Lucian Corlaciu, GSoC
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36 #include <assert.h>
37 #include "j2kheader_manager.h"
38
39 #ifdef SERVER
40 #include "fcgi_stdio.h"
41 #define logstream FCGI_stdout
42 #else
43 #define FCGI_stdout stdout
44 #define FCGI_stderr stderr
45 #define logstream stderr
46 #endif /*SERVER */
47
48
49 SIZmarker_param_t get_SIZmkrdata_from_j2kstream( Byte_t *SIZstream);
50 CODmarker_param_t get_CODmkrdata_from_j2kstream( Byte_t *CODstream);
51
52 opj_bool get_mainheader_from_j2kstream( Byte_t *j2kstream, SIZmarker_param_t *SIZ, CODmarker_param_t *COD)
53 {
54   if( *j2kstream++ != 0xff || *j2kstream++ != 0x4f){
55     fprintf( FCGI_stderr, "Error, j2kstream is not starting with SOC marker\n");
56     return OPJ_FALSE;
57   }
58   
59   if( SIZ){
60     *SIZ = get_SIZmkrdata_from_j2kstream( j2kstream);
61     if( SIZ->Lsiz == 0)
62       return OPJ_FALSE;
63
64     j2kstream += (SIZ->Lsiz+2);
65   }
66
67   if( COD){
68     if( !SIZ)
69       j2kstream += (big2( j2kstream+2) + 2);
70     
71     *COD = get_CODmkrdata_from_j2kstream( j2kstream);
72     if( COD->Lcod == 0)
73       return OPJ_FALSE;
74   }
75   return OPJ_TRUE;
76 }
77
78 SIZmarker_param_t get_SIZmkrdata_from_j2kstream( Byte_t *SIZstream)
79 {
80   SIZmarker_param_t SIZ;
81   int i;
82
83   if( *SIZstream++ != 0xff || *SIZstream++ != 0x51){
84     fprintf( FCGI_stderr, "Error, SIZ marker not found in the reconstructed j2kstream\n");
85     memset( &SIZ, 0, sizeof( SIZ ) );
86     return SIZ;
87   }
88
89   SIZ.Lsiz   = big2( SIZstream);
90   SIZ.Rsiz   = big2( SIZstream+2);
91   SIZ.Xsiz   = big4( SIZstream+4);
92   SIZ.Ysiz   = big4( SIZstream+8);
93   SIZ.XOsiz  = big4( SIZstream+12);
94   SIZ.YOsiz  = big4( SIZstream+16);
95   SIZ.XTsiz  = big4( SIZstream+20);
96   SIZ.YTsiz  = big4( SIZstream+24);
97   SIZ.XTOsiz = big4( SIZstream+28);
98   SIZ.YTOsiz = big4( SIZstream+32);
99   SIZ.Csiz   = big2( SIZstream+36);
100
101   SIZ.XTnum  = ( SIZ.Xsiz-SIZ.XTOsiz+SIZ.XTsiz-1)/SIZ.XTsiz;
102   SIZ.YTnum  = ( SIZ.Ysiz-SIZ.YTOsiz+SIZ.YTsiz-1)/SIZ.YTsiz;
103
104   for( i=0; i<(int)SIZ.Csiz; i++){
105     SIZ.Ssiz[i]  = *(SIZstream+(38+i*3));
106     SIZ.XRsiz[i] = *(SIZstream+(39+i*3));
107     SIZ.YRsiz[i] = *(SIZstream+(40+i*3));
108   }
109
110   return SIZ;
111 }
112
113 CODmarker_param_t get_CODmkrdata_from_j2kstream( Byte_t *CODstream)
114 {
115   CODmarker_param_t COD;
116   int i;
117
118   if( *CODstream++ != 0xff || *CODstream++ != 0x52){
119     fprintf( FCGI_stderr, "Error, COD marker not found in the reconstructed j2kstream\n");
120     return COD;
121   }
122   
123   COD.Lcod = big2( CODstream);
124   COD.Scod = *( CODstream+2);
125   COD.prog_order = *( CODstream+3);
126   COD.numOflayers = big2( CODstream+4);
127   COD.numOfdecomp = *( CODstream+7);
128
129   if(COD.Scod & 0x01){
130     COD.XPsiz = (Byte4_t *)opj_malloc( (OPJ_SIZE_T)(COD.numOfdecomp+1)*sizeof(Byte4_t));
131     COD.YPsiz = (Byte4_t *)opj_malloc( (OPJ_SIZE_T)(COD.numOfdecomp+1)*sizeof(Byte4_t));
132     
133     for( i=0; i<=COD.numOfdecomp; i++){
134       /*precinct size */
135       COD.XPsiz[i] = (Byte4_t)pow( 2, *( CODstream+12+i) & 0x0F);
136       COD.YPsiz[i] = (Byte4_t)pow( 2, (*( CODstream+12+i) & 0xF0) >> 4);
137     }
138   }
139   else{
140     COD.XPsiz = (Byte4_t *)opj_malloc( sizeof(Byte4_t));
141     COD.YPsiz = (Byte4_t *)opj_malloc( sizeof(Byte4_t));
142     COD.XPsiz[0] = COD.YPsiz[0] = pow(2,15);
143   }
144   return COD;
145 }
146
147
148 opj_bool modify_SIZmkrstream( SIZmarker_param_t SIZ, int difOfdecomplev, Byte_t *SIZstream);
149 Byte2_t modify_CODmkrstream( CODmarker_param_t COD, int numOfdecomp, Byte_t *CODstream);
150
151 opj_bool modify_mainheader( Byte_t *j2kstream, int numOfdecomp, SIZmarker_param_t SIZ, CODmarker_param_t COD, Byte8_t *j2klen)
152 {
153   Byte2_t newLcod;
154
155   if( *j2kstream++ != 0xff || *j2kstream++ != 0x4f){
156     fprintf( FCGI_stderr, "Error, j2kstream is not starting with SOC marker\n");
157     return OPJ_FALSE;
158   }
159
160   if(!modify_SIZmkrstream( SIZ, COD.numOfdecomp-numOfdecomp, j2kstream))
161     return OPJ_FALSE;
162   
163   j2kstream += SIZ.Lsiz+2;
164   if( !(newLcod = modify_CODmkrstream( COD, numOfdecomp, j2kstream)))
165     return OPJ_FALSE;
166
167   memmove( j2kstream+2+newLcod, j2kstream+2+COD.Lcod, *j2klen - (Byte8_t)(SIZ.Lsiz+COD.Lcod+6));
168   *j2klen -= (Byte8_t)( COD.Lcod - newLcod);
169   
170   return OPJ_TRUE;
171 }
172
173 opj_bool modify_SIZmkrstream( SIZmarker_param_t SIZ, int difOfdecomplev, Byte_t *SIZstream)
174 {
175   int i;
176   
177   if( *SIZstream++ != 0xff || *SIZstream++ != 0x51){
178     fprintf( FCGI_stderr, "Error, SIZ marker not found in the reconstructed j2kstream\n");
179     return OPJ_FALSE;
180   }
181     
182   for( i=0; i<difOfdecomplev; i++){
183     SIZ.Xsiz   = (Byte4_t)ceil( (double)SIZ.Xsiz/2.0);
184     SIZ.Ysiz   = (Byte4_t)ceil( (double)SIZ.Ysiz/2.0);
185     SIZ.XOsiz  = (Byte4_t)ceil( (double)SIZ.XOsiz/2.0);
186     SIZ.YOsiz  = (Byte4_t)ceil( (double)SIZ.YOsiz/2.0);
187     SIZ.XTsiz  = (Byte4_t)ceil( (double)SIZ.XTsiz/2.0);
188     SIZ.YTsiz  = (Byte4_t)ceil( (double)SIZ.YTsiz/2.0);
189     SIZ.XTOsiz = (Byte4_t)ceil( (double)SIZ.XTOsiz/2.0);
190     SIZ.YTOsiz = (Byte4_t)ceil( (double)SIZ.YTOsiz/2.0);
191   }
192
193   SIZstream += 4; /* skip Lsiz + Rsiz */
194
195   modify_4Bytecode( SIZ.Xsiz,   SIZstream);
196   modify_4Bytecode( SIZ.Ysiz,   SIZstream+4);
197   modify_4Bytecode( SIZ.XOsiz,  SIZstream+8);
198   modify_4Bytecode( SIZ.YOsiz,  SIZstream+12);
199   modify_4Bytecode( SIZ.XTsiz,  SIZstream+16);
200   modify_4Bytecode( SIZ.YTsiz,  SIZstream+20);
201   modify_4Bytecode( SIZ.XTOsiz, SIZstream+24);
202   modify_4Bytecode( SIZ.YTOsiz, SIZstream+28);
203
204   return OPJ_TRUE;
205 }
206
207 Byte2_t modify_CODmkrstream( CODmarker_param_t COD, int numOfdecomp, Byte_t *CODstream)
208 {
209   Byte2_t newLcod;
210
211   assert( numOfdecomp >= 0 || numOfdecomp <= 255 );
212   if( *CODstream++ != 0xff || *CODstream++ != 0x52){
213     fprintf( FCGI_stderr, "Error, COD marker not found in the reconstructed j2kstream\n");
214     return 0;
215   }
216   
217   if( COD.Scod & 0x01){
218     newLcod  = (Byte2_t)(13+numOfdecomp);
219
220     *CODstream++ = (Byte_t)((Byte2_t)(newLcod & 0xff00) >> 8);
221     *CODstream++ = (Byte_t)(newLcod & 0x00ff);
222   }
223   else{
224     newLcod = COD.Lcod;
225     CODstream += 2;
226   }
227   
228   CODstream += 5; /* skip Scod & SGcod */
229   
230   /* SPcod */
231   *CODstream++ = (Byte_t) numOfdecomp;
232   
233   return newLcod;
234 }
235
236 opj_bool modify_COCmkrstream( int numOfdecomp, Byte_t *COCstream, Byte2_t Csiz, Byte2_t *oldLcoc, Byte2_t *newLcoc);
237
238 opj_bool modify_tileheader( Byte_t *j2kstream, Byte8_t SOToffset, int numOfdecomp, Byte2_t Csiz, Byte8_t *j2klen)
239 {
240   Byte4_t Psot; /* tile part length ref A.4.2 Start of tile-part SOT */
241   Byte_t *thstream, *SOTstream, *Psot_stream;
242   Byte2_t oldLcoc, newLcoc;
243   
244   SOTstream = thstream = j2kstream+SOToffset;
245   
246   if( *SOTstream++ != 0xff || *SOTstream++ != 0x90){
247     fprintf( FCGI_stderr, "Error, thstream is not starting with SOT marker\n");
248     return OPJ_FALSE;
249   }
250
251   SOTstream += 4; /* skip Lsot & Isot */
252   Psot = (Byte4_t)((SOTstream[0]<<24)+(SOTstream[1]<<16)+(SOTstream[2]<<8)+(SOTstream[3]));
253   Psot_stream = SOTstream;
254   
255   thstream += 12; /* move to next marker (SOT always 12bytes) */
256   
257   while( !( *thstream == 0xff && *(thstream+1) == 0x93)){ /* search SOD */
258     if( numOfdecomp != -1 && *thstream == 0xff && *(thstream+1) == 0x53){ /* COC */
259       if( !modify_COCmkrstream( numOfdecomp, thstream, Csiz, &oldLcoc, &newLcoc))
260         return OPJ_FALSE;
261       
262       memmove( thstream+newLcoc+2, thstream+oldLcoc+2, *j2klen - (Byte8_t)(thstream-j2kstream+oldLcoc+2));
263       *j2klen -= (Byte8_t)( oldLcoc - newLcoc);
264     }
265     thstream += 2;
266     thstream += ((thstream[0]<<8)+(thstream[1])); /* marker length */
267   }
268
269   if( (*j2klen)-SOToffset != Psot){
270     Psot = (Byte4_t)((*j2klen)-SOToffset);
271     modify_4Bytecode( Psot, Psot_stream);
272   }
273   return OPJ_TRUE;
274 }
275
276 opj_bool modify_COCmkrstream( int numOfdecomp, Byte_t *COCstream, Byte2_t Csiz, Byte2_t *oldLcoc, Byte2_t *newLcoc)
277 {
278   if( numOfdecomp < 0 || numOfdecomp > 255 ) return OPJ_FALSE;
279   if( *COCstream++ != 0xff || *COCstream++ != 0x53){
280     fprintf( FCGI_stderr, "Error, COC marker not found in the reconstructed j2kstream\n");
281     return OPJ_FALSE;
282   }
283   
284   *oldLcoc = big2( COCstream);
285   *newLcoc = (Byte2_t)((Csiz < 257 ? 10 : 11) + numOfdecomp);
286   *COCstream++ = (Byte_t)((Byte2_t)((*newLcoc) & 0xff00) >> 8);
287   *COCstream++ = (Byte_t)((*newLcoc) & 0x00ff);
288       
289   if( Csiz < 257) COCstream +=2; /* skip Ccoc & Scoc */
290   else COCstream += 3;
291       
292   *COCstream = (Byte_t)numOfdecomp;
293   
294   return OPJ_TRUE;
295 }