Merge pull request #1518 from dg0yt/static-windows
[openjpeg.git] / src / lib / openjpip / j2kheader_manager.c
1 /*
2  * $Id$
3  *
4  * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2014, 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,
53                                        SIZmarker_param_t *SIZ, CODmarker_param_t *COD)
54 {
55     if (*j2kstream++ != 0xff || *j2kstream++ != 0x4f) {
56         fprintf(FCGI_stderr, "Error, j2kstream is not starting with SOC marker\n");
57         return OPJ_FALSE;
58     }
59
60     if (SIZ) {
61         *SIZ = get_SIZmkrdata_from_j2kstream(j2kstream);
62         if (SIZ->Lsiz == 0) {
63             return OPJ_FALSE;
64         }
65
66         j2kstream += (SIZ->Lsiz + 2);
67     }
68
69     if (COD) {
70         if (!SIZ) {
71             j2kstream += (big2(j2kstream + 2) + 2);
72         }
73
74         *COD = get_CODmkrdata_from_j2kstream(j2kstream);
75         if (COD->Lcod == 0) {
76             return OPJ_FALSE;
77         }
78     }
79     return OPJ_TRUE;
80 }
81
82 SIZmarker_param_t get_SIZmkrdata_from_j2kstream(Byte_t *SIZstream)
83 {
84     SIZmarker_param_t SIZ;
85     int i;
86
87     if (*SIZstream++ != 0xff || *SIZstream++ != 0x51) {
88         fprintf(FCGI_stderr,
89                 "Error, SIZ marker not found in the reconstructed j2kstream\n");
90         memset(&SIZ, 0, sizeof(SIZ));
91         return SIZ;
92     }
93
94     SIZ.Lsiz   = big2(SIZstream);
95     SIZ.Rsiz   = big2(SIZstream + 2);
96     SIZ.Xsiz   = big4(SIZstream + 4);
97     SIZ.Ysiz   = big4(SIZstream + 8);
98     SIZ.XOsiz  = big4(SIZstream + 12);
99     SIZ.YOsiz  = big4(SIZstream + 16);
100     SIZ.XTsiz  = big4(SIZstream + 20);
101     SIZ.YTsiz  = big4(SIZstream + 24);
102     SIZ.XTOsiz = big4(SIZstream + 28);
103     SIZ.YTOsiz = big4(SIZstream + 32);
104     SIZ.Csiz   = big2(SIZstream + 36);
105
106     SIZ.XTnum  = (SIZ.Xsiz - SIZ.XTOsiz + SIZ.XTsiz - 1) / SIZ.XTsiz;
107     SIZ.YTnum  = (SIZ.Ysiz - SIZ.YTOsiz + SIZ.YTsiz - 1) / SIZ.YTsiz;
108
109     for (i = 0; i < (int)SIZ.Csiz; i++) {
110         SIZ.Ssiz[i]  = *(SIZstream + (38 + i * 3));
111         SIZ.XRsiz[i] = *(SIZstream + (39 + i * 3));
112         SIZ.YRsiz[i] = *(SIZstream + (40 + i * 3));
113     }
114
115     return SIZ;
116 }
117
118 CODmarker_param_t get_CODmkrdata_from_j2kstream(Byte_t *CODstream)
119 {
120     CODmarker_param_t COD;
121     int i;
122
123     if (*CODstream++ != 0xff || *CODstream++ != 0x52) {
124         fprintf(FCGI_stderr,
125                 "Error, COD marker not found in the reconstructed j2kstream\n");
126         memset(&COD, 0, sizeof(COD));
127         return COD;
128     }
129
130     COD.Lcod = big2(CODstream);
131     COD.Scod = *(CODstream + 2);
132     COD.prog_order = *(CODstream + 3);
133     COD.numOflayers = big2(CODstream + 4);
134     COD.numOfdecomp = *(CODstream + 7);
135
136     if (COD.Scod & 0x01) {
137         COD.XPsiz = (Byte4_t *)opj_malloc((OPJ_SIZE_T)(COD.numOfdecomp + 1) * sizeof(
138                                               Byte4_t));
139         COD.YPsiz = (Byte4_t *)opj_malloc((OPJ_SIZE_T)(COD.numOfdecomp + 1) * sizeof(
140                                               Byte4_t));
141
142         for (i = 0; i <= COD.numOfdecomp; i++) {
143             /*precinct size */
144             COD.XPsiz[i] = (Byte4_t)pow(2, *(CODstream + 12 + i) & 0x0F);
145             COD.YPsiz[i] = (Byte4_t)pow(2, (*(CODstream + 12 + i) & 0xF0) >> 4);
146         }
147     } else {
148         COD.XPsiz = (Byte4_t *)opj_malloc(sizeof(Byte4_t));
149         COD.YPsiz = (Byte4_t *)opj_malloc(sizeof(Byte4_t));
150         COD.XPsiz[0] = COD.YPsiz[0] = 1 << 15; /*pow(2,15)*/
151     }
152     return COD;
153 }
154
155
156 OPJ_BOOL modify_SIZmkrstream(SIZmarker_param_t SIZ, int difOfdecomplev,
157                              Byte_t *SIZstream);
158 Byte2_t modify_CODmkrstream(CODmarker_param_t COD, int numOfdecomp,
159                             Byte_t *CODstream);
160
161 OPJ_BOOL modify_mainheader(Byte_t *j2kstream, int numOfdecomp,
162                            SIZmarker_param_t SIZ, CODmarker_param_t COD, Byte8_t *j2klen)
163 {
164     Byte2_t newLcod;
165
166     if (*j2kstream++ != 0xff || *j2kstream++ != 0x4f) {
167         fprintf(FCGI_stderr, "Error, j2kstream is not starting with SOC marker\n");
168         return OPJ_FALSE;
169     }
170
171     if (!modify_SIZmkrstream(SIZ, COD.numOfdecomp - numOfdecomp, j2kstream)) {
172         return OPJ_FALSE;
173     }
174
175     j2kstream += SIZ.Lsiz + 2;
176     if (!(newLcod = modify_CODmkrstream(COD, numOfdecomp, j2kstream))) {
177         return OPJ_FALSE;
178     }
179
180     memmove(j2kstream + 2 + newLcod, j2kstream + 2 + COD.Lcod,
181             *j2klen - (Byte8_t)(SIZ.Lsiz + COD.Lcod + 6));
182     *j2klen -= (Byte8_t)(COD.Lcod - newLcod);
183
184     return OPJ_TRUE;
185 }
186
187 OPJ_BOOL modify_SIZmkrstream(SIZmarker_param_t SIZ, int difOfdecomplev,
188                              Byte_t *SIZstream)
189 {
190     int i;
191
192     if (*SIZstream++ != 0xff || *SIZstream++ != 0x51) {
193         fprintf(FCGI_stderr,
194                 "Error, SIZ marker not found in the reconstructed j2kstream\n");
195         return OPJ_FALSE;
196     }
197
198     for (i = 0; i < difOfdecomplev; i++) {
199         SIZ.Xsiz   = (Byte4_t)ceil((double)SIZ.Xsiz / 2.0);
200         SIZ.Ysiz   = (Byte4_t)ceil((double)SIZ.Ysiz / 2.0);
201         SIZ.XOsiz  = (Byte4_t)ceil((double)SIZ.XOsiz / 2.0);
202         SIZ.YOsiz  = (Byte4_t)ceil((double)SIZ.YOsiz / 2.0);
203         SIZ.XTsiz  = (Byte4_t)ceil((double)SIZ.XTsiz / 2.0);
204         SIZ.YTsiz  = (Byte4_t)ceil((double)SIZ.YTsiz / 2.0);
205         SIZ.XTOsiz = (Byte4_t)ceil((double)SIZ.XTOsiz / 2.0);
206         SIZ.YTOsiz = (Byte4_t)ceil((double)SIZ.YTOsiz / 2.0);
207     }
208
209     SIZstream += 4; /* skip Lsiz + Rsiz */
210
211     modify_4Bytecode(SIZ.Xsiz,   SIZstream);
212     modify_4Bytecode(SIZ.Ysiz,   SIZstream + 4);
213     modify_4Bytecode(SIZ.XOsiz,  SIZstream + 8);
214     modify_4Bytecode(SIZ.YOsiz,  SIZstream + 12);
215     modify_4Bytecode(SIZ.XTsiz,  SIZstream + 16);
216     modify_4Bytecode(SIZ.YTsiz,  SIZstream + 20);
217     modify_4Bytecode(SIZ.XTOsiz, SIZstream + 24);
218     modify_4Bytecode(SIZ.YTOsiz, SIZstream + 28);
219
220     return OPJ_TRUE;
221 }
222
223 Byte2_t modify_CODmkrstream(CODmarker_param_t COD, int numOfdecomp,
224                             Byte_t *CODstream)
225 {
226     Byte2_t newLcod;
227
228     assert(numOfdecomp >= 0 || numOfdecomp <= 255);
229     if (*CODstream++ != 0xff || *CODstream++ != 0x52) {
230         fprintf(FCGI_stderr,
231                 "Error, COD marker not found in the reconstructed j2kstream\n");
232         return 0;
233     }
234
235     if (COD.Scod & 0x01) {
236         newLcod  = (Byte2_t)(13 + numOfdecomp);
237
238         *CODstream++ = (Byte_t)((Byte2_t)(newLcod & 0xff00) >> 8);
239         *CODstream++ = (Byte_t)(newLcod & 0x00ff);
240     } else {
241         newLcod = COD.Lcod;
242         CODstream += 2;
243     }
244
245     CODstream += 5; /* skip Scod & SGcod */
246
247     /* SPcod */
248     *CODstream++ = (Byte_t) numOfdecomp;
249
250     return newLcod;
251 }
252
253 OPJ_BOOL modify_COCmkrstream(int numOfdecomp, Byte_t *COCstream, Byte2_t Csiz,
254                              Byte2_t *oldLcoc, Byte2_t *newLcoc);
255
256 OPJ_BOOL modify_tileheader(Byte_t *j2kstream, Byte8_t SOToffset,
257                            int numOfdecomp, Byte2_t Csiz, Byte8_t *j2klen)
258 {
259     Byte4_t Psot; /* tile part length ref A.4.2 Start of tile-part SOT */
260     Byte_t *thstream, *SOTstream, *Psot_stream;
261     Byte2_t oldLcoc, newLcoc;
262
263     SOTstream = thstream = j2kstream + SOToffset;
264
265     if (*SOTstream++ != 0xff || *SOTstream++ != 0x90) {
266         fprintf(FCGI_stderr, "Error, thstream is not starting with SOT marker\n");
267         return OPJ_FALSE;
268     }
269
270     SOTstream += 4; /* skip Lsot & Isot */
271     Psot = (Byte4_t)((SOTstream[0] << 24) + (SOTstream[1] << 16) +
272                      (SOTstream[2] << 8) + (SOTstream[3]));
273     Psot_stream = SOTstream;
274
275     thstream += 12; /* move to next marker (SOT always 12bytes) */
276
277     while (!(*thstream == 0xff && *(thstream + 1) == 0x93)) { /* search SOD */
278         if (numOfdecomp != -1 && *thstream == 0xff &&
279                 *(thstream + 1) == 0x53) { /* COC */
280             if (!modify_COCmkrstream(numOfdecomp, thstream, Csiz, &oldLcoc, &newLcoc)) {
281                 return OPJ_FALSE;
282             }
283
284             memmove(thstream + newLcoc + 2, thstream + oldLcoc + 2,
285                     *j2klen - (Byte8_t)(thstream - j2kstream + oldLcoc + 2));
286             *j2klen -= (Byte8_t)(oldLcoc - newLcoc);
287         }
288         thstream += 2;
289         thstream += ((thstream[0] << 8) + (thstream[1])); /* marker length */
290     }
291
292     if ((*j2klen) - SOToffset != Psot) {
293         Psot = (Byte4_t)((*j2klen) - SOToffset);
294         modify_4Bytecode(Psot, Psot_stream);
295     }
296     return OPJ_TRUE;
297 }
298
299 OPJ_BOOL modify_COCmkrstream(int numOfdecomp, Byte_t *COCstream, Byte2_t Csiz,
300                              Byte2_t *oldLcoc, Byte2_t *newLcoc)
301 {
302     if (numOfdecomp < 0 || numOfdecomp > 255) {
303         return OPJ_FALSE;
304     }
305     if (*COCstream++ != 0xff || *COCstream++ != 0x53) {
306         fprintf(FCGI_stderr,
307                 "Error, COC marker not found in the reconstructed j2kstream\n");
308         return OPJ_FALSE;
309     }
310
311     *oldLcoc = big2(COCstream);
312     *newLcoc = (Byte2_t)((Csiz < 257 ? 10 : 11) + numOfdecomp);
313     *COCstream++ = (Byte_t)((Byte2_t)((*newLcoc) & 0xff00) >> 8);
314     *COCstream++ = (Byte_t)((*newLcoc) & 0x00ff);
315
316     if (Csiz < 257) {
317         COCstream += 2;    /* skip Ccoc & Scoc */
318     } else {
319         COCstream += 3;
320     }
321
322     *COCstream = (Byte_t)numOfdecomp;
323
324     return OPJ_TRUE;
325 }