xref: /aosp_15_r20/external/sandboxed-api/oss-internship-2020/openjpeg/examples/convert.patch (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1*ec63e07aSXin Li--- convert.c	2020-08-27 15:46:32.911584344 +0000
2*ec63e07aSXin Li+++ convert_helper.cc	2020-08-27 15:10:52.695231032 +0000
3*ec63e07aSXin Li@@ -35,2605 +35,311 @@
4*ec63e07aSXin Li  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
5*ec63e07aSXin Li  * POSSIBILITY OF SUCH DAMAGE.
6*ec63e07aSXin Li  */
7*ec63e07aSXin Li-#include "opj_apps_config.h"
8*ec63e07aSXin Li
9*ec63e07aSXin Li-#include <stdio.h>
10*ec63e07aSXin Li-#include <stdlib.h>
11*ec63e07aSXin Li-#include <string.h>
12*ec63e07aSXin Li-#include <ctype.h>
13*ec63e07aSXin Li-#include <limits.h>
14*ec63e07aSXin Li-
15*ec63e07aSXin Li-#include "openjpeg.h"
16*ec63e07aSXin Li-#include "convert.h"
17*ec63e07aSXin Li-
18*ec63e07aSXin Li-/*
19*ec63e07aSXin Li- * Get logarithm of an integer and round downwards.
20*ec63e07aSXin Li- *
21*ec63e07aSXin Li- * log2(a)
22*ec63e07aSXin Li- */
23*ec63e07aSXin Li-static int int_floorlog2(int a)
24*ec63e07aSXin Li-{
25*ec63e07aSXin Li-    int l;
26*ec63e07aSXin Li-    for (l = 0; a > 1; l++) {
27*ec63e07aSXin Li-        a >>= 1;
28*ec63e07aSXin Li-    }
29*ec63e07aSXin Li-    return l;
30*ec63e07aSXin Li-}
31*ec63e07aSXin Li-
32*ec63e07aSXin Li-/* Component precision scaling */
33*ec63e07aSXin Li-void clip_component(opj_image_comp_t* component, OPJ_UINT32 precision)
34*ec63e07aSXin Li-{
35*ec63e07aSXin Li-    OPJ_SIZE_T i;
36*ec63e07aSXin Li-    OPJ_SIZE_T len;
37*ec63e07aSXin Li-    OPJ_UINT32 umax = (OPJ_UINT32)((OPJ_INT32) - 1);
38*ec63e07aSXin Li-
39*ec63e07aSXin Li-    len = (OPJ_SIZE_T)component->w * (OPJ_SIZE_T)component->h;
40*ec63e07aSXin Li-    if (precision < 32) {
41*ec63e07aSXin Li-        umax = (1U << precision) - 1U;
42*ec63e07aSXin Li-    }
43*ec63e07aSXin Li-
44*ec63e07aSXin Li-    if (component->sgnd) {
45*ec63e07aSXin Li-        OPJ_INT32* l_data = component->data;
46*ec63e07aSXin Li-        OPJ_INT32 max = (OPJ_INT32)(umax / 2U);
47*ec63e07aSXin Li-        OPJ_INT32 min = -max - 1;
48*ec63e07aSXin Li-        for (i = 0; i < len; ++i) {
49*ec63e07aSXin Li-            if (l_data[i] > max) {
50*ec63e07aSXin Li-                l_data[i] = max;
51*ec63e07aSXin Li-            } else if (l_data[i] < min) {
52*ec63e07aSXin Li-                l_data[i] = min;
53*ec63e07aSXin Li-            }
54*ec63e07aSXin Li-        }
55*ec63e07aSXin Li-    } else {
56*ec63e07aSXin Li-        OPJ_UINT32* l_data = (OPJ_UINT32*)component->data;
57*ec63e07aSXin Li-        for (i = 0; i < len; ++i) {
58*ec63e07aSXin Li-            if (l_data[i] > umax) {
59*ec63e07aSXin Li-                l_data[i] = umax;
60*ec63e07aSXin Li-            }
61*ec63e07aSXin Li-        }
62*ec63e07aSXin Li-    }
63*ec63e07aSXin Li-    component->prec = precision;
64*ec63e07aSXin Li-}
65*ec63e07aSXin Li+// patched versions of a few library tools
66*ec63e07aSXin Li
67*ec63e07aSXin Li-/* Component precision scaling */
68*ec63e07aSXin Li-static void scale_component_up(opj_image_comp_t* component,
69*ec63e07aSXin Li-                               OPJ_UINT32 precision)
70*ec63e07aSXin Li-{
71*ec63e07aSXin Li-    OPJ_SIZE_T i, len;
72*ec63e07aSXin Li-
73*ec63e07aSXin Li-    len = (OPJ_SIZE_T)component->w * (OPJ_SIZE_T)component->h;
74*ec63e07aSXin Li-    if (component->sgnd) {
75*ec63e07aSXin Li-        OPJ_INT64  newMax = (OPJ_INT64)(1U << (precision - 1));
76*ec63e07aSXin Li-        OPJ_INT64  oldMax = (OPJ_INT64)(1U << (component->prec - 1));
77*ec63e07aSXin Li-        OPJ_INT32* l_data = component->data;
78*ec63e07aSXin Li-        for (i = 0; i < len; ++i) {
79*ec63e07aSXin Li-            l_data[i] = (OPJ_INT32)(((OPJ_INT64)l_data[i] * newMax) / oldMax);
80*ec63e07aSXin Li-        }
81*ec63e07aSXin Li-    } else {
82*ec63e07aSXin Li-        OPJ_UINT64  newMax = (OPJ_UINT64)((1U << precision) - 1U);
83*ec63e07aSXin Li-        OPJ_UINT64  oldMax = (OPJ_UINT64)((1U << component->prec) - 1U);
84*ec63e07aSXin Li-        OPJ_UINT32* l_data = (OPJ_UINT32*)component->data;
85*ec63e07aSXin Li-        for (i = 0; i < len; ++i) {
86*ec63e07aSXin Li-            l_data[i] = (OPJ_UINT32)(((OPJ_UINT64)l_data[i] * newMax) / oldMax);
87*ec63e07aSXin Li-        }
88*ec63e07aSXin Li-    }
89*ec63e07aSXin Li-    component->prec = precision;
90*ec63e07aSXin Li-    component->bpp = precision;
91*ec63e07aSXin Li-}
92*ec63e07aSXin Li-void scale_component(opj_image_comp_t* component, OPJ_UINT32 precision)
93*ec63e07aSXin Li-{
94*ec63e07aSXin Li-    int shift;
95*ec63e07aSXin Li-    OPJ_SIZE_T i, len;
96*ec63e07aSXin Li-
97*ec63e07aSXin Li-    if (component->prec == precision) {
98*ec63e07aSXin Li-        return;
99*ec63e07aSXin Li-    }
100*ec63e07aSXin Li-    if (component->prec < precision) {
101*ec63e07aSXin Li-        scale_component_up(component, precision);
102*ec63e07aSXin Li-        return;
103*ec63e07aSXin Li-    }
104*ec63e07aSXin Li-    shift = (int)(component->prec - precision);
105*ec63e07aSXin Li-    len = (OPJ_SIZE_T)component->w * (OPJ_SIZE_T)component->h;
106*ec63e07aSXin Li-    if (component->sgnd) {
107*ec63e07aSXin Li-        OPJ_INT32* l_data = component->data;
108*ec63e07aSXin Li-        for (i = 0; i < len; ++i) {
109*ec63e07aSXin Li-            l_data[i] >>= shift;
110*ec63e07aSXin Li-        }
111*ec63e07aSXin Li-    } else {
112*ec63e07aSXin Li-        OPJ_UINT32* l_data = (OPJ_UINT32*)component->data;
113*ec63e07aSXin Li-        for (i = 0; i < len; ++i) {
114*ec63e07aSXin Li-            l_data[i] >>= shift;
115*ec63e07aSXin Li-        }
116*ec63e07aSXin Li-    }
117*ec63e07aSXin Li-    component->bpp = precision;
118*ec63e07aSXin Li-    component->prec = precision;
119*ec63e07aSXin Li-}
120*ec63e07aSXin Li-
121*ec63e07aSXin Li-
122*ec63e07aSXin Li-/* planar / interleaved conversions */
123*ec63e07aSXin Li-/* used by PNG/TIFF */
124*ec63e07aSXin Li-static void convert_32s_C1P1(const OPJ_INT32* pSrc, OPJ_INT32* const* pDst,
125*ec63e07aSXin Li-                             OPJ_SIZE_T length)
126*ec63e07aSXin Li-{
127*ec63e07aSXin Li-    memcpy(pDst[0], pSrc, length * sizeof(OPJ_INT32));
128*ec63e07aSXin Li-}
129*ec63e07aSXin Li-static void convert_32s_C2P2(const OPJ_INT32* pSrc, OPJ_INT32* const* pDst,
130*ec63e07aSXin Li-                             OPJ_SIZE_T length)
131*ec63e07aSXin Li-{
132*ec63e07aSXin Li-    OPJ_SIZE_T i;
133*ec63e07aSXin Li-    OPJ_INT32* pDst0 = pDst[0];
134*ec63e07aSXin Li-    OPJ_INT32* pDst1 = pDst[1];
135*ec63e07aSXin Li-
136*ec63e07aSXin Li-    for (i = 0; i < length; i++) {
137*ec63e07aSXin Li-        pDst0[i] = pSrc[2 * i + 0];
138*ec63e07aSXin Li-        pDst1[i] = pSrc[2 * i + 1];
139*ec63e07aSXin Li-    }
140*ec63e07aSXin Li-}
141*ec63e07aSXin Li-static void convert_32s_C3P3(const OPJ_INT32* pSrc, OPJ_INT32* const* pDst,
142*ec63e07aSXin Li-                             OPJ_SIZE_T length)
143*ec63e07aSXin Li-{
144*ec63e07aSXin Li-    OPJ_SIZE_T i;
145*ec63e07aSXin Li-    OPJ_INT32* pDst0 = pDst[0];
146*ec63e07aSXin Li-    OPJ_INT32* pDst1 = pDst[1];
147*ec63e07aSXin Li-    OPJ_INT32* pDst2 = pDst[2];
148*ec63e07aSXin Li-
149*ec63e07aSXin Li-    for (i = 0; i < length; i++) {
150*ec63e07aSXin Li-        pDst0[i] = pSrc[3 * i + 0];
151*ec63e07aSXin Li-        pDst1[i] = pSrc[3 * i + 1];
152*ec63e07aSXin Li-        pDst2[i] = pSrc[3 * i + 2];
153*ec63e07aSXin Li-    }
154*ec63e07aSXin Li-}
155*ec63e07aSXin Li-static void convert_32s_C4P4(const OPJ_INT32* pSrc, OPJ_INT32* const* pDst,
156*ec63e07aSXin Li-                             OPJ_SIZE_T length)
157*ec63e07aSXin Li-{
158*ec63e07aSXin Li-    OPJ_SIZE_T i;
159*ec63e07aSXin Li-    OPJ_INT32* pDst0 = pDst[0];
160*ec63e07aSXin Li-    OPJ_INT32* pDst1 = pDst[1];
161*ec63e07aSXin Li-    OPJ_INT32* pDst2 = pDst[2];
162*ec63e07aSXin Li-    OPJ_INT32* pDst3 = pDst[3];
163*ec63e07aSXin Li-
164*ec63e07aSXin Li-    for (i = 0; i < length; i++) {
165*ec63e07aSXin Li-        pDst0[i] = pSrc[4 * i + 0];
166*ec63e07aSXin Li-        pDst1[i] = pSrc[4 * i + 1];
167*ec63e07aSXin Li-        pDst2[i] = pSrc[4 * i + 2];
168*ec63e07aSXin Li-        pDst3[i] = pSrc[4 * i + 3];
169*ec63e07aSXin Li-    }
170*ec63e07aSXin Li-}
171*ec63e07aSXin Li-const convert_32s_CXPX convert_32s_CXPX_LUT[5] = {
172*ec63e07aSXin Li-    NULL,
173*ec63e07aSXin Li-    convert_32s_C1P1,
174*ec63e07aSXin Li-    convert_32s_C2P2,
175*ec63e07aSXin Li-    convert_32s_C3P3,
176*ec63e07aSXin Li-    convert_32s_C4P4
177*ec63e07aSXin Li-};
178*ec63e07aSXin Li-
179*ec63e07aSXin Li-static void convert_32s_P1C1(OPJ_INT32 const* const* pSrc, OPJ_INT32* pDst,
180*ec63e07aSXin Li-                             OPJ_SIZE_T length, OPJ_INT32 adjust)
181*ec63e07aSXin Li-{
182*ec63e07aSXin Li-    OPJ_SIZE_T i;
183*ec63e07aSXin Li-    const OPJ_INT32* pSrc0 = pSrc[0];
184*ec63e07aSXin Li+#include "convert.h"
185*ec63e07aSXin Li
186*ec63e07aSXin Li-    for (i = 0; i < length; i++) {
187*ec63e07aSXin Li-        pDst[i] = pSrc0[i] + adjust;
188*ec63e07aSXin Li-    }
189*ec63e07aSXin Li-}
190*ec63e07aSXin Li-static void convert_32s_P2C2(OPJ_INT32 const* const* pSrc, OPJ_INT32* pDst,
191*ec63e07aSXin Li-                             OPJ_SIZE_T length, OPJ_INT32 adjust)
192*ec63e07aSXin Li-{
193*ec63e07aSXin Li-    OPJ_SIZE_T i;
194*ec63e07aSXin Li-    const OPJ_INT32* pSrc0 = pSrc[0];
195*ec63e07aSXin Li-    const OPJ_INT32* pSrc1 = pSrc[1];
196*ec63e07aSXin Li-
197*ec63e07aSXin Li-    for (i = 0; i < length; i++) {
198*ec63e07aSXin Li-        pDst[2 * i + 0] = pSrc0[i] + adjust;
199*ec63e07aSXin Li-        pDst[2 * i + 1] = pSrc1[i] + adjust;
200*ec63e07aSXin Li-    }
201*ec63e07aSXin Li-}
202*ec63e07aSXin Li-static void convert_32s_P3C3(OPJ_INT32 const* const* pSrc, OPJ_INT32* pDst,
203*ec63e07aSXin Li-                             OPJ_SIZE_T length, OPJ_INT32 adjust)
204*ec63e07aSXin Li-{
205*ec63e07aSXin Li-    OPJ_SIZE_T i;
206*ec63e07aSXin Li-    const OPJ_INT32* pSrc0 = pSrc[0];
207*ec63e07aSXin Li-    const OPJ_INT32* pSrc1 = pSrc[1];
208*ec63e07aSXin Li-    const OPJ_INT32* pSrc2 = pSrc[2];
209*ec63e07aSXin Li-
210*ec63e07aSXin Li-    for (i = 0; i < length; i++) {
211*ec63e07aSXin Li-        pDst[3 * i + 0] = pSrc0[i] + adjust;
212*ec63e07aSXin Li-        pDst[3 * i + 1] = pSrc1[i] + adjust;
213*ec63e07aSXin Li-        pDst[3 * i + 2] = pSrc2[i] + adjust;
214*ec63e07aSXin Li-    }
215*ec63e07aSXin Li-}
216*ec63e07aSXin Li-static void convert_32s_P4C4(OPJ_INT32 const* const* pSrc, OPJ_INT32* pDst,
217*ec63e07aSXin Li-                             OPJ_SIZE_T length, OPJ_INT32 adjust)
218*ec63e07aSXin Li-{
219*ec63e07aSXin Li-    OPJ_SIZE_T i;
220*ec63e07aSXin Li-    const OPJ_INT32* pSrc0 = pSrc[0];
221*ec63e07aSXin Li-    const OPJ_INT32* pSrc1 = pSrc[1];
222*ec63e07aSXin Li-    const OPJ_INT32* pSrc2 = pSrc[2];
223*ec63e07aSXin Li-    const OPJ_INT32* pSrc3 = pSrc[3];
224*ec63e07aSXin Li-
225*ec63e07aSXin Li-    for (i = 0; i < length; i++) {
226*ec63e07aSXin Li-        pDst[4 * i + 0] = pSrc0[i] + adjust;
227*ec63e07aSXin Li-        pDst[4 * i + 1] = pSrc1[i] + adjust;
228*ec63e07aSXin Li-        pDst[4 * i + 2] = pSrc2[i] + adjust;
229*ec63e07aSXin Li-        pDst[4 * i + 3] = pSrc3[i] + adjust;
230*ec63e07aSXin Li-    }
231*ec63e07aSXin Li-}
232*ec63e07aSXin Li-const convert_32s_PXCX convert_32s_PXCX_LUT[5] = {
233*ec63e07aSXin Li-    NULL,
234*ec63e07aSXin Li-    convert_32s_P1C1,
235*ec63e07aSXin Li-    convert_32s_P2C2,
236*ec63e07aSXin Li-    convert_32s_P3C3,
237*ec63e07aSXin Li-    convert_32s_P4C4
238*ec63e07aSXin Li-};
239*ec63e07aSXin Li-
240*ec63e07aSXin Li-/* bit depth conversions */
241*ec63e07aSXin Li-/* used by PNG/TIFF up to 8bpp */
242*ec63e07aSXin Li-static void convert_1u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst,
243*ec63e07aSXin Li-                              OPJ_SIZE_T length)
244*ec63e07aSXin Li-{
245*ec63e07aSXin Li-    OPJ_SIZE_T i;
246*ec63e07aSXin Li-    for (i = 0; i < (length & ~(OPJ_SIZE_T)7U); i += 8U) {
247*ec63e07aSXin Li-        OPJ_UINT32 val = *pSrc++;
248*ec63e07aSXin Li-        pDst[i + 0] = (OPJ_INT32)(val >> 7);
249*ec63e07aSXin Li-        pDst[i + 1] = (OPJ_INT32)((val >> 6) & 0x1U);
250*ec63e07aSXin Li-        pDst[i + 2] = (OPJ_INT32)((val >> 5) & 0x1U);
251*ec63e07aSXin Li-        pDst[i + 3] = (OPJ_INT32)((val >> 4) & 0x1U);
252*ec63e07aSXin Li-        pDst[i + 4] = (OPJ_INT32)((val >> 3) & 0x1U);
253*ec63e07aSXin Li-        pDst[i + 5] = (OPJ_INT32)((val >> 2) & 0x1U);
254*ec63e07aSXin Li-        pDst[i + 6] = (OPJ_INT32)((val >> 1) & 0x1U);
255*ec63e07aSXin Li-        pDst[i + 7] = (OPJ_INT32)(val & 0x1U);
256*ec63e07aSXin Li-    }
257*ec63e07aSXin Li-    if (length & 7U) {
258*ec63e07aSXin Li-        OPJ_UINT32 val = *pSrc++;
259*ec63e07aSXin Li-        length = length & 7U;
260*ec63e07aSXin Li-        pDst[i + 0] = (OPJ_INT32)(val >> 7);
261*ec63e07aSXin Li-
262*ec63e07aSXin Li-        if (length > 1U) {
263*ec63e07aSXin Li-            pDst[i + 1] = (OPJ_INT32)((val >> 6) & 0x1U);
264*ec63e07aSXin Li-            if (length > 2U) {
265*ec63e07aSXin Li-                pDst[i + 2] = (OPJ_INT32)((val >> 5) & 0x1U);
266*ec63e07aSXin Li-                if (length > 3U) {
267*ec63e07aSXin Li-                    pDst[i + 3] = (OPJ_INT32)((val >> 4) & 0x1U);
268*ec63e07aSXin Li-                    if (length > 4U) {
269*ec63e07aSXin Li-                        pDst[i + 4] = (OPJ_INT32)((val >> 3) & 0x1U);
270*ec63e07aSXin Li-                        if (length > 5U) {
271*ec63e07aSXin Li-                            pDst[i + 5] = (OPJ_INT32)((val >> 2) & 0x1U);
272*ec63e07aSXin Li-                            if (length > 6U) {
273*ec63e07aSXin Li-                                pDst[i + 6] = (OPJ_INT32)((val >> 1) & 0x1U);
274*ec63e07aSXin Li-                            }
275*ec63e07aSXin Li-                        }
276*ec63e07aSXin Li-                    }
277*ec63e07aSXin Li-                }
278*ec63e07aSXin Li-            }
279*ec63e07aSXin Li-        }
280*ec63e07aSXin Li-    }
281*ec63e07aSXin Li-}
282*ec63e07aSXin Li-static void convert_2u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst,
283*ec63e07aSXin Li-                              OPJ_SIZE_T length)
284*ec63e07aSXin Li-{
285*ec63e07aSXin Li-    OPJ_SIZE_T i;
286*ec63e07aSXin Li-    for (i = 0; i < (length & ~(OPJ_SIZE_T)3U); i += 4U) {
287*ec63e07aSXin Li-        OPJ_UINT32 val = *pSrc++;
288*ec63e07aSXin Li-        pDst[i + 0] = (OPJ_INT32)(val >> 6);
289*ec63e07aSXin Li-        pDst[i + 1] = (OPJ_INT32)((val >> 4) & 0x3U);
290*ec63e07aSXin Li-        pDst[i + 2] = (OPJ_INT32)((val >> 2) & 0x3U);
291*ec63e07aSXin Li-        pDst[i + 3] = (OPJ_INT32)(val & 0x3U);
292*ec63e07aSXin Li-    }
293*ec63e07aSXin Li-    if (length & 3U) {
294*ec63e07aSXin Li-        OPJ_UINT32 val = *pSrc++;
295*ec63e07aSXin Li-        length = length & 3U;
296*ec63e07aSXin Li-        pDst[i + 0] = (OPJ_INT32)(val >> 6);
297*ec63e07aSXin Li-
298*ec63e07aSXin Li-        if (length > 1U) {
299*ec63e07aSXin Li-            pDst[i + 1] = (OPJ_INT32)((val >> 4) & 0x3U);
300*ec63e07aSXin Li-            if (length > 2U) {
301*ec63e07aSXin Li-                pDst[i + 2] = (OPJ_INT32)((val >> 2) & 0x3U);
302*ec63e07aSXin Li+#define OPJ_TRUE 1
303*ec63e07aSXin Li+#define OPJ_FALSE 0
304*ec63e07aSXin Li
305*ec63e07aSXin Li-            }
306*ec63e07aSXin Li-        }
307*ec63e07aSXin Li-    }
308*ec63e07aSXin Li-}
309*ec63e07aSXin Li-static void convert_4u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst,
310*ec63e07aSXin Li-                              OPJ_SIZE_T length)
311*ec63e07aSXin Li-{
312*ec63e07aSXin Li-    OPJ_SIZE_T i;
313*ec63e07aSXin Li-    for (i = 0; i < (length & ~(OPJ_SIZE_T)1U); i += 2U) {
314*ec63e07aSXin Li-        OPJ_UINT32 val = *pSrc++;
315*ec63e07aSXin Li-        pDst[i + 0] = (OPJ_INT32)(val >> 4);
316*ec63e07aSXin Li-        pDst[i + 1] = (OPJ_INT32)(val & 0xFU);
317*ec63e07aSXin Li-    }
318*ec63e07aSXin Li-    if (length & 1U) {
319*ec63e07aSXin Li-        OPJ_UINT8 val = *pSrc++;
320*ec63e07aSXin Li-        pDst[i + 0] = (OPJ_INT32)(val >> 4);
321*ec63e07aSXin Li-    }
322*ec63e07aSXin Li-}
323*ec63e07aSXin Li-static void convert_6u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst,
324*ec63e07aSXin Li-                              OPJ_SIZE_T length)
325*ec63e07aSXin Li-{
326*ec63e07aSXin Li-    OPJ_SIZE_T i;
327*ec63e07aSXin Li-    for (i = 0; i < (length & ~(OPJ_SIZE_T)3U); i += 4U) {
328*ec63e07aSXin Li-        OPJ_UINT32 val0 = *pSrc++;
329*ec63e07aSXin Li-        OPJ_UINT32 val1 = *pSrc++;
330*ec63e07aSXin Li-        OPJ_UINT32 val2 = *pSrc++;
331*ec63e07aSXin Li-        pDst[i + 0] = (OPJ_INT32)(val0 >> 2);
332*ec63e07aSXin Li-        pDst[i + 1] = (OPJ_INT32)(((val0 & 0x3U) << 4) | (val1 >> 4));
333*ec63e07aSXin Li-        pDst[i + 2] = (OPJ_INT32)(((val1 & 0xFU) << 2) | (val2 >> 6));
334*ec63e07aSXin Li-        pDst[i + 3] = (OPJ_INT32)(val2 & 0x3FU);
335*ec63e07aSXin Li+const char *opj_version(void) { return "2.3.1"; }
336*ec63e07aSXin Li
337*ec63e07aSXin Li-    }
338*ec63e07aSXin Li-    if (length & 3U) {
339*ec63e07aSXin Li-        OPJ_UINT32 val0 = *pSrc++;
340*ec63e07aSXin Li-        length = length & 3U;
341*ec63e07aSXin Li-        pDst[i + 0] = (OPJ_INT32)(val0 >> 2);
342*ec63e07aSXin Li-
343*ec63e07aSXin Li-        if (length > 1U) {
344*ec63e07aSXin Li-            OPJ_UINT32 val1 = *pSrc++;
345*ec63e07aSXin Li-            pDst[i + 1] = (OPJ_INT32)(((val0 & 0x3U) << 4) | (val1 >> 4));
346*ec63e07aSXin Li-            if (length > 2U) {
347*ec63e07aSXin Li-                OPJ_UINT32 val2 = *pSrc++;
348*ec63e07aSXin Li-                pDst[i + 2] = (OPJ_INT32)(((val1 & 0xFU) << 2) | (val2 >> 6));
349*ec63e07aSXin Li-            }
350*ec63e07aSXin Li-        }
351*ec63e07aSXin Li-    }
352*ec63e07aSXin Li-}
353*ec63e07aSXin Li-static void convert_8u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst,
354*ec63e07aSXin Li-                              OPJ_SIZE_T length)
355*ec63e07aSXin Li-{
356*ec63e07aSXin Li-    OPJ_SIZE_T i;
357*ec63e07aSXin Li-    for (i = 0; i < length; i++) {
358*ec63e07aSXin Li-        pDst[i] = pSrc[i];
359*ec63e07aSXin Li-    }
360*ec63e07aSXin Li-}
361*ec63e07aSXin Li-const convert_XXx32s_C1R convert_XXu32s_C1R_LUT[9] = {
362*ec63e07aSXin Li-    NULL,
363*ec63e07aSXin Li-    convert_1u32s_C1R,
364*ec63e07aSXin Li-    convert_2u32s_C1R,
365*ec63e07aSXin Li-    NULL,
366*ec63e07aSXin Li-    convert_4u32s_C1R,
367*ec63e07aSXin Li-    NULL,
368*ec63e07aSXin Li-    convert_6u32s_C1R,
369*ec63e07aSXin Li-    NULL,
370*ec63e07aSXin Li-    convert_8u32s_C1R
371*ec63e07aSXin Li-};
372*ec63e07aSXin Li-
373*ec63e07aSXin Li-
374*ec63e07aSXin Li-static void convert_32s1u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst,
375*ec63e07aSXin Li-                              OPJ_SIZE_T length)
376*ec63e07aSXin Li-{
377*ec63e07aSXin Li-    OPJ_SIZE_T i;
378*ec63e07aSXin Li-    for (i = 0; i < (length & ~(OPJ_SIZE_T)7U); i += 8U) {
379*ec63e07aSXin Li-        OPJ_UINT32 src0 = (OPJ_UINT32)pSrc[i + 0];
380*ec63e07aSXin Li-        OPJ_UINT32 src1 = (OPJ_UINT32)pSrc[i + 1];
381*ec63e07aSXin Li-        OPJ_UINT32 src2 = (OPJ_UINT32)pSrc[i + 2];
382*ec63e07aSXin Li-        OPJ_UINT32 src3 = (OPJ_UINT32)pSrc[i + 3];
383*ec63e07aSXin Li-        OPJ_UINT32 src4 = (OPJ_UINT32)pSrc[i + 4];
384*ec63e07aSXin Li-        OPJ_UINT32 src5 = (OPJ_UINT32)pSrc[i + 5];
385*ec63e07aSXin Li-        OPJ_UINT32 src6 = (OPJ_UINT32)pSrc[i + 6];
386*ec63e07aSXin Li-        OPJ_UINT32 src7 = (OPJ_UINT32)pSrc[i + 7];
387*ec63e07aSXin Li-
388*ec63e07aSXin Li-        *pDst++ = (OPJ_BYTE)((src0 << 7) | (src1 << 6) | (src2 << 5) | (src3 << 4) |
389*ec63e07aSXin Li-                             (src4 << 3) | (src5 << 2) | (src6 << 1) | src7);
390*ec63e07aSXin Li-    }
391*ec63e07aSXin Li-
392*ec63e07aSXin Li-    if (length & 7U) {
393*ec63e07aSXin Li-        OPJ_UINT32 src0 = (OPJ_UINT32)pSrc[i + 0];
394*ec63e07aSXin Li-        OPJ_UINT32 src1 = 0U;
395*ec63e07aSXin Li-        OPJ_UINT32 src2 = 0U;
396*ec63e07aSXin Li-        OPJ_UINT32 src3 = 0U;
397*ec63e07aSXin Li-        OPJ_UINT32 src4 = 0U;
398*ec63e07aSXin Li-        OPJ_UINT32 src5 = 0U;
399*ec63e07aSXin Li-        OPJ_UINT32 src6 = 0U;
400*ec63e07aSXin Li-        length = length & 7U;
401*ec63e07aSXin Li-
402*ec63e07aSXin Li-        if (length > 1U) {
403*ec63e07aSXin Li-            src1 = (OPJ_UINT32)pSrc[i + 1];
404*ec63e07aSXin Li-            if (length > 2U) {
405*ec63e07aSXin Li-                src2 = (OPJ_UINT32)pSrc[i + 2];
406*ec63e07aSXin Li-                if (length > 3U) {
407*ec63e07aSXin Li-                    src3 = (OPJ_UINT32)pSrc[i + 3];
408*ec63e07aSXin Li-                    if (length > 4U) {
409*ec63e07aSXin Li-                        src4 = (OPJ_UINT32)pSrc[i + 4];
410*ec63e07aSXin Li-                        if (length > 5U) {
411*ec63e07aSXin Li-                            src5 = (OPJ_UINT32)pSrc[i + 5];
412*ec63e07aSXin Li-                            if (length > 6U) {
413*ec63e07aSXin Li-                                src6 = (OPJ_UINT32)pSrc[i + 6];
414*ec63e07aSXin Li-                            }
415*ec63e07aSXin Li-                        }
416*ec63e07aSXin Li-                    }
417*ec63e07aSXin Li-                }
418*ec63e07aSXin Li-            }
419*ec63e07aSXin Li-        }
420*ec63e07aSXin Li-        *pDst++ = (OPJ_BYTE)((src0 << 7) | (src1 << 6) | (src2 << 5) | (src3 << 4) |
421*ec63e07aSXin Li-                             (src4 << 3) | (src5 << 2) | (src6 << 1));
422*ec63e07aSXin Li-    }
423*ec63e07aSXin Li-}
424*ec63e07aSXin Li-
425*ec63e07aSXin Li-static void convert_32s2u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst,
426*ec63e07aSXin Li-                              OPJ_SIZE_T length)
427*ec63e07aSXin Li-{
428*ec63e07aSXin Li-    OPJ_SIZE_T i;
429*ec63e07aSXin Li-    for (i = 0; i < (length & ~(OPJ_SIZE_T)3U); i += 4U) {
430*ec63e07aSXin Li-        OPJ_UINT32 src0 = (OPJ_UINT32)pSrc[i + 0];
431*ec63e07aSXin Li-        OPJ_UINT32 src1 = (OPJ_UINT32)pSrc[i + 1];
432*ec63e07aSXin Li-        OPJ_UINT32 src2 = (OPJ_UINT32)pSrc[i + 2];
433*ec63e07aSXin Li-        OPJ_UINT32 src3 = (OPJ_UINT32)pSrc[i + 3];
434*ec63e07aSXin Li-
435*ec63e07aSXin Li-        *pDst++ = (OPJ_BYTE)((src0 << 6) | (src1 << 4) | (src2 << 2) | src3);
436*ec63e07aSXin Li-    }
437*ec63e07aSXin Li-
438*ec63e07aSXin Li-    if (length & 3U) {
439*ec63e07aSXin Li-        OPJ_UINT32 src0 = (OPJ_UINT32)pSrc[i + 0];
440*ec63e07aSXin Li-        OPJ_UINT32 src1 = 0U;
441*ec63e07aSXin Li-        OPJ_UINT32 src2 = 0U;
442*ec63e07aSXin Li-        length = length & 3U;
443*ec63e07aSXin Li-
444*ec63e07aSXin Li-        if (length > 1U) {
445*ec63e07aSXin Li-            src1 = (OPJ_UINT32)pSrc[i + 1];
446*ec63e07aSXin Li-            if (length > 2U) {
447*ec63e07aSXin Li-                src2 = (OPJ_UINT32)pSrc[i + 2];
448*ec63e07aSXin Li-            }
449*ec63e07aSXin Li-        }
450*ec63e07aSXin Li-        *pDst++ = (OPJ_BYTE)((src0 << 6) | (src1 << 4) | (src2 << 2));
451*ec63e07aSXin Li-    }
452*ec63e07aSXin Li-}
453*ec63e07aSXin Li-
454*ec63e07aSXin Li-static void convert_32s4u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst,
455*ec63e07aSXin Li-                              OPJ_SIZE_T length)
456*ec63e07aSXin Li-{
457*ec63e07aSXin Li-    OPJ_SIZE_T i;
458*ec63e07aSXin Li-    for (i = 0; i < (length & ~(OPJ_SIZE_T)1U); i += 2U) {
459*ec63e07aSXin Li-        OPJ_UINT32 src0 = (OPJ_UINT32)pSrc[i + 0];
460*ec63e07aSXin Li-        OPJ_UINT32 src1 = (OPJ_UINT32)pSrc[i + 1];
461*ec63e07aSXin Li-
462*ec63e07aSXin Li-        *pDst++ = (OPJ_BYTE)((src0 << 4) | src1);
463*ec63e07aSXin Li-    }
464*ec63e07aSXin Li-
465*ec63e07aSXin Li-    if (length & 1U) {
466*ec63e07aSXin Li-        OPJ_UINT32 src0 = (OPJ_UINT32)pSrc[i + 0];
467*ec63e07aSXin Li-        *pDst++ = (OPJ_BYTE)((src0 << 4));
468*ec63e07aSXin Li-    }
469*ec63e07aSXin Li-}
470*ec63e07aSXin Li-
471*ec63e07aSXin Li-static void convert_32s6u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst,
472*ec63e07aSXin Li-                              OPJ_SIZE_T length)
473*ec63e07aSXin Li-{
474*ec63e07aSXin Li-    OPJ_SIZE_T i;
475*ec63e07aSXin Li-    for (i = 0; i < (length & ~(OPJ_SIZE_T)3U); i += 4U) {
476*ec63e07aSXin Li-        OPJ_UINT32 src0 = (OPJ_UINT32)pSrc[i + 0];
477*ec63e07aSXin Li-        OPJ_UINT32 src1 = (OPJ_UINT32)pSrc[i + 1];
478*ec63e07aSXin Li-        OPJ_UINT32 src2 = (OPJ_UINT32)pSrc[i + 2];
479*ec63e07aSXin Li-        OPJ_UINT32 src3 = (OPJ_UINT32)pSrc[i + 3];
480*ec63e07aSXin Li-
481*ec63e07aSXin Li-        *pDst++ = (OPJ_BYTE)((src0 << 2) | (src1 >> 4));
482*ec63e07aSXin Li-        *pDst++ = (OPJ_BYTE)(((src1 & 0xFU) << 4) | (src2 >> 2));
483*ec63e07aSXin Li-        *pDst++ = (OPJ_BYTE)(((src2 & 0x3U) << 6) | src3);
484*ec63e07aSXin Li-    }
485*ec63e07aSXin Li-
486*ec63e07aSXin Li-    if (length & 3U) {
487*ec63e07aSXin Li-        OPJ_UINT32 src0 = (OPJ_UINT32)pSrc[i + 0];
488*ec63e07aSXin Li-        OPJ_UINT32 src1 = 0U;
489*ec63e07aSXin Li-        OPJ_UINT32 src2 = 0U;
490*ec63e07aSXin Li-        length = length & 3U;
491*ec63e07aSXin Li-
492*ec63e07aSXin Li-        if (length > 1U) {
493*ec63e07aSXin Li-            src1 = (OPJ_UINT32)pSrc[i + 1];
494*ec63e07aSXin Li-            if (length > 2U) {
495*ec63e07aSXin Li-                src2 = (OPJ_UINT32)pSrc[i + 2];
496*ec63e07aSXin Li-            }
497*ec63e07aSXin Li-        }
498*ec63e07aSXin Li-        *pDst++ = (OPJ_BYTE)((src0 << 2) | (src1 >> 4));
499*ec63e07aSXin Li-        if (length > 1U) {
500*ec63e07aSXin Li-            *pDst++ = (OPJ_BYTE)(((src1 & 0xFU) << 4) | (src2 >> 2));
501*ec63e07aSXin Li-            if (length > 2U) {
502*ec63e07aSXin Li-                *pDst++ = (OPJ_BYTE)(((src2 & 0x3U) << 6));
503*ec63e07aSXin Li-            }
504*ec63e07aSXin Li-        }
505*ec63e07aSXin Li-    }
506*ec63e07aSXin Li-}
507*ec63e07aSXin Li-static void convert_32s8u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst,
508*ec63e07aSXin Li-                              OPJ_SIZE_T length)
509*ec63e07aSXin Li-{
510*ec63e07aSXin Li-    OPJ_SIZE_T i;
511*ec63e07aSXin Li-    for (i = 0; i < length; ++i) {
512*ec63e07aSXin Li-        pDst[i] = (OPJ_BYTE)pSrc[i];
513*ec63e07aSXin Li-    }
514*ec63e07aSXin Li-}
515*ec63e07aSXin Li-const convert_32sXXx_C1R convert_32sXXu_C1R_LUT[9] = {
516*ec63e07aSXin Li-    NULL,
517*ec63e07aSXin Li-    convert_32s1u_C1R,
518*ec63e07aSXin Li-    convert_32s2u_C1R,
519*ec63e07aSXin Li-    NULL,
520*ec63e07aSXin Li-    convert_32s4u_C1R,
521*ec63e07aSXin Li-    NULL,
522*ec63e07aSXin Li-    convert_32s6u_C1R,
523*ec63e07aSXin Li-    NULL,
524*ec63e07aSXin Li-    convert_32s8u_C1R
525*ec63e07aSXin Li-};
526*ec63e07aSXin Li-
527*ec63e07aSXin Li-/* -->> -->> -->> -->>
528*ec63e07aSXin Li-
529*ec63e07aSXin Li-  TGA IMAGE FORMAT
530*ec63e07aSXin Li-
531*ec63e07aSXin Li- <<-- <<-- <<-- <<-- */
532*ec63e07aSXin Li-
533*ec63e07aSXin Li-#ifdef INFORMATION_ONLY
534*ec63e07aSXin Li-/* TGA header definition. */
535*ec63e07aSXin Li-struct tga_header {
536*ec63e07aSXin Li-    unsigned char   id_length;              /* Image id field length    */
537*ec63e07aSXin Li-    unsigned char   colour_map_type;        /* Colour map type          */
538*ec63e07aSXin Li-    unsigned char   image_type;             /* Image type               */
539*ec63e07aSXin Li-    /*
540*ec63e07aSXin Li-    ** Colour map specification
541*ec63e07aSXin Li-    */
542*ec63e07aSXin Li-    unsigned short  colour_map_index;       /* First entry index        */
543*ec63e07aSXin Li-    unsigned short  colour_map_length;      /* Colour map length        */
544*ec63e07aSXin Li-    unsigned char   colour_map_entry_size;  /* Colour map entry size    */
545*ec63e07aSXin Li-    /*
546*ec63e07aSXin Li-    ** Image specification
547*ec63e07aSXin Li-    */
548*ec63e07aSXin Li-    unsigned short  x_origin;               /* x origin of image        */
549*ec63e07aSXin Li-    unsigned short  y_origin;               /* u origin of image        */
550*ec63e07aSXin Li-    unsigned short  image_width;            /* Image width              */
551*ec63e07aSXin Li-    unsigned short  image_height;           /* Image height             */
552*ec63e07aSXin Li-    unsigned char   pixel_depth;            /* Pixel depth              */
553*ec63e07aSXin Li-    unsigned char   image_desc;             /* Image descriptor         */
554*ec63e07aSXin Li-};
555*ec63e07aSXin Li-#endif /* INFORMATION_ONLY */
556*ec63e07aSXin Li-
557*ec63e07aSXin Li-/* Returns a ushort from a little-endian serialized value */
558*ec63e07aSXin Li-static unsigned short get_tga_ushort(const unsigned char *data)
559*ec63e07aSXin Li-{
560*ec63e07aSXin Li-    return (unsigned short)(data[0] | (data[1] << 8));
561*ec63e07aSXin Li-}
562*ec63e07aSXin Li-
563*ec63e07aSXin Li-#define TGA_HEADER_SIZE 18
564*ec63e07aSXin Li-
565*ec63e07aSXin Li-static int tga_readheader(FILE *fp, unsigned int *bits_per_pixel,
566*ec63e07aSXin Li-                          unsigned int *width, unsigned int *height, int *flip_image)
567*ec63e07aSXin Li-{
568*ec63e07aSXin Li-    int palette_size;
569*ec63e07aSXin Li-    unsigned char tga[TGA_HEADER_SIZE];
570*ec63e07aSXin Li-    unsigned char id_len, /*cmap_type,*/ image_type;
571*ec63e07aSXin Li-    unsigned char pixel_depth, image_desc;
572*ec63e07aSXin Li-    unsigned short /*cmap_index,*/ cmap_len, cmap_entry_size;
573*ec63e07aSXin Li-    unsigned short /*x_origin, y_origin,*/ image_w, image_h;
574*ec63e07aSXin Li-
575*ec63e07aSXin Li-    if (!bits_per_pixel || !width || !height || !flip_image) {
576*ec63e07aSXin Li-        return 0;
577*ec63e07aSXin Li-    }
578*ec63e07aSXin Li-
579*ec63e07aSXin Li-    if (fread(tga, TGA_HEADER_SIZE, 1, fp) != 1) {
580*ec63e07aSXin Li-        fprintf(stderr,
581*ec63e07aSXin Li-                "\nError: fread return a number of element different from the expected.\n");
582*ec63e07aSXin Li-        return 0 ;
583*ec63e07aSXin Li-    }
584*ec63e07aSXin Li-    id_len = tga[0];
585*ec63e07aSXin Li-    /*cmap_type = tga[1];*/
586*ec63e07aSXin Li-    image_type = tga[2];
587*ec63e07aSXin Li-    /*cmap_index = get_tga_ushort(&tga[3]);*/
588*ec63e07aSXin Li-    cmap_len = get_tga_ushort(&tga[5]);
589*ec63e07aSXin Li-    cmap_entry_size = tga[7];
590*ec63e07aSXin Li-
591*ec63e07aSXin Li-
592*ec63e07aSXin Li-#if 0
593*ec63e07aSXin Li-    x_origin = get_tga_ushort(&tga[8]);
594*ec63e07aSXin Li-    y_origin = get_tga_ushort(&tga[10]);
595*ec63e07aSXin Li-#endif
596*ec63e07aSXin Li-    image_w = get_tga_ushort(&tga[12]);
597*ec63e07aSXin Li-    image_h = get_tga_ushort(&tga[14]);
598*ec63e07aSXin Li-    pixel_depth = tga[16];
599*ec63e07aSXin Li-    image_desc  = tga[17];
600*ec63e07aSXin Li-
601*ec63e07aSXin Li-    *bits_per_pixel = (unsigned int)pixel_depth;
602*ec63e07aSXin Li-    *width  = (unsigned int)image_w;
603*ec63e07aSXin Li-    *height = (unsigned int)image_h;
604*ec63e07aSXin Li-
605*ec63e07aSXin Li-    /* Ignore tga identifier, if present ... */
606*ec63e07aSXin Li-    if (id_len) {
607*ec63e07aSXin Li-        unsigned char *id = (unsigned char *) malloc(id_len);
608*ec63e07aSXin Li-        if (id == 0) {
609*ec63e07aSXin Li-            fprintf(stderr, "tga_readheader: memory out\n");
610*ec63e07aSXin Li-            return 0;
611*ec63e07aSXin Li-        }
612*ec63e07aSXin Li-        if (!fread(id, id_len, 1, fp)) {
613*ec63e07aSXin Li-            fprintf(stderr,
614*ec63e07aSXin Li-                    "\nError: fread return a number of element different from the expected.\n");
615*ec63e07aSXin Li-            free(id);
616*ec63e07aSXin Li-            return 0 ;
617*ec63e07aSXin Li-        }
618*ec63e07aSXin Li-        free(id);
619*ec63e07aSXin Li-    }
620*ec63e07aSXin Li-
621*ec63e07aSXin Li-    /* Test for compressed formats ... not yet supported ...
622*ec63e07aSXin Li-    // Note :-  9 - RLE encoded palettized.
623*ec63e07aSXin Li-    //         10 - RLE encoded RGB. */
624*ec63e07aSXin Li-    if (image_type > 8) {
625*ec63e07aSXin Li-        fprintf(stderr, "Sorry, compressed tga files are not currently supported.\n");
626*ec63e07aSXin Li-        return 0 ;
627*ec63e07aSXin Li-    }
628*ec63e07aSXin Li-
629*ec63e07aSXin Li-    *flip_image = !(image_desc & 32);
630*ec63e07aSXin Li-
631*ec63e07aSXin Li-    /* Palettized formats are not yet supported, skip over the palette, if present ... */
632*ec63e07aSXin Li-    palette_size = cmap_len * (cmap_entry_size / 8);
633*ec63e07aSXin Li-
634*ec63e07aSXin Li-    if (palette_size > 0) {
635*ec63e07aSXin Li-        fprintf(stderr, "File contains a palette - not yet supported.");
636*ec63e07aSXin Li-        fseek(fp, palette_size, SEEK_CUR);
637*ec63e07aSXin Li-    }
638*ec63e07aSXin Li+static int are_comps_similar(opj_image_t *image) {
639*ec63e07aSXin Li+  unsigned int i;
640*ec63e07aSXin Li+  for (i = 1; i < image->numcomps; i++) {
641*ec63e07aSXin Li+    if (image->comps[0].dx != image->comps[i].dx ||
642*ec63e07aSXin Li+        image->comps[0].dy != image->comps[i].dy ||
643*ec63e07aSXin Li+        (i <= 2 && (image->comps[0].prec != image->comps[i].prec ||
644*ec63e07aSXin Li+                    image->comps[0].sgnd != image->comps[i].sgnd))) {
645*ec63e07aSXin Li+      return OPJ_FALSE;
646*ec63e07aSXin Li+    }
647*ec63e07aSXin Li+  }
648*ec63e07aSXin Li+  return OPJ_TRUE;
649*ec63e07aSXin Li+}
650*ec63e07aSXin Li+
651*ec63e07aSXin Li+int imagetopnm(opj_image_t *image, const char *outfile, int force_split) {
652*ec63e07aSXin Li+  int *red, *green, *blue, *alpha;
653*ec63e07aSXin Li+  int wr, hr, max;
654*ec63e07aSXin Li+  int i;
655*ec63e07aSXin Li+  unsigned int compno, ncomp;
656*ec63e07aSXin Li+  int adjustR, adjustG, adjustB, adjustA;
657*ec63e07aSXin Li+  int fails, two, want_gray, has_alpha, triple;
658*ec63e07aSXin Li+  int prec, v;
659*ec63e07aSXin Li+  FILE *fdest = NULL;
660*ec63e07aSXin Li+  const char *tmp = outfile;
661*ec63e07aSXin Li+  char *destname;
662*ec63e07aSXin Li+
663*ec63e07aSXin Li+  alpha = NULL;
664*ec63e07aSXin Li+
665*ec63e07aSXin Li+  if ((prec = (int)image->comps[0].prec) > 16) {
666*ec63e07aSXin Li+    fprintf(stderr,
667*ec63e07aSXin Li+            "%s:%d:imagetopnm\n\tprecision %d is larger than 16"
668*ec63e07aSXin Li+            "\n\t: refused.\n",
669*ec63e07aSXin Li+            __FILE__, __LINE__, prec);
670*ec63e07aSXin Li     return 1;
671*ec63e07aSXin Li-}
672*ec63e07aSXin Li-
673*ec63e07aSXin Li-#ifdef OPJ_BIG_ENDIAN
674*ec63e07aSXin Li-
675*ec63e07aSXin Li-static INLINE OPJ_UINT16 swap16(OPJ_UINT16 x)
676*ec63e07aSXin Li-{
677*ec63e07aSXin Li-    return (OPJ_UINT16)(((x & 0x00ffU) <<  8) | ((x & 0xff00U) >>  8));
678*ec63e07aSXin Li-}
679*ec63e07aSXin Li-
680*ec63e07aSXin Li-#endif
681*ec63e07aSXin Li+  }
682*ec63e07aSXin Li
683*ec63e07aSXin Li-static int tga_writeheader(FILE *fp, int bits_per_pixel, int width, int height,
684*ec63e07aSXin Li-                           OPJ_BOOL flip_image)
685*ec63e07aSXin Li-{
686*ec63e07aSXin Li-    OPJ_UINT16 image_w, image_h, us0;
687*ec63e07aSXin Li-    unsigned char uc0, image_type;
688*ec63e07aSXin Li-    unsigned char pixel_depth, image_desc;
689*ec63e07aSXin Li-
690*ec63e07aSXin Li-    if (!bits_per_pixel || !width || !height) {
691*ec63e07aSXin Li-        return 0;
692*ec63e07aSXin Li-    }
693*ec63e07aSXin Li-
694*ec63e07aSXin Li-    pixel_depth = 0;
695*ec63e07aSXin Li-
696*ec63e07aSXin Li-    if (bits_per_pixel < 256) {
697*ec63e07aSXin Li-        pixel_depth = (unsigned char)bits_per_pixel;
698*ec63e07aSXin Li-    } else {
699*ec63e07aSXin Li-        fprintf(stderr, "ERROR: Wrong bits per pixel inside tga_header");
700*ec63e07aSXin Li-        return 0;
701*ec63e07aSXin Li-    }
702*ec63e07aSXin Li-    uc0 = 0;
703*ec63e07aSXin Li-
704*ec63e07aSXin Li-    if (fwrite(&uc0, 1, 1, fp) != 1) {
705*ec63e07aSXin Li-        goto fails;    /* id_length */
706*ec63e07aSXin Li-    }
707*ec63e07aSXin Li-    if (fwrite(&uc0, 1, 1, fp) != 1) {
708*ec63e07aSXin Li-        goto fails;    /* colour_map_type */
709*ec63e07aSXin Li-    }
710*ec63e07aSXin Li-
711*ec63e07aSXin Li-    image_type = 2; /* Uncompressed. */
712*ec63e07aSXin Li-    if (fwrite(&image_type, 1, 1, fp) != 1) {
713*ec63e07aSXin Li-        goto fails;
714*ec63e07aSXin Li-    }
715*ec63e07aSXin Li-
716*ec63e07aSXin Li-    us0 = 0;
717*ec63e07aSXin Li-    if (fwrite(&us0, 2, 1, fp) != 1) {
718*ec63e07aSXin Li-        goto fails;    /* colour_map_index */
719*ec63e07aSXin Li-    }
720*ec63e07aSXin Li-    if (fwrite(&us0, 2, 1, fp) != 1) {
721*ec63e07aSXin Li-        goto fails;    /* colour_map_length */
722*ec63e07aSXin Li-    }
723*ec63e07aSXin Li-    if (fwrite(&uc0, 1, 1, fp) != 1) {
724*ec63e07aSXin Li-        goto fails;    /* colour_map_entry_size */
725*ec63e07aSXin Li-    }
726*ec63e07aSXin Li-
727*ec63e07aSXin Li-    if (fwrite(&us0, 2, 1, fp) != 1) {
728*ec63e07aSXin Li-        goto fails;    /* x_origin */
729*ec63e07aSXin Li-    }
730*ec63e07aSXin Li-    if (fwrite(&us0, 2, 1, fp) != 1) {
731*ec63e07aSXin Li-        goto fails;    /* y_origin */
732*ec63e07aSXin Li-    }
733*ec63e07aSXin Li-
734*ec63e07aSXin Li-    image_w = (unsigned short)width;
735*ec63e07aSXin Li-    image_h = (unsigned short) height;
736*ec63e07aSXin Li-
737*ec63e07aSXin Li-#ifndef OPJ_BIG_ENDIAN
738*ec63e07aSXin Li-    if (fwrite(&image_w, 2, 1, fp) != 1) {
739*ec63e07aSXin Li-        goto fails;
740*ec63e07aSXin Li-    }
741*ec63e07aSXin Li-    if (fwrite(&image_h, 2, 1, fp) != 1) {
742*ec63e07aSXin Li-        goto fails;
743*ec63e07aSXin Li-    }
744*ec63e07aSXin Li-#else
745*ec63e07aSXin Li-    image_w = swap16(image_w);
746*ec63e07aSXin Li-    image_h = swap16(image_h);
747*ec63e07aSXin Li-    if (fwrite(&image_w, 2, 1, fp) != 1) {
748*ec63e07aSXin Li-        goto fails;
749*ec63e07aSXin Li-    }
750*ec63e07aSXin Li-    if (fwrite(&image_h, 2, 1, fp) != 1) {
751*ec63e07aSXin Li-        goto fails;
752*ec63e07aSXin Li-    }
753*ec63e07aSXin Li-#endif
754*ec63e07aSXin Li-
755*ec63e07aSXin Li-    if (fwrite(&pixel_depth, 1, 1, fp) != 1) {
756*ec63e07aSXin Li-        goto fails;
757*ec63e07aSXin Li-    }
758*ec63e07aSXin Li-
759*ec63e07aSXin Li-    image_desc = 8; /* 8 bits per component. */
760*ec63e07aSXin Li-
761*ec63e07aSXin Li-    if (flip_image) {
762*ec63e07aSXin Li-        image_desc |= 32;
763*ec63e07aSXin Li-    }
764*ec63e07aSXin Li-    if (fwrite(&image_desc, 1, 1, fp) != 1) {
765*ec63e07aSXin Li-        goto fails;
766*ec63e07aSXin Li-    }
767*ec63e07aSXin Li-
768*ec63e07aSXin Li-    return 1;
769*ec63e07aSXin Li-
770*ec63e07aSXin Li-fails:
771*ec63e07aSXin Li-    fputs("\nwrite_tgaheader: write ERROR\n", stderr);
772*ec63e07aSXin Li-    return 0;
773*ec63e07aSXin Li-}
774*ec63e07aSXin Li-
775*ec63e07aSXin Li-opj_image_t* tgatoimage(const char *filename, opj_cparameters_t *parameters)
776*ec63e07aSXin Li-{
777*ec63e07aSXin Li-    FILE *f;
778*ec63e07aSXin Li-    opj_image_t *image;
779*ec63e07aSXin Li-    unsigned int image_width, image_height, pixel_bit_depth;
780*ec63e07aSXin Li-    unsigned int x, y;
781*ec63e07aSXin Li-    int flip_image = 0;
782*ec63e07aSXin Li-    opj_image_cmptparm_t cmptparm[4];   /* maximum 4 components */
783*ec63e07aSXin Li-    int numcomps;
784*ec63e07aSXin Li-    OPJ_COLOR_SPACE color_space;
785*ec63e07aSXin Li-    OPJ_BOOL mono ;
786*ec63e07aSXin Li-    OPJ_BOOL save_alpha;
787*ec63e07aSXin Li-    int subsampling_dx, subsampling_dy;
788*ec63e07aSXin Li-    int i;
789*ec63e07aSXin Li-
790*ec63e07aSXin Li-    f = fopen(filename, "rb");
791*ec63e07aSXin Li-    if (!f) {
792*ec63e07aSXin Li-        fprintf(stderr, "Failed to open %s for reading !!\n", filename);
793*ec63e07aSXin Li-        return 0;
794*ec63e07aSXin Li-    }
795*ec63e07aSXin Li-
796*ec63e07aSXin Li-    if (!tga_readheader(f, &pixel_bit_depth, &image_width, &image_height,
797*ec63e07aSXin Li-                        &flip_image)) {
798*ec63e07aSXin Li-        fclose(f);
799*ec63e07aSXin Li-        return NULL;
800*ec63e07aSXin Li-    }
801*ec63e07aSXin Li-
802*ec63e07aSXin Li-    /* We currently only support 24 & 32 bit tga's ... */
803*ec63e07aSXin Li-    if (!((pixel_bit_depth == 24) || (pixel_bit_depth == 32))) {
804*ec63e07aSXin Li-        fclose(f);
805*ec63e07aSXin Li-        return NULL;
806*ec63e07aSXin Li-    }
807*ec63e07aSXin Li-
808*ec63e07aSXin Li-    /* initialize image components */
809*ec63e07aSXin Li-    memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));
810*ec63e07aSXin Li-
811*ec63e07aSXin Li-    mono = (pixel_bit_depth == 8) ||
812*ec63e07aSXin Li-           (pixel_bit_depth == 16);  /* Mono with & without alpha. */
813*ec63e07aSXin Li-    save_alpha = (pixel_bit_depth == 16) ||
814*ec63e07aSXin Li-                 (pixel_bit_depth == 32); /* Mono with alpha, or RGB with alpha */
815*ec63e07aSXin Li-
816*ec63e07aSXin Li-    if (mono) {
817*ec63e07aSXin Li-        color_space = OPJ_CLRSPC_GRAY;
818*ec63e07aSXin Li-        numcomps = save_alpha ? 2 : 1;
819*ec63e07aSXin Li-    } else {
820*ec63e07aSXin Li-        numcomps = save_alpha ? 4 : 3;
821*ec63e07aSXin Li-        color_space = OPJ_CLRSPC_SRGB;
822*ec63e07aSXin Li-    }
823*ec63e07aSXin Li-
824*ec63e07aSXin Li-    /* If the declared file size is > 10 MB, check that the file is big */
825*ec63e07aSXin Li-    /* enough to avoid excessive memory allocations */
826*ec63e07aSXin Li-    if (image_height != 0 &&
827*ec63e07aSXin Li-            image_width > 10000000U / image_height / (OPJ_UINT32)numcomps) {
828*ec63e07aSXin Li-        char ch;
829*ec63e07aSXin Li-        OPJ_UINT64 expected_file_size =
830*ec63e07aSXin Li-            (OPJ_UINT64)image_width * image_height * (OPJ_UINT32)numcomps;
831*ec63e07aSXin Li-        long curpos = ftell(f);
832*ec63e07aSXin Li-        if (expected_file_size > (OPJ_UINT64)INT_MAX) {
833*ec63e07aSXin Li-            expected_file_size = (OPJ_UINT64)INT_MAX;
834*ec63e07aSXin Li-        }
835*ec63e07aSXin Li-        fseek(f, (long)expected_file_size - 1, SEEK_SET);
836*ec63e07aSXin Li-        if (fread(&ch, 1, 1, f) != 1) {
837*ec63e07aSXin Li-            fclose(f);
838*ec63e07aSXin Li-            return NULL;
839*ec63e07aSXin Li-        }
840*ec63e07aSXin Li-        fseek(f, curpos, SEEK_SET);
841*ec63e07aSXin Li-    }
842*ec63e07aSXin Li-
843*ec63e07aSXin Li-    subsampling_dx = parameters->subsampling_dx;
844*ec63e07aSXin Li-    subsampling_dy = parameters->subsampling_dy;
845*ec63e07aSXin Li-
846*ec63e07aSXin Li-    for (i = 0; i < numcomps; i++) {
847*ec63e07aSXin Li-        cmptparm[i].prec = 8;
848*ec63e07aSXin Li-        cmptparm[i].bpp = 8;
849*ec63e07aSXin Li-        cmptparm[i].sgnd = 0;
850*ec63e07aSXin Li-        cmptparm[i].dx = (OPJ_UINT32)subsampling_dx;
851*ec63e07aSXin Li-        cmptparm[i].dy = (OPJ_UINT32)subsampling_dy;
852*ec63e07aSXin Li-        cmptparm[i].w = image_width;
853*ec63e07aSXin Li-        cmptparm[i].h = image_height;
854*ec63e07aSXin Li-    }
855*ec63e07aSXin Li-
856*ec63e07aSXin Li-    /* create the image */
857*ec63e07aSXin Li-    image = opj_image_create((OPJ_UINT32)numcomps, &cmptparm[0], color_space);
858*ec63e07aSXin Li-
859*ec63e07aSXin Li-    if (!image) {
860*ec63e07aSXin Li-        fclose(f);
861*ec63e07aSXin Li-        return NULL;
862*ec63e07aSXin Li-    }
863*ec63e07aSXin Li-
864*ec63e07aSXin Li-
865*ec63e07aSXin Li-    /* set image offset and reference grid */
866*ec63e07aSXin Li-    image->x0 = (OPJ_UINT32)parameters->image_offset_x0;
867*ec63e07aSXin Li-    image->y0 = (OPJ_UINT32)parameters->image_offset_y0;
868*ec63e07aSXin Li-    image->x1 = !image->x0 ? (OPJ_UINT32)(image_width - 1)  *
869*ec63e07aSXin Li-                (OPJ_UINT32)subsampling_dx + 1 : image->x0 + (OPJ_UINT32)(image_width - 1)  *
870*ec63e07aSXin Li-                (OPJ_UINT32)subsampling_dx + 1;
871*ec63e07aSXin Li-    image->y1 = !image->y0 ? (OPJ_UINT32)(image_height - 1) *
872*ec63e07aSXin Li-                (OPJ_UINT32)subsampling_dy + 1 : image->y0 + (OPJ_UINT32)(image_height - 1) *
873*ec63e07aSXin Li-                (OPJ_UINT32)subsampling_dy + 1;
874*ec63e07aSXin Li-
875*ec63e07aSXin Li-    /* set image data */
876*ec63e07aSXin Li-    for (y = 0; y < image_height; y++) {
877*ec63e07aSXin Li-        int index;
878*ec63e07aSXin Li-
879*ec63e07aSXin Li-        if (flip_image) {
880*ec63e07aSXin Li-            index = (int)((image_height - y - 1) * image_width);
881*ec63e07aSXin Li-        } else {
882*ec63e07aSXin Li-            index = (int)(y * image_width);
883*ec63e07aSXin Li-        }
884*ec63e07aSXin Li-
885*ec63e07aSXin Li-        if (numcomps == 3) {
886*ec63e07aSXin Li-            for (x = 0; x < image_width; x++) {
887*ec63e07aSXin Li-                unsigned char r, g, b;
888*ec63e07aSXin Li-
889*ec63e07aSXin Li-                if (!fread(&b, 1, 1, f)) {
890*ec63e07aSXin Li-                    fprintf(stderr,
891*ec63e07aSXin Li-                            "\nError: fread return a number of element different from the expected.\n");
892*ec63e07aSXin Li-                    opj_image_destroy(image);
893*ec63e07aSXin Li-                    fclose(f);
894*ec63e07aSXin Li-                    return NULL;
895*ec63e07aSXin Li-                }
896*ec63e07aSXin Li-                if (!fread(&g, 1, 1, f)) {
897*ec63e07aSXin Li-                    fprintf(stderr,
898*ec63e07aSXin Li-                            "\nError: fread return a number of element different from the expected.\n");
899*ec63e07aSXin Li-                    opj_image_destroy(image);
900*ec63e07aSXin Li-                    fclose(f);
901*ec63e07aSXin Li-                    return NULL;
902*ec63e07aSXin Li-                }
903*ec63e07aSXin Li-                if (!fread(&r, 1, 1, f)) {
904*ec63e07aSXin Li-                    fprintf(stderr,
905*ec63e07aSXin Li-                            "\nError: fread return a number of element different from the expected.\n");
906*ec63e07aSXin Li-                    opj_image_destroy(image);
907*ec63e07aSXin Li-                    fclose(f);
908*ec63e07aSXin Li-                    return NULL;
909*ec63e07aSXin Li-                }
910*ec63e07aSXin Li-
911*ec63e07aSXin Li-                image->comps[0].data[index] = r;
912*ec63e07aSXin Li-                image->comps[1].data[index] = g;
913*ec63e07aSXin Li-                image->comps[2].data[index] = b;
914*ec63e07aSXin Li-                index++;
915*ec63e07aSXin Li-            }
916*ec63e07aSXin Li-        } else if (numcomps == 4) {
917*ec63e07aSXin Li-            for (x = 0; x < image_width; x++) {
918*ec63e07aSXin Li-                unsigned char r, g, b, a;
919*ec63e07aSXin Li-                if (!fread(&b, 1, 1, f)) {
920*ec63e07aSXin Li-                    fprintf(stderr,
921*ec63e07aSXin Li-                            "\nError: fread return a number of element different from the expected.\n");
922*ec63e07aSXin Li-                    opj_image_destroy(image);
923*ec63e07aSXin Li-                    fclose(f);
924*ec63e07aSXin Li-                    return NULL;
925*ec63e07aSXin Li-                }
926*ec63e07aSXin Li-                if (!fread(&g, 1, 1, f)) {
927*ec63e07aSXin Li-                    fprintf(stderr,
928*ec63e07aSXin Li-                            "\nError: fread return a number of element different from the expected.\n");
929*ec63e07aSXin Li-                    opj_image_destroy(image);
930*ec63e07aSXin Li-                    fclose(f);
931*ec63e07aSXin Li-                    return NULL;
932*ec63e07aSXin Li-                }
933*ec63e07aSXin Li-                if (!fread(&r, 1, 1, f)) {
934*ec63e07aSXin Li-                    fprintf(stderr,
935*ec63e07aSXin Li-                            "\nError: fread return a number of element different from the expected.\n");
936*ec63e07aSXin Li-                    opj_image_destroy(image);
937*ec63e07aSXin Li-                    fclose(f);
938*ec63e07aSXin Li-                    return NULL;
939*ec63e07aSXin Li-                }
940*ec63e07aSXin Li-                if (!fread(&a, 1, 1, f)) {
941*ec63e07aSXin Li-                    fprintf(stderr,
942*ec63e07aSXin Li-                            "\nError: fread return a number of element different from the expected.\n");
943*ec63e07aSXin Li-                    opj_image_destroy(image);
944*ec63e07aSXin Li-                    fclose(f);
945*ec63e07aSXin Li-                    return NULL;
946*ec63e07aSXin Li-                }
947*ec63e07aSXin Li-
948*ec63e07aSXin Li-                image->comps[0].data[index] = r;
949*ec63e07aSXin Li-                image->comps[1].data[index] = g;
950*ec63e07aSXin Li-                image->comps[2].data[index] = b;
951*ec63e07aSXin Li-                image->comps[3].data[index] = a;
952*ec63e07aSXin Li-                index++;
953*ec63e07aSXin Li-            }
954*ec63e07aSXin Li-        } else {
955*ec63e07aSXin Li-            fprintf(stderr, "Currently unsupported bit depth : %s\n", filename);
956*ec63e07aSXin Li-        }
957*ec63e07aSXin Li-    }
958*ec63e07aSXin Li-    fclose(f);
959*ec63e07aSXin Li-    return image;
960*ec63e07aSXin Li-}
961*ec63e07aSXin Li-
962*ec63e07aSXin Li-int imagetotga(opj_image_t * image, const char *outfile)
963*ec63e07aSXin Li-{
964*ec63e07aSXin Li-    int width, height, bpp, x, y;
965*ec63e07aSXin Li-    OPJ_BOOL write_alpha;
966*ec63e07aSXin Li-    unsigned int i;
967*ec63e07aSXin Li-    int adjustR, adjustG = 0, adjustB = 0, fails;
968*ec63e07aSXin Li-    unsigned int alpha_channel;
969*ec63e07aSXin Li-    float r, g, b, a;
970*ec63e07aSXin Li-    unsigned char value;
971*ec63e07aSXin Li-    float scale;
972*ec63e07aSXin Li-    FILE *fdest;
973*ec63e07aSXin Li-    size_t res;
974*ec63e07aSXin Li-    fails = 1;
975*ec63e07aSXin Li+  two = has_alpha = 0;
976*ec63e07aSXin Li+  fails = 1;
977*ec63e07aSXin Li+  ncomp = image->numcomps;
978*ec63e07aSXin Li+
979*ec63e07aSXin Li+  while (*tmp) {
980*ec63e07aSXin Li+    ++tmp;
981*ec63e07aSXin Li+  }
982*ec63e07aSXin Li+  tmp -= 2;
983*ec63e07aSXin Li+  want_gray = (*tmp == 'g' || *tmp == 'G');
984*ec63e07aSXin Li+  ncomp = image->numcomps;
985*ec63e07aSXin Li+
986*ec63e07aSXin Li+  if (want_gray) {
987*ec63e07aSXin Li+    ncomp = 1;
988*ec63e07aSXin Li+  }
989*ec63e07aSXin Li
990*ec63e07aSXin Li+  if ((force_split == 0) && ncomp >= 2 && are_comps_similar(image)) {
991*ec63e07aSXin Li     fdest = fopen(outfile, "wb");
992*ec63e07aSXin Li+
993*ec63e07aSXin Li     if (!fdest) {
994*ec63e07aSXin Li-        fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
995*ec63e07aSXin Li-        return 1;
996*ec63e07aSXin Li+      fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
997*ec63e07aSXin Li+      return fails;
998*ec63e07aSXin Li     }
999*ec63e07aSXin Li-
1000*ec63e07aSXin Li-    for (i = 0; i < image->numcomps - 1; i++) {
1001*ec63e07aSXin Li-        if ((image->comps[0].dx != image->comps[i + 1].dx)
1002*ec63e07aSXin Li-                || (image->comps[0].dy != image->comps[i + 1].dy)
1003*ec63e07aSXin Li-                || (image->comps[0].prec != image->comps[i + 1].prec)
1004*ec63e07aSXin Li-                || (image->comps[0].sgnd != image->comps[i + 1].sgnd)) {
1005*ec63e07aSXin Li-            fclose(fdest);
1006*ec63e07aSXin Li-            fprintf(stderr,
1007*ec63e07aSXin Li-                    "Unable to create a tga file with such J2K image charateristics.\n");
1008*ec63e07aSXin Li-            return 1;
1009*ec63e07aSXin Li-        }
1010*ec63e07aSXin Li+    two = (prec > 8);
1011*ec63e07aSXin Li+    triple = (ncomp > 2);
1012*ec63e07aSXin Li+    wr = (int)image->comps[0].w;
1013*ec63e07aSXin Li+    hr = (int)image->comps[0].h;
1014*ec63e07aSXin Li+    max = (1 << prec) - 1;
1015*ec63e07aSXin Li+    has_alpha = (ncomp == 4 || ncomp == 2);
1016*ec63e07aSXin Li+
1017*ec63e07aSXin Li+    red = image->comps[0].data;
1018*ec63e07aSXin Li+    if (red == NULL) {
1019*ec63e07aSXin Li+      fprintf(stderr, "imagetopnm: planes[%d] == NULL.\n", 0);
1020*ec63e07aSXin Li+      fprintf(stderr, "\tAborting\n");
1021*ec63e07aSXin Li+      fclose(fdest);
1022*ec63e07aSXin Li+      return fails;
1023*ec63e07aSXin Li+    }
1024*ec63e07aSXin Li+
1025*ec63e07aSXin Li+    if (triple) {
1026*ec63e07aSXin Li+      green = image->comps[1].data;
1027*ec63e07aSXin Li+      blue = image->comps[2].data;
1028*ec63e07aSXin Li+      for (i = 1; i <= 2; i++) {
1029*ec63e07aSXin Li+        if (image->comps[i].data == NULL) {
1030*ec63e07aSXin Li+          fprintf(stderr, "imagetopnm: planes[%d] == NULL.\n", i);
1031*ec63e07aSXin Li+          fprintf(stderr, "\tAborting\n");
1032*ec63e07aSXin Li+          fclose(fdest);
1033*ec63e07aSXin Li+          return fails;
1034*ec63e07aSXin Li+        }
1035*ec63e07aSXin Li+      }
1036*ec63e07aSXin Li+    } else {
1037*ec63e07aSXin Li+      green = blue = NULL;
1038*ec63e07aSXin Li+    }
1039*ec63e07aSXin Li+
1040*ec63e07aSXin Li+    if (has_alpha) {
1041*ec63e07aSXin Li+      const char *tt = (triple ? "RGB_ALPHA" : "GRAYSCALE_ALPHA");
1042*ec63e07aSXin Li+
1043*ec63e07aSXin Li+      fprintf(fdest,
1044*ec63e07aSXin Li+              "P7\n# OpenJPEG-%s\nWIDTH %d\nHEIGHT %d\nDEPTH %u\n"
1045*ec63e07aSXin Li+              "MAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
1046*ec63e07aSXin Li+              opj_version(), wr, hr, ncomp, max, tt);
1047*ec63e07aSXin Li+      alpha = image->comps[ncomp - 1].data;
1048*ec63e07aSXin Li+      adjustA = (image->comps[ncomp - 1].sgnd
1049*ec63e07aSXin Li+                     ? 1 << (image->comps[ncomp - 1].prec - 1)
1050*ec63e07aSXin Li+                     : 0);
1051*ec63e07aSXin Li+    } else {
1052*ec63e07aSXin Li+      fprintf(fdest, "P6\n# OpenJPEG-%s\n%d %d\n%d\n", opj_version(), wr, hr,
1053*ec63e07aSXin Li+              max);
1054*ec63e07aSXin Li+      adjustA = 0;
1055*ec63e07aSXin Li     }
1056*ec63e07aSXin Li-
1057*ec63e07aSXin Li-    width  = (int)image->comps[0].w;
1058*ec63e07aSXin Li-    height = (int)image->comps[0].h;
1059*ec63e07aSXin Li-
1060*ec63e07aSXin Li-    /* Mono with alpha, or RGB with alpha. */
1061*ec63e07aSXin Li-    write_alpha = (image->numcomps == 2) || (image->numcomps == 4);
1062*ec63e07aSXin Li-
1063*ec63e07aSXin Li-    /* Write TGA header  */
1064*ec63e07aSXin Li-    bpp = write_alpha ? 32 : 24;
1065*ec63e07aSXin Li-
1066*ec63e07aSXin Li-    if (!tga_writeheader(fdest, bpp, width, height, OPJ_TRUE)) {
1067*ec63e07aSXin Li-        goto fin;
1068*ec63e07aSXin Li-    }
1069*ec63e07aSXin Li-
1070*ec63e07aSXin Li-    alpha_channel = image->numcomps - 1;
1071*ec63e07aSXin Li-
1072*ec63e07aSXin Li-    scale = 255.0f / (float)((1 << image->comps[0].prec) - 1);
1073*ec63e07aSXin Li-
1074*ec63e07aSXin Li     adjustR = (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
1075*ec63e07aSXin Li-    if (image->numcomps >= 3) {
1076*ec63e07aSXin Li-        adjustG = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
1077*ec63e07aSXin Li-        adjustB = (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
1078*ec63e07aSXin Li-    }
1079*ec63e07aSXin Li-
1080*ec63e07aSXin Li-    for (y = 0; y < height; y++) {
1081*ec63e07aSXin Li-        unsigned int index = (unsigned int)(y * width);
1082*ec63e07aSXin Li-
1083*ec63e07aSXin Li-        for (x = 0; x < width; x++, index++) {
1084*ec63e07aSXin Li-            r = (float)(image->comps[0].data[index] + adjustR);
1085*ec63e07aSXin Li
1086*ec63e07aSXin Li-            if (image->numcomps > 2) {
1087*ec63e07aSXin Li-                g = (float)(image->comps[1].data[index] + adjustG);
1088*ec63e07aSXin Li-                b = (float)(image->comps[2].data[index] + adjustB);
1089*ec63e07aSXin Li-            } else {
1090*ec63e07aSXin Li-                /* Greyscale ... */
1091*ec63e07aSXin Li-                g = r;
1092*ec63e07aSXin Li-                b = r;
1093*ec63e07aSXin Li-            }
1094*ec63e07aSXin Li-
1095*ec63e07aSXin Li-            /* TGA format writes BGR ... */
1096*ec63e07aSXin Li-            if (b > 255.) {
1097*ec63e07aSXin Li-                b = 255.;
1098*ec63e07aSXin Li-            } else if (b < 0.) {
1099*ec63e07aSXin Li-                b = 0.;
1100*ec63e07aSXin Li-            }
1101*ec63e07aSXin Li-            value = (unsigned char)(b * scale);
1102*ec63e07aSXin Li-            res = fwrite(&value, 1, 1, fdest);
1103*ec63e07aSXin Li-
1104*ec63e07aSXin Li-            if (res < 1) {
1105*ec63e07aSXin Li-                fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
1106*ec63e07aSXin Li-                goto fin;
1107*ec63e07aSXin Li-            }
1108*ec63e07aSXin Li-            if (g > 255.) {
1109*ec63e07aSXin Li-                g = 255.;
1110*ec63e07aSXin Li-            } else if (g < 0.) {
1111*ec63e07aSXin Li-                g = 0.;
1112*ec63e07aSXin Li-            }
1113*ec63e07aSXin Li-            value = (unsigned char)(g * scale);
1114*ec63e07aSXin Li-            res = fwrite(&value, 1, 1, fdest);
1115*ec63e07aSXin Li-
1116*ec63e07aSXin Li-            if (res < 1) {
1117*ec63e07aSXin Li-                fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
1118*ec63e07aSXin Li-                goto fin;
1119*ec63e07aSXin Li-            }
1120*ec63e07aSXin Li-            if (r > 255.) {
1121*ec63e07aSXin Li-                r = 255.;
1122*ec63e07aSXin Li-            } else if (r < 0.) {
1123*ec63e07aSXin Li-                r = 0.;
1124*ec63e07aSXin Li-            }
1125*ec63e07aSXin Li-            value = (unsigned char)(r * scale);
1126*ec63e07aSXin Li-            res = fwrite(&value, 1, 1, fdest);
1127*ec63e07aSXin Li-
1128*ec63e07aSXin Li-            if (res < 1) {
1129*ec63e07aSXin Li-                fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
1130*ec63e07aSXin Li-                goto fin;
1131*ec63e07aSXin Li-            }
1132*ec63e07aSXin Li-
1133*ec63e07aSXin Li-            if (write_alpha) {
1134*ec63e07aSXin Li-                a = (float)(image->comps[alpha_channel].data[index]);
1135*ec63e07aSXin Li-                if (a > 255.) {
1136*ec63e07aSXin Li-                    a = 255.;
1137*ec63e07aSXin Li-                } else if (a < 0.) {
1138*ec63e07aSXin Li-                    a = 0.;
1139*ec63e07aSXin Li-                }
1140*ec63e07aSXin Li-                value = (unsigned char)(a * scale);
1141*ec63e07aSXin Li-                res = fwrite(&value, 1, 1, fdest);
1142*ec63e07aSXin Li-
1143*ec63e07aSXin Li-                if (res < 1) {
1144*ec63e07aSXin Li-                    fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
1145*ec63e07aSXin Li-                    goto fin;
1146*ec63e07aSXin Li-                }
1147*ec63e07aSXin Li-            }
1148*ec63e07aSXin Li-        }
1149*ec63e07aSXin Li-    }
1150*ec63e07aSXin Li-    fails = 0;
1151*ec63e07aSXin Li-fin:
1152*ec63e07aSXin Li-    fclose(fdest);
1153*ec63e07aSXin Li-
1154*ec63e07aSXin Li-    return fails;
1155*ec63e07aSXin Li-}
1156*ec63e07aSXin Li-
1157*ec63e07aSXin Li-/* -->> -->> -->> -->>
1158*ec63e07aSXin Li-
1159*ec63e07aSXin Li-PGX IMAGE FORMAT
1160*ec63e07aSXin Li-
1161*ec63e07aSXin Li-<<-- <<-- <<-- <<-- */
1162*ec63e07aSXin Li-
1163*ec63e07aSXin Li-
1164*ec63e07aSXin Li-static unsigned char readuchar(FILE * f)
1165*ec63e07aSXin Li-{
1166*ec63e07aSXin Li-    unsigned char c1;
1167*ec63e07aSXin Li-    if (!fread(&c1, 1, 1, f)) {
1168*ec63e07aSXin Li-        fprintf(stderr,
1169*ec63e07aSXin Li-                "\nError: fread return a number of element different from the expected.\n");
1170*ec63e07aSXin Li-        return 0;
1171*ec63e07aSXin Li-    }
1172*ec63e07aSXin Li-    return c1;
1173*ec63e07aSXin Li-}
1174*ec63e07aSXin Li-
1175*ec63e07aSXin Li-static unsigned short readushort(FILE * f, int bigendian)
1176*ec63e07aSXin Li-{
1177*ec63e07aSXin Li-    unsigned char c1, c2;
1178*ec63e07aSXin Li-    if (!fread(&c1, 1, 1, f)) {
1179*ec63e07aSXin Li-        fprintf(stderr,
1180*ec63e07aSXin Li-                "\nError: fread return a number of element different from the expected.\n");
1181*ec63e07aSXin Li-        return 0;
1182*ec63e07aSXin Li-    }
1183*ec63e07aSXin Li-    if (!fread(&c2, 1, 1, f)) {
1184*ec63e07aSXin Li-        fprintf(stderr,
1185*ec63e07aSXin Li-                "\nError: fread return a number of element different from the expected.\n");
1186*ec63e07aSXin Li-        return 0;
1187*ec63e07aSXin Li-    }
1188*ec63e07aSXin Li-    if (bigendian) {
1189*ec63e07aSXin Li-        return (unsigned short)((c1 << 8) + c2);
1190*ec63e07aSXin Li-    } else {
1191*ec63e07aSXin Li-        return (unsigned short)((c2 << 8) + c1);
1192*ec63e07aSXin Li-    }
1193*ec63e07aSXin Li-}
1194*ec63e07aSXin Li-
1195*ec63e07aSXin Li-static unsigned int readuint(FILE * f, int bigendian)
1196*ec63e07aSXin Li-{
1197*ec63e07aSXin Li-    unsigned char c1, c2, c3, c4;
1198*ec63e07aSXin Li-    if (!fread(&c1, 1, 1, f)) {
1199*ec63e07aSXin Li-        fprintf(stderr,
1200*ec63e07aSXin Li-                "\nError: fread return a number of element different from the expected.\n");
1201*ec63e07aSXin Li-        return 0;
1202*ec63e07aSXin Li-    }
1203*ec63e07aSXin Li-    if (!fread(&c2, 1, 1, f)) {
1204*ec63e07aSXin Li-        fprintf(stderr,
1205*ec63e07aSXin Li-                "\nError: fread return a number of element different from the expected.\n");
1206*ec63e07aSXin Li-        return 0;
1207*ec63e07aSXin Li-    }
1208*ec63e07aSXin Li-    if (!fread(&c3, 1, 1, f)) {
1209*ec63e07aSXin Li-        fprintf(stderr,
1210*ec63e07aSXin Li-                "\nError: fread return a number of element different from the expected.\n");
1211*ec63e07aSXin Li-        return 0;
1212*ec63e07aSXin Li-    }
1213*ec63e07aSXin Li-    if (!fread(&c4, 1, 1, f)) {
1214*ec63e07aSXin Li-        fprintf(stderr,
1215*ec63e07aSXin Li-                "\nError: fread return a number of element different from the expected.\n");
1216*ec63e07aSXin Li-        return 0;
1217*ec63e07aSXin Li-    }
1218*ec63e07aSXin Li-    if (bigendian) {
1219*ec63e07aSXin Li-        return (unsigned int)(c1 << 24) + (unsigned int)(c2 << 16) + (unsigned int)(
1220*ec63e07aSXin Li-                   c3 << 8) + c4;
1221*ec63e07aSXin Li+    if (triple) {
1222*ec63e07aSXin Li+      adjustG = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
1223*ec63e07aSXin Li+      adjustB = (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
1224*ec63e07aSXin Li     } else {
1225*ec63e07aSXin Li-        return (unsigned int)(c4 << 24) + (unsigned int)(c3 << 16) + (unsigned int)(
1226*ec63e07aSXin Li-                   c2 << 8) + c1;
1227*ec63e07aSXin Li-    }
1228*ec63e07aSXin Li-}
1229*ec63e07aSXin Li-
1230*ec63e07aSXin Li-opj_image_t* pgxtoimage(const char *filename, opj_cparameters_t *parameters)
1231*ec63e07aSXin Li-{
1232*ec63e07aSXin Li-    FILE *f = NULL;
1233*ec63e07aSXin Li-    int w, h, prec;
1234*ec63e07aSXin Li-    int i, numcomps, max;
1235*ec63e07aSXin Li-    OPJ_COLOR_SPACE color_space;
1236*ec63e07aSXin Li-    opj_image_cmptparm_t cmptparm;  /* maximum of 1 component  */
1237*ec63e07aSXin Li-    opj_image_t * image = NULL;
1238*ec63e07aSXin Li-    int adjustS, ushift, dshift, force8;
1239*ec63e07aSXin Li-    OPJ_UINT64 expected_file_size;
1240*ec63e07aSXin Li-
1241*ec63e07aSXin Li-    char endian1, endian2, sign;
1242*ec63e07aSXin Li-    char signtmp[32];
1243*ec63e07aSXin Li-
1244*ec63e07aSXin Li-    char temp[32];
1245*ec63e07aSXin Li-    int bigendian;
1246*ec63e07aSXin Li-    opj_image_comp_t *comp = NULL;
1247*ec63e07aSXin Li-
1248*ec63e07aSXin Li-    numcomps = 1;
1249*ec63e07aSXin Li-    color_space = OPJ_CLRSPC_GRAY;
1250*ec63e07aSXin Li-
1251*ec63e07aSXin Li-    memset(&cmptparm, 0, sizeof(opj_image_cmptparm_t));
1252*ec63e07aSXin Li-
1253*ec63e07aSXin Li-    max = 0;
1254*ec63e07aSXin Li-
1255*ec63e07aSXin Li-    f = fopen(filename, "rb");
1256*ec63e07aSXin Li-    if (!f) {
1257*ec63e07aSXin Li-        fprintf(stderr, "Failed to open %s for reading !\n", filename);
1258*ec63e07aSXin Li-        return NULL;
1259*ec63e07aSXin Li+      adjustG = adjustB = 0;
1260*ec63e07aSXin Li     }
1261*ec63e07aSXin Li
1262*ec63e07aSXin Li-    fseek(f, 0, SEEK_SET);
1263*ec63e07aSXin Li-    if (fscanf(f, "PG%31[ \t]%c%c%31[ \t+-]%d%31[ \t]%d%31[ \t]%d", temp, &endian1,
1264*ec63e07aSXin Li-               &endian2, signtmp, &prec, temp, &w, temp, &h) != 9) {
1265*ec63e07aSXin Li-        fclose(f);
1266*ec63e07aSXin Li-        fprintf(stderr,
1267*ec63e07aSXin Li-                "ERROR: Failed to read the right number of element from the fscanf() function!\n");
1268*ec63e07aSXin Li-        return NULL;
1269*ec63e07aSXin Li-    }
1270*ec63e07aSXin Li-
1271*ec63e07aSXin Li-    i = 0;
1272*ec63e07aSXin Li-    sign = '+';
1273*ec63e07aSXin Li-    while (signtmp[i] != '\0') {
1274*ec63e07aSXin Li-        if (signtmp[i] == '-') {
1275*ec63e07aSXin Li-            sign = '-';
1276*ec63e07aSXin Li+    for (i = 0; i < wr * hr; ++i) {
1277*ec63e07aSXin Li+      if (two) {
1278*ec63e07aSXin Li+        v = *red + adjustR;
1279*ec63e07aSXin Li+        ++red;
1280*ec63e07aSXin Li+        if (v > 65535) {
1281*ec63e07aSXin Li+          v = 65535;
1282*ec63e07aSXin Li+        } else if (v < 0) {
1283*ec63e07aSXin Li+          v = 0;
1284*ec63e07aSXin Li         }
1285*ec63e07aSXin Li-        i++;
1286*ec63e07aSXin Li-    }
1287*ec63e07aSXin Li
1288*ec63e07aSXin Li-    fgetc(f);
1289*ec63e07aSXin Li-    if (endian1 == 'M' && endian2 == 'L') {
1290*ec63e07aSXin Li-        bigendian = 1;
1291*ec63e07aSXin Li-    } else if (endian2 == 'M' && endian1 == 'L') {
1292*ec63e07aSXin Li-        bigendian = 0;
1293*ec63e07aSXin Li-    } else {
1294*ec63e07aSXin Li-        fclose(f);
1295*ec63e07aSXin Li-        fprintf(stderr, "Bad pgx header, please check input file\n");
1296*ec63e07aSXin Li-        return NULL;
1297*ec63e07aSXin Li-    }
1298*ec63e07aSXin Li-
1299*ec63e07aSXin Li-    if (w < 1 || h < 1 || prec < 1 || prec > 31) {
1300*ec63e07aSXin Li-        fclose(f);
1301*ec63e07aSXin Li-        fprintf(stderr, "Bad pgx header, please check input file\n");
1302*ec63e07aSXin Li-        return NULL;
1303*ec63e07aSXin Li-    }
1304*ec63e07aSXin Li-
1305*ec63e07aSXin Li-    expected_file_size =
1306*ec63e07aSXin Li-        (OPJ_UINT64)w * (OPJ_UINT64)h * (prec > 16 ? 4 : prec > 8 ? 2 : 1);
1307*ec63e07aSXin Li-    if (expected_file_size > 10000000U) {
1308*ec63e07aSXin Li-        char ch;
1309*ec63e07aSXin Li-        long curpos = ftell(f);
1310*ec63e07aSXin Li-        if (expected_file_size > (OPJ_UINT64)INT_MAX) {
1311*ec63e07aSXin Li-            expected_file_size = (OPJ_UINT64)INT_MAX;
1312*ec63e07aSXin Li-        }
1313*ec63e07aSXin Li-        fseek(f, (long)expected_file_size - 1, SEEK_SET);
1314*ec63e07aSXin Li-        if (fread(&ch, 1, 1, f) != 1) {
1315*ec63e07aSXin Li-            fprintf(stderr, "File too short\n");
1316*ec63e07aSXin Li-            fclose(f);
1317*ec63e07aSXin Li-            return NULL;
1318*ec63e07aSXin Li-        }
1319*ec63e07aSXin Li-        fseek(f, curpos, SEEK_SET);
1320*ec63e07aSXin Li-    }
1321*ec63e07aSXin Li-
1322*ec63e07aSXin Li-    /* initialize image component */
1323*ec63e07aSXin Li-
1324*ec63e07aSXin Li-    cmptparm.x0 = (OPJ_UINT32)parameters->image_offset_x0;
1325*ec63e07aSXin Li-    cmptparm.y0 = (OPJ_UINT32)parameters->image_offset_y0;
1326*ec63e07aSXin Li-    cmptparm.w = !cmptparm.x0 ? (OPJ_UINT32)((w - 1) * parameters->subsampling_dx +
1327*ec63e07aSXin Li-                 1) : cmptparm.x0 + (OPJ_UINT32)(w - 1) * (OPJ_UINT32)parameters->subsampling_dx
1328*ec63e07aSXin Li-                 + 1;
1329*ec63e07aSXin Li-    cmptparm.h = !cmptparm.y0 ? (OPJ_UINT32)((h - 1) * parameters->subsampling_dy +
1330*ec63e07aSXin Li-                 1) : cmptparm.y0 + (OPJ_UINT32)(h - 1) * (OPJ_UINT32)parameters->subsampling_dy
1331*ec63e07aSXin Li-                 + 1;
1332*ec63e07aSXin Li-
1333*ec63e07aSXin Li-    if (sign == '-') {
1334*ec63e07aSXin Li-        cmptparm.sgnd = 1;
1335*ec63e07aSXin Li-    } else {
1336*ec63e07aSXin Li-        cmptparm.sgnd = 0;
1337*ec63e07aSXin Li-    }
1338*ec63e07aSXin Li-    if (prec < 8) {
1339*ec63e07aSXin Li-        force8 = 1;
1340*ec63e07aSXin Li-        ushift = 8 - prec;
1341*ec63e07aSXin Li-        dshift = prec - ushift;
1342*ec63e07aSXin Li-        if (cmptparm.sgnd) {
1343*ec63e07aSXin Li-            adjustS = (1 << (prec - 1));
1344*ec63e07aSXin Li-        } else {
1345*ec63e07aSXin Li-            adjustS = 0;
1346*ec63e07aSXin Li-        }
1347*ec63e07aSXin Li-        cmptparm.sgnd = 0;
1348*ec63e07aSXin Li-        prec = 8;
1349*ec63e07aSXin Li-    } else {
1350*ec63e07aSXin Li-        ushift = dshift = force8 = adjustS = 0;
1351*ec63e07aSXin Li-    }
1352*ec63e07aSXin Li-
1353*ec63e07aSXin Li-    cmptparm.prec = (OPJ_UINT32)prec;
1354*ec63e07aSXin Li-    cmptparm.bpp = (OPJ_UINT32)prec;
1355*ec63e07aSXin Li-    cmptparm.dx = (OPJ_UINT32)parameters->subsampling_dx;
1356*ec63e07aSXin Li-    cmptparm.dy = (OPJ_UINT32)parameters->subsampling_dy;
1357*ec63e07aSXin Li-
1358*ec63e07aSXin Li-    /* create the image */
1359*ec63e07aSXin Li-    image = opj_image_create((OPJ_UINT32)numcomps, &cmptparm, color_space);
1360*ec63e07aSXin Li-    if (!image) {
1361*ec63e07aSXin Li-        fclose(f);
1362*ec63e07aSXin Li-        return NULL;
1363*ec63e07aSXin Li-    }
1364*ec63e07aSXin Li-    /* set image offset and reference grid */
1365*ec63e07aSXin Li-    image->x0 = cmptparm.x0;
1366*ec63e07aSXin Li-    image->y0 = cmptparm.x0;
1367*ec63e07aSXin Li-    image->x1 = cmptparm.w;
1368*ec63e07aSXin Li-    image->y1 = cmptparm.h;
1369*ec63e07aSXin Li-
1370*ec63e07aSXin Li-    /* set image data */
1371*ec63e07aSXin Li-
1372*ec63e07aSXin Li-    comp = &image->comps[0];
1373*ec63e07aSXin Li-
1374*ec63e07aSXin Li-    for (i = 0; i < w * h; i++) {
1375*ec63e07aSXin Li-        int v;
1376*ec63e07aSXin Li-        if (force8) {
1377*ec63e07aSXin Li-            v = readuchar(f) + adjustS;
1378*ec63e07aSXin Li-            v = (v << ushift) + (v >> dshift);
1379*ec63e07aSXin Li-            comp->data[i] = (unsigned char)v;
1380*ec63e07aSXin Li-
1381*ec63e07aSXin Li-            if (v > max) {
1382*ec63e07aSXin Li-                max = v;
1383*ec63e07aSXin Li-            }
1384*ec63e07aSXin Li-
1385*ec63e07aSXin Li-            continue;
1386*ec63e07aSXin Li-        }
1387*ec63e07aSXin Li-        if (comp->prec == 8) {
1388*ec63e07aSXin Li-            if (!comp->sgnd) {
1389*ec63e07aSXin Li-                v = readuchar(f);
1390*ec63e07aSXin Li-            } else {
1391*ec63e07aSXin Li-                v = (char) readuchar(f);
1392*ec63e07aSXin Li-            }
1393*ec63e07aSXin Li-        } else if (comp->prec <= 16) {
1394*ec63e07aSXin Li-            if (!comp->sgnd) {
1395*ec63e07aSXin Li-                v = readushort(f, bigendian);
1396*ec63e07aSXin Li-            } else {
1397*ec63e07aSXin Li-                v = (short) readushort(f, bigendian);
1398*ec63e07aSXin Li-            }
1399*ec63e07aSXin Li-        } else {
1400*ec63e07aSXin Li-            if (!comp->sgnd) {
1401*ec63e07aSXin Li-                v = (int)readuint(f, bigendian);
1402*ec63e07aSXin Li-            } else {
1403*ec63e07aSXin Li-                v = (int) readuint(f, bigendian);
1404*ec63e07aSXin Li-            }
1405*ec63e07aSXin Li-        }
1406*ec63e07aSXin Li-        if (v > max) {
1407*ec63e07aSXin Li-            max = v;
1408*ec63e07aSXin Li-        }
1409*ec63e07aSXin Li-        comp->data[i] = v;
1410*ec63e07aSXin Li-    }
1411*ec63e07aSXin Li-    fclose(f);
1412*ec63e07aSXin Li-    comp->bpp = (OPJ_UINT32)int_floorlog2(max) + 1;
1413*ec63e07aSXin Li-
1414*ec63e07aSXin Li-    return image;
1415*ec63e07aSXin Li-}
1416*ec63e07aSXin Li-
1417*ec63e07aSXin Li-#define CLAMP(x,a,b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
1418*ec63e07aSXin Li-
1419*ec63e07aSXin Li-static INLINE int clamp(const int value, const int prec, const int sgnd)
1420*ec63e07aSXin Li-{
1421*ec63e07aSXin Li-    if (sgnd) {
1422*ec63e07aSXin Li-        if (prec <= 8) {
1423*ec63e07aSXin Li-            return CLAMP(value, -128, 127);
1424*ec63e07aSXin Li-        } else if (prec <= 16) {
1425*ec63e07aSXin Li-            return CLAMP(value, -32768, 32767);
1426*ec63e07aSXin Li-        } else {
1427*ec63e07aSXin Li-            return CLAMP(value, -2147483647 - 1, 2147483647);
1428*ec63e07aSXin Li-        }
1429*ec63e07aSXin Li-    } else {
1430*ec63e07aSXin Li-        if (prec <= 8) {
1431*ec63e07aSXin Li-            return CLAMP(value, 0, 255);
1432*ec63e07aSXin Li-        } else if (prec <= 16) {
1433*ec63e07aSXin Li-            return CLAMP(value, 0, 65535);
1434*ec63e07aSXin Li-        } else {
1435*ec63e07aSXin Li-            return value;    /*CLAMP(value,0,4294967295);*/
1436*ec63e07aSXin Li-        }
1437*ec63e07aSXin Li-    }
1438*ec63e07aSXin Li-}
1439*ec63e07aSXin Li-
1440*ec63e07aSXin Li-int imagetopgx(opj_image_t * image, const char *outfile)
1441*ec63e07aSXin Li-{
1442*ec63e07aSXin Li-    int w, h;
1443*ec63e07aSXin Li-    int i, j, fails = 1;
1444*ec63e07aSXin Li-    unsigned int compno;
1445*ec63e07aSXin Li-    FILE *fdest = NULL;
1446*ec63e07aSXin Li-
1447*ec63e07aSXin Li-    for (compno = 0; compno < image->numcomps; compno++) {
1448*ec63e07aSXin Li-        opj_image_comp_t *comp = &image->comps[compno];
1449*ec63e07aSXin Li-        char bname[256]; /* buffer for name */
1450*ec63e07aSXin Li-        char *name = bname; /* pointer */
1451*ec63e07aSXin Li-        int nbytes = 0;
1452*ec63e07aSXin Li-        size_t res;
1453*ec63e07aSXin Li-        const size_t olen = strlen(outfile);
1454*ec63e07aSXin Li-        const size_t dotpos = olen - 4;
1455*ec63e07aSXin Li-        const size_t total = dotpos + 1 + 1 + 4; /* '-' + '[1-3]' + '.pgx' */
1456*ec63e07aSXin Li-
1457*ec63e07aSXin Li-        if (outfile[dotpos] != '.') {
1458*ec63e07aSXin Li-            /* `pgx` was recognized but there is no dot at expected position */
1459*ec63e07aSXin Li-            fprintf(stderr, "ERROR -> Impossible happen.");
1460*ec63e07aSXin Li-            goto fin;
1461*ec63e07aSXin Li-        }
1462*ec63e07aSXin Li-        if (total > 256) {
1463*ec63e07aSXin Li-            name = (char*)malloc(total + 1);
1464*ec63e07aSXin Li-            if (name == NULL) {
1465*ec63e07aSXin Li-                fprintf(stderr, "imagetopgx: memory out\n");
1466*ec63e07aSXin Li-                goto fin;
1467*ec63e07aSXin Li-            }
1468*ec63e07aSXin Li-        }
1469*ec63e07aSXin Li-        strncpy(name, outfile, dotpos);
1470*ec63e07aSXin Li-        sprintf(name + dotpos, "_%u.pgx", compno);
1471*ec63e07aSXin Li-        fdest = fopen(name, "wb");
1472*ec63e07aSXin Li-        /* don't need name anymore */
1473*ec63e07aSXin Li-
1474*ec63e07aSXin Li-        if (!fdest) {
1475*ec63e07aSXin Li-
1476*ec63e07aSXin Li-            fprintf(stderr, "ERROR -> failed to open %s for writing\n", name);
1477*ec63e07aSXin Li-            if (total > 256) {
1478*ec63e07aSXin Li-                free(name);
1479*ec63e07aSXin Li-            }
1480*ec63e07aSXin Li-            goto fin;
1481*ec63e07aSXin Li-        }
1482*ec63e07aSXin Li-
1483*ec63e07aSXin Li-        w = (int)image->comps[compno].w;
1484*ec63e07aSXin Li-        h = (int)image->comps[compno].h;
1485*ec63e07aSXin Li-
1486*ec63e07aSXin Li-        fprintf(fdest, "PG ML %c %d %d %d\n", comp->sgnd ? '-' : '+', comp->prec,
1487*ec63e07aSXin Li-                w, h);
1488*ec63e07aSXin Li-
1489*ec63e07aSXin Li-        if (comp->prec <= 8) {
1490*ec63e07aSXin Li-            nbytes = 1;
1491*ec63e07aSXin Li-        } else if (comp->prec <= 16) {
1492*ec63e07aSXin Li-            nbytes = 2;
1493*ec63e07aSXin Li-        } else {
1494*ec63e07aSXin Li-            nbytes = 4;
1495*ec63e07aSXin Li-        }
1496*ec63e07aSXin Li-
1497*ec63e07aSXin Li-        if (nbytes == 1) {
1498*ec63e07aSXin Li-            unsigned char* line_buffer = malloc((size_t)w);
1499*ec63e07aSXin Li-            if (line_buffer == NULL) {
1500*ec63e07aSXin Li-                fprintf(stderr, "Out of memory");
1501*ec63e07aSXin Li-                if (total > 256) {
1502*ec63e07aSXin Li-                    free(name);
1503*ec63e07aSXin Li-                }
1504*ec63e07aSXin Li-                goto fin;
1505*ec63e07aSXin Li-            }
1506*ec63e07aSXin Li-            for (j = 0; j < h; j++) {
1507*ec63e07aSXin Li-                if (comp->prec == 8 && comp->sgnd == 0) {
1508*ec63e07aSXin Li-                    for (i = 0; i < w; i++) {
1509*ec63e07aSXin Li-                        line_buffer[i] = (unsigned char)CLAMP(image->comps[compno].data[j * w + i], 0,
1510*ec63e07aSXin Li-                                                              255);
1511*ec63e07aSXin Li-                    }
1512*ec63e07aSXin Li-                } else {
1513*ec63e07aSXin Li-                    for (i = 0; i < w; i++) {
1514*ec63e07aSXin Li-                        line_buffer[i] = (unsigned char)
1515*ec63e07aSXin Li-                                         clamp(image->comps[compno].data[j * w + i],
1516*ec63e07aSXin Li-                                               (int)comp->prec, (int)comp->sgnd);
1517*ec63e07aSXin Li-                    }
1518*ec63e07aSXin Li-                }
1519*ec63e07aSXin Li-                res = fwrite(line_buffer, 1, (size_t)w, fdest);
1520*ec63e07aSXin Li-                if (res != (size_t)w) {
1521*ec63e07aSXin Li-                    fprintf(stderr, "failed to write %d bytes for %s\n", w, name);
1522*ec63e07aSXin Li-                    if (total > 256) {
1523*ec63e07aSXin Li-                        free(name);
1524*ec63e07aSXin Li-                    }
1525*ec63e07aSXin Li-                    free(line_buffer);
1526*ec63e07aSXin Li-                    goto fin;
1527*ec63e07aSXin Li-                }
1528*ec63e07aSXin Li-            }
1529*ec63e07aSXin Li-            free(line_buffer);
1530*ec63e07aSXin Li-        } else {
1531*ec63e07aSXin Li-
1532*ec63e07aSXin Li-            for (i = 0; i < w * h; i++) {
1533*ec63e07aSXin Li-                /* FIXME: clamp func is being called within a loop */
1534*ec63e07aSXin Li-                const int val = clamp(image->comps[compno].data[i],
1535*ec63e07aSXin Li-                                      (int)comp->prec, (int)comp->sgnd);
1536*ec63e07aSXin Li-
1537*ec63e07aSXin Li-                for (j = nbytes - 1; j >= 0; j--) {
1538*ec63e07aSXin Li-                    int v = (int)(val >> (j * 8));
1539*ec63e07aSXin Li-                    unsigned char byte = (unsigned char)v;
1540*ec63e07aSXin Li-                    res = fwrite(&byte, 1, 1, fdest);
1541*ec63e07aSXin Li-
1542*ec63e07aSXin Li-                    if (res < 1) {
1543*ec63e07aSXin Li-                        fprintf(stderr, "failed to write 1 byte for %s\n", name);
1544*ec63e07aSXin Li-                        if (total > 256) {
1545*ec63e07aSXin Li-                            free(name);
1546*ec63e07aSXin Li-                        }
1547*ec63e07aSXin Li-                        goto fin;
1548*ec63e07aSXin Li-                    }
1549*ec63e07aSXin Li-                }
1550*ec63e07aSXin Li-            }
1551*ec63e07aSXin Li-        }
1552*ec63e07aSXin Li-
1553*ec63e07aSXin Li-        if (total > 256) {
1554*ec63e07aSXin Li-            free(name);
1555*ec63e07aSXin Li-        }
1556*ec63e07aSXin Li-        fclose(fdest);
1557*ec63e07aSXin Li-        fdest = NULL;
1558*ec63e07aSXin Li-    }
1559*ec63e07aSXin Li-    fails = 0;
1560*ec63e07aSXin Li-fin:
1561*ec63e07aSXin Li-    if (fdest) {
1562*ec63e07aSXin Li-        fclose(fdest);
1563*ec63e07aSXin Li-    }
1564*ec63e07aSXin Li-
1565*ec63e07aSXin Li-    return fails;
1566*ec63e07aSXin Li-}
1567*ec63e07aSXin Li-
1568*ec63e07aSXin Li-/* -->> -->> -->> -->>
1569*ec63e07aSXin Li-
1570*ec63e07aSXin Li-PNM IMAGE FORMAT
1571*ec63e07aSXin Li-
1572*ec63e07aSXin Li-<<-- <<-- <<-- <<-- */
1573*ec63e07aSXin Li-
1574*ec63e07aSXin Li-struct pnm_header {
1575*ec63e07aSXin Li-    int width, height, maxval, depth, format;
1576*ec63e07aSXin Li-    char rgb, rgba, gray, graya, bw;
1577*ec63e07aSXin Li-    char ok;
1578*ec63e07aSXin Li-};
1579*ec63e07aSXin Li-
1580*ec63e07aSXin Li-static char *skip_white(char *s)
1581*ec63e07aSXin Li-{
1582*ec63e07aSXin Li-    if (s != NULL) {
1583*ec63e07aSXin Li-        while (*s) {
1584*ec63e07aSXin Li-            if (*s == '\n' || *s == '\r') {
1585*ec63e07aSXin Li-                return NULL;
1586*ec63e07aSXin Li-            }
1587*ec63e07aSXin Li-            if (isspace(*s)) {
1588*ec63e07aSXin Li-                ++s;
1589*ec63e07aSXin Li-                continue;
1590*ec63e07aSXin Li-            }
1591*ec63e07aSXin Li-            return s;
1592*ec63e07aSXin Li-        }
1593*ec63e07aSXin Li-    }
1594*ec63e07aSXin Li-    return NULL;
1595*ec63e07aSXin Li-}
1596*ec63e07aSXin Li-
1597*ec63e07aSXin Li-static char *skip_int(char *start, int *out_n)
1598*ec63e07aSXin Li-{
1599*ec63e07aSXin Li-    char *s;
1600*ec63e07aSXin Li-    char c;
1601*ec63e07aSXin Li-
1602*ec63e07aSXin Li-    *out_n = 0;
1603*ec63e07aSXin Li-
1604*ec63e07aSXin Li-    s = skip_white(start);
1605*ec63e07aSXin Li-    if (s == NULL) {
1606*ec63e07aSXin Li-        return NULL;
1607*ec63e07aSXin Li-    }
1608*ec63e07aSXin Li-    start = s;
1609*ec63e07aSXin Li-
1610*ec63e07aSXin Li-    while (*s) {
1611*ec63e07aSXin Li-        if (!isdigit(*s)) {
1612*ec63e07aSXin Li-            break;
1613*ec63e07aSXin Li-        }
1614*ec63e07aSXin Li-        ++s;
1615*ec63e07aSXin Li-    }
1616*ec63e07aSXin Li-    c = *s;
1617*ec63e07aSXin Li-    *s = 0;
1618*ec63e07aSXin Li-    *out_n = atoi(start);
1619*ec63e07aSXin Li-    *s = c;
1620*ec63e07aSXin Li-    return s;
1621*ec63e07aSXin Li-}
1622*ec63e07aSXin Li-
1623*ec63e07aSXin Li-static char *skip_idf(char *start, char out_idf[256])
1624*ec63e07aSXin Li-{
1625*ec63e07aSXin Li-    char *s;
1626*ec63e07aSXin Li-    char c;
1627*ec63e07aSXin Li-
1628*ec63e07aSXin Li-    s = skip_white(start);
1629*ec63e07aSXin Li-    if (s == NULL) {
1630*ec63e07aSXin Li-        return NULL;
1631*ec63e07aSXin Li-    }
1632*ec63e07aSXin Li-    start = s;
1633*ec63e07aSXin Li-
1634*ec63e07aSXin Li-    while (*s) {
1635*ec63e07aSXin Li-        if (isalpha(*s) || *s == '_') {
1636*ec63e07aSXin Li-            ++s;
1637*ec63e07aSXin Li-            continue;
1638*ec63e07aSXin Li-        }
1639*ec63e07aSXin Li-        break;
1640*ec63e07aSXin Li-    }
1641*ec63e07aSXin Li-    c = *s;
1642*ec63e07aSXin Li-    *s = 0;
1643*ec63e07aSXin Li-    strncpy(out_idf, start, 255);
1644*ec63e07aSXin Li-    *s = c;
1645*ec63e07aSXin Li-    return s;
1646*ec63e07aSXin Li-}
1647*ec63e07aSXin Li-
1648*ec63e07aSXin Li-static void read_pnm_header(FILE *reader, struct pnm_header *ph)
1649*ec63e07aSXin Li-{
1650*ec63e07aSXin Li-    int format, end, ttype;
1651*ec63e07aSXin Li-    char idf[256], type[256];
1652*ec63e07aSXin Li-    char line[256];
1653*ec63e07aSXin Li-
1654*ec63e07aSXin Li-    if (fgets(line, 250, reader) == NULL) {
1655*ec63e07aSXin Li-        fprintf(stderr, "\nWARNING: fgets return a NULL value");
1656*ec63e07aSXin Li-        return;
1657*ec63e07aSXin Li-    }
1658*ec63e07aSXin Li-
1659*ec63e07aSXin Li-    if (line[0] != 'P') {
1660*ec63e07aSXin Li-        fprintf(stderr, "read_pnm_header:PNM:magic P missing\n");
1661*ec63e07aSXin Li-        return;
1662*ec63e07aSXin Li-    }
1663*ec63e07aSXin Li-    format = atoi(line + 1);
1664*ec63e07aSXin Li-    if (format < 1 || format > 7) {
1665*ec63e07aSXin Li-        fprintf(stderr, "read_pnm_header:magic format %d invalid\n", format);
1666*ec63e07aSXin Li-        return;
1667*ec63e07aSXin Li-    }
1668*ec63e07aSXin Li-    ph->format = format;
1669*ec63e07aSXin Li-    ttype = end = 0;
1670*ec63e07aSXin Li-
1671*ec63e07aSXin Li-    while (fgets(line, 250, reader)) {
1672*ec63e07aSXin Li-        char *s;
1673*ec63e07aSXin Li-        int allow_null = 0;
1674*ec63e07aSXin Li-
1675*ec63e07aSXin Li-        if (*line == '#') {
1676*ec63e07aSXin Li-            continue;
1677*ec63e07aSXin Li-        }
1678*ec63e07aSXin Li-
1679*ec63e07aSXin Li-        s = line;
1680*ec63e07aSXin Li-
1681*ec63e07aSXin Li-        if (format == 7) {
1682*ec63e07aSXin Li-            s = skip_idf(s, idf);
1683*ec63e07aSXin Li-
1684*ec63e07aSXin Li-            if (s == NULL || *s == 0) {
1685*ec63e07aSXin Li-                return;
1686*ec63e07aSXin Li-            }
1687*ec63e07aSXin Li-
1688*ec63e07aSXin Li-            if (strcmp(idf, "ENDHDR") == 0) {
1689*ec63e07aSXin Li-                end = 1;
1690*ec63e07aSXin Li-                break;
1691*ec63e07aSXin Li-            }
1692*ec63e07aSXin Li-            if (strcmp(idf, "WIDTH") == 0) {
1693*ec63e07aSXin Li-                s = skip_int(s, &ph->width);
1694*ec63e07aSXin Li-                if (s == NULL || *s == 0) {
1695*ec63e07aSXin Li-                    return;
1696*ec63e07aSXin Li-                }
1697*ec63e07aSXin Li-
1698*ec63e07aSXin Li-                continue;
1699*ec63e07aSXin Li-            }
1700*ec63e07aSXin Li-            if (strcmp(idf, "HEIGHT") == 0) {
1701*ec63e07aSXin Li-                s = skip_int(s, &ph->height);
1702*ec63e07aSXin Li-                if (s == NULL || *s == 0) {
1703*ec63e07aSXin Li-                    return;
1704*ec63e07aSXin Li-                }
1705*ec63e07aSXin Li-
1706*ec63e07aSXin Li-                continue;
1707*ec63e07aSXin Li-            }
1708*ec63e07aSXin Li-            if (strcmp(idf, "DEPTH") == 0) {
1709*ec63e07aSXin Li-                s = skip_int(s, &ph->depth);
1710*ec63e07aSXin Li-                if (s == NULL || *s == 0) {
1711*ec63e07aSXin Li-                    return;
1712*ec63e07aSXin Li-                }
1713*ec63e07aSXin Li-
1714*ec63e07aSXin Li-                continue;
1715*ec63e07aSXin Li-            }
1716*ec63e07aSXin Li-            if (strcmp(idf, "MAXVAL") == 0) {
1717*ec63e07aSXin Li-                s = skip_int(s, &ph->maxval);
1718*ec63e07aSXin Li-                if (s == NULL || *s == 0) {
1719*ec63e07aSXin Li-                    return;
1720*ec63e07aSXin Li-                }
1721*ec63e07aSXin Li-
1722*ec63e07aSXin Li-                continue;
1723*ec63e07aSXin Li-            }
1724*ec63e07aSXin Li-            if (strcmp(idf, "TUPLTYPE") == 0) {
1725*ec63e07aSXin Li-                s = skip_idf(s, type);
1726*ec63e07aSXin Li-                if (s == NULL || *s == 0) {
1727*ec63e07aSXin Li-                    return;
1728*ec63e07aSXin Li-                }
1729*ec63e07aSXin Li-
1730*ec63e07aSXin Li-                if (strcmp(type, "BLACKANDWHITE") == 0) {
1731*ec63e07aSXin Li-                    ph->bw = 1;
1732*ec63e07aSXin Li-                    ttype = 1;
1733*ec63e07aSXin Li-                    continue;
1734*ec63e07aSXin Li-                }
1735*ec63e07aSXin Li-                if (strcmp(type, "GRAYSCALE") == 0) {
1736*ec63e07aSXin Li-                    ph->gray = 1;
1737*ec63e07aSXin Li-                    ttype = 1;
1738*ec63e07aSXin Li-                    continue;
1739*ec63e07aSXin Li-                }
1740*ec63e07aSXin Li-                if (strcmp(type, "GRAYSCALE_ALPHA") == 0) {
1741*ec63e07aSXin Li-                    ph->graya = 1;
1742*ec63e07aSXin Li-                    ttype = 1;
1743*ec63e07aSXin Li-                    continue;
1744*ec63e07aSXin Li-                }
1745*ec63e07aSXin Li-                if (strcmp(type, "RGB") == 0) {
1746*ec63e07aSXin Li-                    ph->rgb = 1;
1747*ec63e07aSXin Li-                    ttype = 1;
1748*ec63e07aSXin Li-                    continue;
1749*ec63e07aSXin Li-                }
1750*ec63e07aSXin Li-                if (strcmp(type, "RGB_ALPHA") == 0) {
1751*ec63e07aSXin Li-                    ph->rgba = 1;
1752*ec63e07aSXin Li-                    ttype = 1;
1753*ec63e07aSXin Li-                    continue;
1754*ec63e07aSXin Li-                }
1755*ec63e07aSXin Li-                fprintf(stderr, "read_pnm_header:unknown P7 TUPLTYPE %s\n", type);
1756*ec63e07aSXin Li-                return;
1757*ec63e07aSXin Li-            }
1758*ec63e07aSXin Li-            fprintf(stderr, "read_pnm_header:unknown P7 idf %s\n", idf);
1759*ec63e07aSXin Li-            return;
1760*ec63e07aSXin Li-        } /* if(format == 7) */
1761*ec63e07aSXin Li-
1762*ec63e07aSXin Li-        /* Here format is in range [1,6] */
1763*ec63e07aSXin Li-        if (ph->width == 0) {
1764*ec63e07aSXin Li-            s = skip_int(s, &ph->width);
1765*ec63e07aSXin Li-            if ((s == NULL) || (*s == 0) || (ph->width < 1)) {
1766*ec63e07aSXin Li-                return;
1767*ec63e07aSXin Li-            }
1768*ec63e07aSXin Li-            allow_null = 1;
1769*ec63e07aSXin Li-        }
1770*ec63e07aSXin Li-        if (ph->height == 0) {
1771*ec63e07aSXin Li-            s = skip_int(s, &ph->height);
1772*ec63e07aSXin Li-            if ((s == NULL) && allow_null) {
1773*ec63e07aSXin Li-                continue;
1774*ec63e07aSXin Li-            }
1775*ec63e07aSXin Li-            if ((s == NULL) || (*s == 0) || (ph->height < 1)) {
1776*ec63e07aSXin Li-                return;
1777*ec63e07aSXin Li-            }
1778*ec63e07aSXin Li-            if (format == 1 || format == 4) {
1779*ec63e07aSXin Li-                break;
1780*ec63e07aSXin Li-            }
1781*ec63e07aSXin Li-            allow_null = 1;
1782*ec63e07aSXin Li-        }
1783*ec63e07aSXin Li-        /* here, format is in P2, P3, P5, P6 */
1784*ec63e07aSXin Li-        s = skip_int(s, &ph->maxval);
1785*ec63e07aSXin Li-        if ((s == NULL) && allow_null) {
1786*ec63e07aSXin Li-            continue;
1787*ec63e07aSXin Li-        }
1788*ec63e07aSXin Li-        if ((s == NULL) || (*s == 0)) {
1789*ec63e07aSXin Li-            return;
1790*ec63e07aSXin Li-        }
1791*ec63e07aSXin Li-        break;
1792*ec63e07aSXin Li-    }/* while(fgets( ) */
1793*ec63e07aSXin Li-    if (format == 2 || format == 3 || format > 4) {
1794*ec63e07aSXin Li-        if (ph->maxval < 1 || ph->maxval > 65535) {
1795*ec63e07aSXin Li-            return;
1796*ec63e07aSXin Li-        }
1797*ec63e07aSXin Li-    }
1798*ec63e07aSXin Li-    if (ph->width < 1 || ph->height < 1) {
1799*ec63e07aSXin Li-        return;
1800*ec63e07aSXin Li-    }
1801*ec63e07aSXin Li-
1802*ec63e07aSXin Li-    if (format == 7) {
1803*ec63e07aSXin Li-        if (!end) {
1804*ec63e07aSXin Li-            fprintf(stderr, "read_pnm_header:P7 without ENDHDR\n");
1805*ec63e07aSXin Li-            return;
1806*ec63e07aSXin Li-        }
1807*ec63e07aSXin Li-        if (ph->depth < 1 || ph->depth > 4) {
1808*ec63e07aSXin Li-            return;
1809*ec63e07aSXin Li-        }
1810*ec63e07aSXin Li-
1811*ec63e07aSXin Li-        if (ttype) {
1812*ec63e07aSXin Li-            ph->ok = 1;
1813*ec63e07aSXin Li-        }
1814*ec63e07aSXin Li-    } else {
1815*ec63e07aSXin Li-        ph->ok = 1;
1816*ec63e07aSXin Li-        if (format == 1 || format == 4) {
1817*ec63e07aSXin Li-            ph->maxval = 255;
1818*ec63e07aSXin Li-        }
1819*ec63e07aSXin Li-    }
1820*ec63e07aSXin Li-}
1821*ec63e07aSXin Li-
1822*ec63e07aSXin Li-static int has_prec(int val)
1823*ec63e07aSXin Li-{
1824*ec63e07aSXin Li-    if (val < 2) {
1825*ec63e07aSXin Li-        return 1;
1826*ec63e07aSXin Li-    }
1827*ec63e07aSXin Li-    if (val < 4) {
1828*ec63e07aSXin Li-        return 2;
1829*ec63e07aSXin Li-    }
1830*ec63e07aSXin Li-    if (val < 8) {
1831*ec63e07aSXin Li-        return 3;
1832*ec63e07aSXin Li-    }
1833*ec63e07aSXin Li-    if (val < 16) {
1834*ec63e07aSXin Li-        return 4;
1835*ec63e07aSXin Li-    }
1836*ec63e07aSXin Li-    if (val < 32) {
1837*ec63e07aSXin Li-        return 5;
1838*ec63e07aSXin Li-    }
1839*ec63e07aSXin Li-    if (val < 64) {
1840*ec63e07aSXin Li-        return 6;
1841*ec63e07aSXin Li-    }
1842*ec63e07aSXin Li-    if (val < 128) {
1843*ec63e07aSXin Li-        return 7;
1844*ec63e07aSXin Li-    }
1845*ec63e07aSXin Li-    if (val < 256) {
1846*ec63e07aSXin Li-        return 8;
1847*ec63e07aSXin Li-    }
1848*ec63e07aSXin Li-    if (val < 512) {
1849*ec63e07aSXin Li-        return 9;
1850*ec63e07aSXin Li-    }
1851*ec63e07aSXin Li-    if (val < 1024) {
1852*ec63e07aSXin Li-        return 10;
1853*ec63e07aSXin Li-    }
1854*ec63e07aSXin Li-    if (val < 2048) {
1855*ec63e07aSXin Li-        return 11;
1856*ec63e07aSXin Li-    }
1857*ec63e07aSXin Li-    if (val < 4096) {
1858*ec63e07aSXin Li-        return 12;
1859*ec63e07aSXin Li-    }
1860*ec63e07aSXin Li-    if (val < 8192) {
1861*ec63e07aSXin Li-        return 13;
1862*ec63e07aSXin Li-    }
1863*ec63e07aSXin Li-    if (val < 16384) {
1864*ec63e07aSXin Li-        return 14;
1865*ec63e07aSXin Li-    }
1866*ec63e07aSXin Li-    if (val < 32768) {
1867*ec63e07aSXin Li-        return 15;
1868*ec63e07aSXin Li-    }
1869*ec63e07aSXin Li-    return 16;
1870*ec63e07aSXin Li-}
1871*ec63e07aSXin Li-
1872*ec63e07aSXin Li-opj_image_t* pnmtoimage(const char *filename, opj_cparameters_t *parameters)
1873*ec63e07aSXin Li-{
1874*ec63e07aSXin Li-    int subsampling_dx = parameters->subsampling_dx;
1875*ec63e07aSXin Li-    int subsampling_dy = parameters->subsampling_dy;
1876*ec63e07aSXin Li-
1877*ec63e07aSXin Li-    FILE *fp = NULL;
1878*ec63e07aSXin Li-    int i, compno, numcomps, w, h, prec, format;
1879*ec63e07aSXin Li-    OPJ_COLOR_SPACE color_space;
1880*ec63e07aSXin Li-    opj_image_cmptparm_t cmptparm[4]; /* RGBA: max. 4 components */
1881*ec63e07aSXin Li-    opj_image_t * image = NULL;
1882*ec63e07aSXin Li-    struct pnm_header header_info;
1883*ec63e07aSXin Li-
1884*ec63e07aSXin Li-    if ((fp = fopen(filename, "rb")) == NULL) {
1885*ec63e07aSXin Li-        fprintf(stderr, "pnmtoimage:Failed to open %s for reading!\n", filename);
1886*ec63e07aSXin Li-        return NULL;
1887*ec63e07aSXin Li-    }
1888*ec63e07aSXin Li-    memset(&header_info, 0, sizeof(struct pnm_header));
1889*ec63e07aSXin Li-
1890*ec63e07aSXin Li-    read_pnm_header(fp, &header_info);
1891*ec63e07aSXin Li-
1892*ec63e07aSXin Li-    if (!header_info.ok) {
1893*ec63e07aSXin Li-        fclose(fp);
1894*ec63e07aSXin Li-        return NULL;
1895*ec63e07aSXin Li-    }
1896*ec63e07aSXin Li-
1897*ec63e07aSXin Li-    if (header_info.width == 0
1898*ec63e07aSXin Li-            || header_info.height == 0
1899*ec63e07aSXin Li-            || (header_info.format == 7 && header_info.depth == 0)) {
1900*ec63e07aSXin Li-        fclose(fp);
1901*ec63e07aSXin Li-        return NULL;
1902*ec63e07aSXin Li-    }
1903*ec63e07aSXin Li-
1904*ec63e07aSXin Li-    /* This limitation could be removed by making sure to use size_t below */
1905*ec63e07aSXin Li-    if (header_info.height != 0 &&
1906*ec63e07aSXin Li-            header_info.width > INT_MAX / header_info.height) {
1907*ec63e07aSXin Li-        fprintf(stderr, "pnmtoimage:Image %dx%d too big!\n",
1908*ec63e07aSXin Li-                header_info.width, header_info.height);
1909*ec63e07aSXin Li-        fclose(fp);
1910*ec63e07aSXin Li-        return NULL;
1911*ec63e07aSXin Li-    }
1912*ec63e07aSXin Li-
1913*ec63e07aSXin Li-    format = header_info.format;
1914*ec63e07aSXin Li-
1915*ec63e07aSXin Li-    switch (format) {
1916*ec63e07aSXin Li-    case 1: /* ascii bitmap */
1917*ec63e07aSXin Li-    case 4: /* raw bitmap */
1918*ec63e07aSXin Li-        numcomps = 1;
1919*ec63e07aSXin Li-        break;
1920*ec63e07aSXin Li-
1921*ec63e07aSXin Li-    case 2: /* ascii greymap */
1922*ec63e07aSXin Li-    case 5: /* raw greymap */
1923*ec63e07aSXin Li-        numcomps = 1;
1924*ec63e07aSXin Li-        break;
1925*ec63e07aSXin Li-
1926*ec63e07aSXin Li-    case 3: /* ascii pixmap */
1927*ec63e07aSXin Li-    case 6: /* raw pixmap */
1928*ec63e07aSXin Li-        numcomps = 3;
1929*ec63e07aSXin Li-        break;
1930*ec63e07aSXin Li-
1931*ec63e07aSXin Li-    case 7: /* arbitrary map */
1932*ec63e07aSXin Li-        numcomps = header_info.depth;
1933*ec63e07aSXin Li-        break;
1934*ec63e07aSXin Li-
1935*ec63e07aSXin Li-    default:
1936*ec63e07aSXin Li-        fclose(fp);
1937*ec63e07aSXin Li-        return NULL;
1938*ec63e07aSXin Li-    }
1939*ec63e07aSXin Li-    if (numcomps < 3) {
1940*ec63e07aSXin Li-        color_space = OPJ_CLRSPC_GRAY;    /* GRAY, GRAYA */
1941*ec63e07aSXin Li-    } else {
1942*ec63e07aSXin Li-        color_space = OPJ_CLRSPC_SRGB;    /* RGB, RGBA */
1943*ec63e07aSXin Li-    }
1944*ec63e07aSXin Li-
1945*ec63e07aSXin Li-    prec = has_prec(header_info.maxval);
1946*ec63e07aSXin Li-
1947*ec63e07aSXin Li-    if (prec < 8) {
1948*ec63e07aSXin Li-        prec = 8;
1949*ec63e07aSXin Li-    }
1950*ec63e07aSXin Li-
1951*ec63e07aSXin Li-    w = header_info.width;
1952*ec63e07aSXin Li-    h = header_info.height;
1953*ec63e07aSXin Li-    subsampling_dx = parameters->subsampling_dx;
1954*ec63e07aSXin Li-    subsampling_dy = parameters->subsampling_dy;
1955*ec63e07aSXin Li-
1956*ec63e07aSXin Li-    memset(&cmptparm[0], 0, (size_t)numcomps * sizeof(opj_image_cmptparm_t));
1957*ec63e07aSXin Li-
1958*ec63e07aSXin Li-    for (i = 0; i < numcomps; i++) {
1959*ec63e07aSXin Li-        cmptparm[i].prec = (OPJ_UINT32)prec;
1960*ec63e07aSXin Li-        cmptparm[i].bpp = (OPJ_UINT32)prec;
1961*ec63e07aSXin Li-        cmptparm[i].sgnd = 0;
1962*ec63e07aSXin Li-        cmptparm[i].dx = (OPJ_UINT32)subsampling_dx;
1963*ec63e07aSXin Li-        cmptparm[i].dy = (OPJ_UINT32)subsampling_dy;
1964*ec63e07aSXin Li-        cmptparm[i].w = (OPJ_UINT32)w;
1965*ec63e07aSXin Li-        cmptparm[i].h = (OPJ_UINT32)h;
1966*ec63e07aSXin Li-    }
1967*ec63e07aSXin Li-    image = opj_image_create((OPJ_UINT32)numcomps, &cmptparm[0], color_space);
1968*ec63e07aSXin Li-
1969*ec63e07aSXin Li-    if (!image) {
1970*ec63e07aSXin Li-        fclose(fp);
1971*ec63e07aSXin Li-        return NULL;
1972*ec63e07aSXin Li-    }
1973*ec63e07aSXin Li-
1974*ec63e07aSXin Li-    /* set image offset and reference grid */
1975*ec63e07aSXin Li-    image->x0 = (OPJ_UINT32)parameters->image_offset_x0;
1976*ec63e07aSXin Li-    image->y0 = (OPJ_UINT32)parameters->image_offset_y0;
1977*ec63e07aSXin Li-    image->x1 = (OPJ_UINT32)(parameters->image_offset_x0 + (w - 1) * subsampling_dx
1978*ec63e07aSXin Li-                             + 1);
1979*ec63e07aSXin Li-    image->y1 = (OPJ_UINT32)(parameters->image_offset_y0 + (h - 1) * subsampling_dy
1980*ec63e07aSXin Li-                             + 1);
1981*ec63e07aSXin Li-
1982*ec63e07aSXin Li-    if ((format == 2) || (format == 3)) { /* ascii pixmap */
1983*ec63e07aSXin Li-        unsigned int index;
1984*ec63e07aSXin Li-
1985*ec63e07aSXin Li-        for (i = 0; i < w * h; i++) {
1986*ec63e07aSXin Li-            for (compno = 0; compno < numcomps; compno++) {
1987*ec63e07aSXin Li-                index = 0;
1988*ec63e07aSXin Li-                if (fscanf(fp, "%u", &index) != 1) {
1989*ec63e07aSXin Li-                    fprintf(stderr, "Missing data. Quitting.\n");
1990*ec63e07aSXin Li-                    opj_image_destroy(image);
1991*ec63e07aSXin Li-                    fclose(fp);
1992*ec63e07aSXin Li-                    return NULL;
1993*ec63e07aSXin Li-                }
1994*ec63e07aSXin Li-
1995*ec63e07aSXin Li-                image->comps[compno].data[i] = (OPJ_INT32)(index * 255) / header_info.maxval;
1996*ec63e07aSXin Li-            }
1997*ec63e07aSXin Li-        }
1998*ec63e07aSXin Li-    } else if ((format == 5)
1999*ec63e07aSXin Li-               || (format == 6)
2000*ec63e07aSXin Li-               || ((format == 7)
2001*ec63e07aSXin Li-                   && (header_info.gray || header_info.graya
2002*ec63e07aSXin Li-                       || header_info.rgb || header_info.rgba))) { /* binary pixmap */
2003*ec63e07aSXin Li-        unsigned char c0, c1, one;
2004*ec63e07aSXin Li-
2005*ec63e07aSXin Li-        one = (prec < 9);
2006*ec63e07aSXin Li-
2007*ec63e07aSXin Li-        for (i = 0; i < w * h; i++) {
2008*ec63e07aSXin Li-            for (compno = 0; compno < numcomps; compno++) {
2009*ec63e07aSXin Li-                if (!fread(&c0, 1, 1, fp)) {
2010*ec63e07aSXin Li-                    fprintf(stderr, "Missing data. Quitting.\n");
2011*ec63e07aSXin Li-                    opj_image_destroy(image);
2012*ec63e07aSXin Li-                    fclose(fp);
2013*ec63e07aSXin Li-                    return NULL;
2014*ec63e07aSXin Li-                }
2015*ec63e07aSXin Li-                if (one) {
2016*ec63e07aSXin Li-                    image->comps[compno].data[i] = c0;
2017*ec63e07aSXin Li-                } else {
2018*ec63e07aSXin Li-                    if (!fread(&c1, 1, 1, fp)) {
2019*ec63e07aSXin Li-                        fprintf(stderr, "Missing data. Quitting.\n");
2020*ec63e07aSXin Li-                        opj_image_destroy(image);
2021*ec63e07aSXin Li-                        fclose(fp);
2022*ec63e07aSXin Li-                        return NULL;
2023*ec63e07aSXin Li-                    }
2024*ec63e07aSXin Li-                    /* netpbm: */
2025*ec63e07aSXin Li-                    image->comps[compno].data[i] = ((c0 << 8) | c1);
2026*ec63e07aSXin Li-                }
2027*ec63e07aSXin Li-            }
2028*ec63e07aSXin Li-        }
2029*ec63e07aSXin Li-    } else if (format == 1) { /* ascii bitmap */
2030*ec63e07aSXin Li-        for (i = 0; i < w * h; i++) {
2031*ec63e07aSXin Li-            unsigned int index;
2032*ec63e07aSXin Li-
2033*ec63e07aSXin Li-            if (fscanf(fp, "%u", &index) != 1) {
2034*ec63e07aSXin Li-                fprintf(stderr, "Missing data. Quitting.\n");
2035*ec63e07aSXin Li-                opj_image_destroy(image);
2036*ec63e07aSXin Li-                fclose(fp);
2037*ec63e07aSXin Li-                return NULL;
2038*ec63e07aSXin Li-            }
2039*ec63e07aSXin Li-
2040*ec63e07aSXin Li-            image->comps[0].data[i] = (index ? 0 : 255);
2041*ec63e07aSXin Li-        }
2042*ec63e07aSXin Li-    } else if (format == 4) {
2043*ec63e07aSXin Li-        int x, y, bit;
2044*ec63e07aSXin Li-        int uc;
2045*ec63e07aSXin Li-
2046*ec63e07aSXin Li-        i = 0;
2047*ec63e07aSXin Li-        for (y = 0; y < h; ++y) {
2048*ec63e07aSXin Li-            bit = -1;
2049*ec63e07aSXin Li-            uc = 0;
2050*ec63e07aSXin Li-
2051*ec63e07aSXin Li-            for (x = 0; x < w; ++x) {
2052*ec63e07aSXin Li-                if (bit == -1) {
2053*ec63e07aSXin Li-                    bit = 7;
2054*ec63e07aSXin Li-                    uc = getc(fp);
2055*ec63e07aSXin Li-                    if (uc == EOF) {
2056*ec63e07aSXin Li-                        fprintf(stderr, "Missing data. Quitting.\n");
2057*ec63e07aSXin Li-                        opj_image_destroy(image);
2058*ec63e07aSXin Li-                        fclose(fp);
2059*ec63e07aSXin Li-                        return NULL;
2060*ec63e07aSXin Li-                    }
2061*ec63e07aSXin Li-                }
2062*ec63e07aSXin Li-                image->comps[0].data[i] = ((((unsigned char)uc >> bit) & 1) ? 0 : 255);
2063*ec63e07aSXin Li-                --bit;
2064*ec63e07aSXin Li-                ++i;
2065*ec63e07aSXin Li-            }
2066*ec63e07aSXin Li-        }
2067*ec63e07aSXin Li-    } else if ((format == 7 && header_info.bw)) { /*MONO*/
2068*ec63e07aSXin Li-        unsigned char uc;
2069*ec63e07aSXin Li-
2070*ec63e07aSXin Li-        for (i = 0; i < w * h; ++i) {
2071*ec63e07aSXin Li-            if (!fread(&uc, 1, 1, fp)) {
2072*ec63e07aSXin Li-                fprintf(stderr, "Missing data. Quitting.\n");
2073*ec63e07aSXin Li-                opj_image_destroy(image);
2074*ec63e07aSXin Li-                fclose(fp);
2075*ec63e07aSXin Li-                return NULL;
2076*ec63e07aSXin Li-            }
2077*ec63e07aSXin Li-            image->comps[0].data[i] = (uc & 1) ? 0 : 255;
2078*ec63e07aSXin Li-        }
2079*ec63e07aSXin Li-    }
2080*ec63e07aSXin Li-    fclose(fp);
2081*ec63e07aSXin Li-
2082*ec63e07aSXin Li-    return image;
2083*ec63e07aSXin Li-}/* pnmtoimage() */
2084*ec63e07aSXin Li-
2085*ec63e07aSXin Li-static int are_comps_similar(opj_image_t * image)
2086*ec63e07aSXin Li-{
2087*ec63e07aSXin Li-    unsigned int i;
2088*ec63e07aSXin Li-    for (i = 1; i < image->numcomps; i++) {
2089*ec63e07aSXin Li-        if (image->comps[0].dx != image->comps[i].dx ||
2090*ec63e07aSXin Li-                image->comps[0].dy != image->comps[i].dy ||
2091*ec63e07aSXin Li-                (i <= 2 &&
2092*ec63e07aSXin Li-                 (image->comps[0].prec != image->comps[i].prec ||
2093*ec63e07aSXin Li-                  image->comps[0].sgnd != image->comps[i].sgnd))) {
2094*ec63e07aSXin Li-            return OPJ_FALSE;
2095*ec63e07aSXin Li-        }
2096*ec63e07aSXin Li-    }
2097*ec63e07aSXin Li-    return OPJ_TRUE;
2098*ec63e07aSXin Li-}
2099*ec63e07aSXin Li-
2100*ec63e07aSXin Li-
2101*ec63e07aSXin Li-int imagetopnm(opj_image_t * image, const char *outfile, int force_split)
2102*ec63e07aSXin Li-{
2103*ec63e07aSXin Li-    int *red, *green, *blue, *alpha;
2104*ec63e07aSXin Li-    int wr, hr, max;
2105*ec63e07aSXin Li-    int i;
2106*ec63e07aSXin Li-    unsigned int compno, ncomp;
2107*ec63e07aSXin Li-    int adjustR, adjustG, adjustB, adjustA;
2108*ec63e07aSXin Li-    int fails, two, want_gray, has_alpha, triple;
2109*ec63e07aSXin Li-    int prec, v;
2110*ec63e07aSXin Li-    FILE *fdest = NULL;
2111*ec63e07aSXin Li-    const char *tmp = outfile;
2112*ec63e07aSXin Li-    char *destname;
2113*ec63e07aSXin Li-
2114*ec63e07aSXin Li-    alpha = NULL;
2115*ec63e07aSXin Li-
2116*ec63e07aSXin Li-    if ((prec = (int)image->comps[0].prec) > 16) {
2117*ec63e07aSXin Li-        fprintf(stderr, "%s:%d:imagetopnm\n\tprecision %d is larger than 16"
2118*ec63e07aSXin Li-                "\n\t: refused.\n", __FILE__, __LINE__, prec);
2119*ec63e07aSXin Li-        return 1;
2120*ec63e07aSXin Li-    }
2121*ec63e07aSXin Li-    two = has_alpha = 0;
2122*ec63e07aSXin Li-    fails = 1;
2123*ec63e07aSXin Li-    ncomp = image->numcomps;
2124*ec63e07aSXin Li-
2125*ec63e07aSXin Li-    while (*tmp) {
2126*ec63e07aSXin Li-        ++tmp;
2127*ec63e07aSXin Li-    }
2128*ec63e07aSXin Li-    tmp -= 2;
2129*ec63e07aSXin Li-    want_gray = (*tmp == 'g' || *tmp == 'G');
2130*ec63e07aSXin Li-    ncomp = image->numcomps;
2131*ec63e07aSXin Li-
2132*ec63e07aSXin Li-    if (want_gray) {
2133*ec63e07aSXin Li-        ncomp = 1;
2134*ec63e07aSXin Li-    }
2135*ec63e07aSXin Li-
2136*ec63e07aSXin Li-    if ((force_split == 0) && ncomp >= 2 &&
2137*ec63e07aSXin Li-            are_comps_similar(image)) {
2138*ec63e07aSXin Li-        fdest = fopen(outfile, "wb");
2139*ec63e07aSXin Li-
2140*ec63e07aSXin Li-        if (!fdest) {
2141*ec63e07aSXin Li-            fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
2142*ec63e07aSXin Li-            return fails;
2143*ec63e07aSXin Li-        }
2144*ec63e07aSXin Li-        two = (prec > 8);
2145*ec63e07aSXin Li-        triple = (ncomp > 2);
2146*ec63e07aSXin Li-        wr = (int)image->comps[0].w;
2147*ec63e07aSXin Li-        hr = (int)image->comps[0].h;
2148*ec63e07aSXin Li-        max = (1 << prec) - 1;
2149*ec63e07aSXin Li-        has_alpha = (ncomp == 4 || ncomp == 2);
2150*ec63e07aSXin Li-
2151*ec63e07aSXin Li-        red = image->comps[0].data;
2152*ec63e07aSXin Li-        if (red == NULL) {
2153*ec63e07aSXin Li-            fprintf(stderr,
2154*ec63e07aSXin Li-                    "imagetopnm: planes[%d] == NULL.\n", 0);
2155*ec63e07aSXin Li-            fprintf(stderr, "\tAborting\n");
2156*ec63e07aSXin Li-            fclose(fdest);
2157*ec63e07aSXin Li-            return fails;
2158*ec63e07aSXin Li-        }
2159*ec63e07aSXin Li-
2160*ec63e07aSXin Li-        if (triple) {
2161*ec63e07aSXin Li-            green = image->comps[1].data;
2162*ec63e07aSXin Li-            blue = image->comps[2].data;
2163*ec63e07aSXin Li-            for (i = 1; i <= 2; i++) {
2164*ec63e07aSXin Li-                if (image->comps[i].data == NULL) {
2165*ec63e07aSXin Li-                    fprintf(stderr,
2166*ec63e07aSXin Li-                            "imagetopnm: planes[%d] == NULL.\n", i);
2167*ec63e07aSXin Li-                    fprintf(stderr, "\tAborting\n");
2168*ec63e07aSXin Li-                    fclose(fdest);
2169*ec63e07aSXin Li-                    return fails;
2170*ec63e07aSXin Li-                }
2171*ec63e07aSXin Li-            }
2172*ec63e07aSXin Li-        } else {
2173*ec63e07aSXin Li-            green = blue = NULL;
2174*ec63e07aSXin Li-        }
2175*ec63e07aSXin Li-
2176*ec63e07aSXin Li-        if (has_alpha) {
2177*ec63e07aSXin Li-            const char *tt = (triple ? "RGB_ALPHA" : "GRAYSCALE_ALPHA");
2178*ec63e07aSXin Li-
2179*ec63e07aSXin Li-            fprintf(fdest, "P7\n# OpenJPEG-%s\nWIDTH %d\nHEIGHT %d\nDEPTH %u\n"
2180*ec63e07aSXin Li-                    "MAXVAL %d\nTUPLTYPE %s\nENDHDR\n", opj_version(),
2181*ec63e07aSXin Li-                    wr, hr, ncomp, max, tt);
2182*ec63e07aSXin Li-            alpha = image->comps[ncomp - 1].data;
2183*ec63e07aSXin Li-            adjustA = (image->comps[ncomp - 1].sgnd ?
2184*ec63e07aSXin Li-                       1 << (image->comps[ncomp - 1].prec - 1) : 0);
2185*ec63e07aSXin Li-        } else {
2186*ec63e07aSXin Li-            fprintf(fdest, "P6\n# OpenJPEG-%s\n%d %d\n%d\n",
2187*ec63e07aSXin Li-                    opj_version(), wr, hr, max);
2188*ec63e07aSXin Li-            adjustA = 0;
2189*ec63e07aSXin Li-        }
2190*ec63e07aSXin Li-        adjustR = (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
2191*ec63e07aSXin Li+        /* netpbm: */
2192*ec63e07aSXin Li+        fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2193*ec63e07aSXin Li
2194*ec63e07aSXin Li         if (triple) {
2195*ec63e07aSXin Li-            adjustG = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
2196*ec63e07aSXin Li-            adjustB = (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
2197*ec63e07aSXin Li-        } else {
2198*ec63e07aSXin Li-            adjustG = adjustB = 0;
2199*ec63e07aSXin Li-        }
2200*ec63e07aSXin Li-
2201*ec63e07aSXin Li-        for (i = 0; i < wr * hr; ++i) {
2202*ec63e07aSXin Li-            if (two) {
2203*ec63e07aSXin Li-                v = *red + adjustR;
2204*ec63e07aSXin Li-                ++red;
2205*ec63e07aSXin Li-                if (v > 65535) {
2206*ec63e07aSXin Li-                    v = 65535;
2207*ec63e07aSXin Li-                } else if (v < 0) {
2208*ec63e07aSXin Li-                    v = 0;
2209*ec63e07aSXin Li-                }
2210*ec63e07aSXin Li-
2211*ec63e07aSXin Li-                /* netpbm: */
2212*ec63e07aSXin Li-                fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2213*ec63e07aSXin Li-
2214*ec63e07aSXin Li-                if (triple) {
2215*ec63e07aSXin Li-                    v = *green + adjustG;
2216*ec63e07aSXin Li-                    ++green;
2217*ec63e07aSXin Li-                    if (v > 65535) {
2218*ec63e07aSXin Li-                        v = 65535;
2219*ec63e07aSXin Li-                    } else if (v < 0) {
2220*ec63e07aSXin Li-                        v = 0;
2221*ec63e07aSXin Li-                    }
2222*ec63e07aSXin Li-
2223*ec63e07aSXin Li-                    /* netpbm: */
2224*ec63e07aSXin Li-                    fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2225*ec63e07aSXin Li-
2226*ec63e07aSXin Li-                    v =  *blue + adjustB;
2227*ec63e07aSXin Li-                    ++blue;
2228*ec63e07aSXin Li-                    if (v > 65535) {
2229*ec63e07aSXin Li-                        v = 65535;
2230*ec63e07aSXin Li-                    } else if (v < 0) {
2231*ec63e07aSXin Li-                        v = 0;
2232*ec63e07aSXin Li-                    }
2233*ec63e07aSXin Li-
2234*ec63e07aSXin Li-                    /* netpbm: */
2235*ec63e07aSXin Li-                    fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2236*ec63e07aSXin Li-
2237*ec63e07aSXin Li-                }/* if(triple) */
2238*ec63e07aSXin Li-
2239*ec63e07aSXin Li-                if (has_alpha) {
2240*ec63e07aSXin Li-                    v = *alpha + adjustA;
2241*ec63e07aSXin Li-                    ++alpha;
2242*ec63e07aSXin Li-                    if (v > 65535) {
2243*ec63e07aSXin Li-                        v = 65535;
2244*ec63e07aSXin Li-                    } else if (v < 0) {
2245*ec63e07aSXin Li-                        v = 0;
2246*ec63e07aSXin Li-                    }
2247*ec63e07aSXin Li-
2248*ec63e07aSXin Li-                    /* netpbm: */
2249*ec63e07aSXin Li-                    fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2250*ec63e07aSXin Li-                }
2251*ec63e07aSXin Li-                continue;
2252*ec63e07aSXin Li-
2253*ec63e07aSXin Li-            }   /* if(two) */
2254*ec63e07aSXin Li-
2255*ec63e07aSXin Li-            /* prec <= 8: */
2256*ec63e07aSXin Li-            v = *red++;
2257*ec63e07aSXin Li-            if (v > 255) {
2258*ec63e07aSXin Li-                v = 255;
2259*ec63e07aSXin Li-            } else if (v < 0) {
2260*ec63e07aSXin Li-                v = 0;
2261*ec63e07aSXin Li-            }
2262*ec63e07aSXin Li-
2263*ec63e07aSXin Li-            fprintf(fdest, "%c", (unsigned char)v);
2264*ec63e07aSXin Li-            if (triple) {
2265*ec63e07aSXin Li-                v = *green++;
2266*ec63e07aSXin Li-                if (v > 255) {
2267*ec63e07aSXin Li-                    v = 255;
2268*ec63e07aSXin Li-                } else if (v < 0) {
2269*ec63e07aSXin Li-                    v = 0;
2270*ec63e07aSXin Li-                }
2271*ec63e07aSXin Li-
2272*ec63e07aSXin Li-                fprintf(fdest, "%c", (unsigned char)v);
2273*ec63e07aSXin Li-                v = *blue++;
2274*ec63e07aSXin Li-                if (v > 255) {
2275*ec63e07aSXin Li-                    v = 255;
2276*ec63e07aSXin Li-                } else if (v < 0) {
2277*ec63e07aSXin Li-                    v = 0;
2278*ec63e07aSXin Li-                }
2279*ec63e07aSXin Li-
2280*ec63e07aSXin Li-                fprintf(fdest, "%c", (unsigned char)v);
2281*ec63e07aSXin Li-            }
2282*ec63e07aSXin Li-            if (has_alpha) {
2283*ec63e07aSXin Li-                v = *alpha++;
2284*ec63e07aSXin Li-                if (v > 255) {
2285*ec63e07aSXin Li-                    v = 255;
2286*ec63e07aSXin Li-                } else if (v < 0) {
2287*ec63e07aSXin Li-                    v = 0;
2288*ec63e07aSXin Li-                }
2289*ec63e07aSXin Li-
2290*ec63e07aSXin Li-                fprintf(fdest, "%c", (unsigned char)v);
2291*ec63e07aSXin Li-            }
2292*ec63e07aSXin Li-        }   /* for(i */
2293*ec63e07aSXin Li+          v = *green + adjustG;
2294*ec63e07aSXin Li+          ++green;
2295*ec63e07aSXin Li+          if (v > 65535) {
2296*ec63e07aSXin Li+            v = 65535;
2297*ec63e07aSXin Li+          } else if (v < 0) {
2298*ec63e07aSXin Li+            v = 0;
2299*ec63e07aSXin Li+          }
2300*ec63e07aSXin Li+
2301*ec63e07aSXin Li+          /* netpbm: */
2302*ec63e07aSXin Li+          fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2303*ec63e07aSXin Li+
2304*ec63e07aSXin Li+          v = *blue + adjustB;
2305*ec63e07aSXin Li+          ++blue;
2306*ec63e07aSXin Li+          if (v > 65535) {
2307*ec63e07aSXin Li+            v = 65535;
2308*ec63e07aSXin Li+          } else if (v < 0) {
2309*ec63e07aSXin Li+            v = 0;
2310*ec63e07aSXin Li+          }
2311*ec63e07aSXin Li
2312*ec63e07aSXin Li-        fclose(fdest);
2313*ec63e07aSXin Li-        return 0;
2314*ec63e07aSXin Li-    }
2315*ec63e07aSXin Li+          /* netpbm: */
2316*ec63e07aSXin Li+          fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2317*ec63e07aSXin Li
2318*ec63e07aSXin Li-    /* YUV or MONO: */
2319*ec63e07aSXin Li+        } /* if(triple) */
2320*ec63e07aSXin Li
2321*ec63e07aSXin Li-    if (image->numcomps > ncomp) {
2322*ec63e07aSXin Li-        fprintf(stderr, "WARNING -> [PGM file] Only the first component\n");
2323*ec63e07aSXin Li-        fprintf(stderr, "           is written to the file\n");
2324*ec63e07aSXin Li-    }
2325*ec63e07aSXin Li-    destname = (char*)malloc(strlen(outfile) + 8);
2326*ec63e07aSXin Li-    if (destname == NULL) {
2327*ec63e07aSXin Li-        fprintf(stderr, "imagetopnm: memory out\n");
2328*ec63e07aSXin Li-        return 1;
2329*ec63e07aSXin Li-    }
2330*ec63e07aSXin Li-    for (compno = 0; compno < ncomp; compno++) {
2331*ec63e07aSXin Li-        if (ncomp > 1) {
2332*ec63e07aSXin Li-            /*sprintf(destname, "%d.%s", compno, outfile);*/
2333*ec63e07aSXin Li-            const size_t olen = strlen(outfile);
2334*ec63e07aSXin Li-            const size_t dotpos = olen - 4;
2335*ec63e07aSXin Li-
2336*ec63e07aSXin Li-            strncpy(destname, outfile, dotpos);
2337*ec63e07aSXin Li-            sprintf(destname + dotpos, "_%u.pgm", compno);
2338*ec63e07aSXin Li-        } else {
2339*ec63e07aSXin Li-            sprintf(destname, "%s", outfile);
2340*ec63e07aSXin Li-        }
2341*ec63e07aSXin Li-
2342*ec63e07aSXin Li-        fdest = fopen(destname, "wb");
2343*ec63e07aSXin Li-        if (!fdest) {
2344*ec63e07aSXin Li-            fprintf(stderr, "ERROR -> failed to open %s for writing\n", destname);
2345*ec63e07aSXin Li-            free(destname);
2346*ec63e07aSXin Li-            return 1;
2347*ec63e07aSXin Li-        }
2348*ec63e07aSXin Li-        wr = (int)image->comps[compno].w;
2349*ec63e07aSXin Li-        hr = (int)image->comps[compno].h;
2350*ec63e07aSXin Li-        prec = (int)image->comps[compno].prec;
2351*ec63e07aSXin Li-        max = (1 << prec) - 1;
2352*ec63e07aSXin Li-
2353*ec63e07aSXin Li-        fprintf(fdest, "P5\n#OpenJPEG-%s\n%d %d\n%d\n",
2354*ec63e07aSXin Li-                opj_version(), wr, hr, max);
2355*ec63e07aSXin Li-
2356*ec63e07aSXin Li-        red = image->comps[compno].data;
2357*ec63e07aSXin Li-        if (!red) {
2358*ec63e07aSXin Li-            fclose(fdest);
2359*ec63e07aSXin Li-            continue;
2360*ec63e07aSXin Li-        }
2361*ec63e07aSXin Li-
2362*ec63e07aSXin Li-        adjustR =
2363*ec63e07aSXin Li-            (image->comps[compno].sgnd ? 1 << (image->comps[compno].prec - 1) : 0);
2364*ec63e07aSXin Li-
2365*ec63e07aSXin Li-        if (prec > 8) {
2366*ec63e07aSXin Li-            for (i = 0; i < wr * hr; i++) {
2367*ec63e07aSXin Li-                v = *red + adjustR;
2368*ec63e07aSXin Li-                ++red;
2369*ec63e07aSXin Li-                if (v > 65535) {
2370*ec63e07aSXin Li-                    v = 65535;
2371*ec63e07aSXin Li-                } else if (v < 0) {
2372*ec63e07aSXin Li-                    v = 0;
2373*ec63e07aSXin Li-                }
2374*ec63e07aSXin Li-
2375*ec63e07aSXin Li-                /* netpbm: */
2376*ec63e07aSXin Li-                fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2377*ec63e07aSXin Li-
2378*ec63e07aSXin Li-                if (has_alpha) {
2379*ec63e07aSXin Li-                    v = *alpha++;
2380*ec63e07aSXin Li-                    if (v > 65535) {
2381*ec63e07aSXin Li-                        v = 65535;
2382*ec63e07aSXin Li-                    } else if (v < 0) {
2383*ec63e07aSXin Li-                        v = 0;
2384*ec63e07aSXin Li-                    }
2385*ec63e07aSXin Li-
2386*ec63e07aSXin Li-                    /* netpbm: */
2387*ec63e07aSXin Li-                    fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2388*ec63e07aSXin Li-                }
2389*ec63e07aSXin Li-            }/* for(i */
2390*ec63e07aSXin Li-        } else { /* prec <= 8 */
2391*ec63e07aSXin Li-            for (i = 0; i < wr * hr; ++i) {
2392*ec63e07aSXin Li-                v = *red + adjustR;
2393*ec63e07aSXin Li-                ++red;
2394*ec63e07aSXin Li-                if (v > 255) {
2395*ec63e07aSXin Li-                    v = 255;
2396*ec63e07aSXin Li-                } else if (v < 0) {
2397*ec63e07aSXin Li-                    v = 0;
2398*ec63e07aSXin Li-                }
2399*ec63e07aSXin Li-
2400*ec63e07aSXin Li-                fprintf(fdest, "%c", (unsigned char)v);
2401*ec63e07aSXin Li-            }
2402*ec63e07aSXin Li-        }
2403*ec63e07aSXin Li-        fclose(fdest);
2404*ec63e07aSXin Li-    } /* for (compno */
2405*ec63e07aSXin Li-    free(destname);
2406*ec63e07aSXin Li+        if (has_alpha) {
2407*ec63e07aSXin Li+          v = *alpha + adjustA;
2408*ec63e07aSXin Li+          ++alpha;
2409*ec63e07aSXin Li+          if (v > 65535) {
2410*ec63e07aSXin Li+            v = 65535;
2411*ec63e07aSXin Li+          } else if (v < 0) {
2412*ec63e07aSXin Li+            v = 0;
2413*ec63e07aSXin Li+          }
2414*ec63e07aSXin Li+
2415*ec63e07aSXin Li+          /* netpbm: */
2416*ec63e07aSXin Li+          fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2417*ec63e07aSXin Li+        }
2418*ec63e07aSXin Li+        continue;
2419*ec63e07aSXin Li+
2420*ec63e07aSXin Li+      } /* if(two) */
2421*ec63e07aSXin Li+
2422*ec63e07aSXin Li+      /* prec <= 8: */
2423*ec63e07aSXin Li+      v = *red++;
2424*ec63e07aSXin Li+      if (v > 255) {
2425*ec63e07aSXin Li+        v = 255;
2426*ec63e07aSXin Li+      } else if (v < 0) {
2427*ec63e07aSXin Li+        v = 0;
2428*ec63e07aSXin Li+      }
2429*ec63e07aSXin Li+
2430*ec63e07aSXin Li+      fprintf(fdest, "%c", (unsigned char)v);
2431*ec63e07aSXin Li+      if (triple) {
2432*ec63e07aSXin Li+        v = *green++;
2433*ec63e07aSXin Li+        if (v > 255) {
2434*ec63e07aSXin Li+          v = 255;
2435*ec63e07aSXin Li+        } else if (v < 0) {
2436*ec63e07aSXin Li+          v = 0;
2437*ec63e07aSXin Li+        }
2438*ec63e07aSXin Li+
2439*ec63e07aSXin Li+        fprintf(fdest, "%c", (unsigned char)v);
2440*ec63e07aSXin Li+        v = *blue++;
2441*ec63e07aSXin Li+        if (v > 255) {
2442*ec63e07aSXin Li+          v = 255;
2443*ec63e07aSXin Li+        } else if (v < 0) {
2444*ec63e07aSXin Li+          v = 0;
2445*ec63e07aSXin Li+        }
2446*ec63e07aSXin Li+
2447*ec63e07aSXin Li+        fprintf(fdest, "%c", (unsigned char)v);
2448*ec63e07aSXin Li+      }
2449*ec63e07aSXin Li+      if (has_alpha) {
2450*ec63e07aSXin Li+        v = *alpha++;
2451*ec63e07aSXin Li+        if (v > 255) {
2452*ec63e07aSXin Li+          v = 255;
2453*ec63e07aSXin Li+        } else if (v < 0) {
2454*ec63e07aSXin Li+          v = 0;
2455*ec63e07aSXin Li+        }
2456*ec63e07aSXin Li+
2457*ec63e07aSXin Li+        fprintf(fdest, "%c", (unsigned char)v);
2458*ec63e07aSXin Li+      }
2459*ec63e07aSXin Li+    } /* for(i */
2460*ec63e07aSXin Li
2461*ec63e07aSXin Li+    fclose(fdest);
2462*ec63e07aSXin Li     return 0;
2463*ec63e07aSXin Li-}/* imagetopnm() */
2464*ec63e07aSXin Li-
2465*ec63e07aSXin Li-/* -->> -->> -->> -->>
2466*ec63e07aSXin Li+  }
2467*ec63e07aSXin Li
2468*ec63e07aSXin Li-    RAW IMAGE FORMAT
2469*ec63e07aSXin Li+  /* YUV or MONO: */
2470*ec63e07aSXin Li
2471*ec63e07aSXin Li- <<-- <<-- <<-- <<-- */
2472*ec63e07aSXin Li-static opj_image_t* rawtoimage_common(const char *filename,
2473*ec63e07aSXin Li-                                      opj_cparameters_t *parameters, raw_cparameters_t *raw_cp, OPJ_BOOL big_endian)
2474*ec63e07aSXin Li-{
2475*ec63e07aSXin Li-    int subsampling_dx = parameters->subsampling_dx;
2476*ec63e07aSXin Li-    int subsampling_dy = parameters->subsampling_dy;
2477*ec63e07aSXin Li-
2478*ec63e07aSXin Li-    FILE *f = NULL;
2479*ec63e07aSXin Li-    int i, compno, numcomps, w, h;
2480*ec63e07aSXin Li-    OPJ_COLOR_SPACE color_space;
2481*ec63e07aSXin Li-    opj_image_cmptparm_t *cmptparm;
2482*ec63e07aSXin Li-    opj_image_t * image = NULL;
2483*ec63e07aSXin Li-    unsigned short ch;
2484*ec63e07aSXin Li-
2485*ec63e07aSXin Li-    if ((!(raw_cp->rawWidth & raw_cp->rawHeight & raw_cp->rawComp &
2486*ec63e07aSXin Li-            raw_cp->rawBitDepth)) == 0) {
2487*ec63e07aSXin Li-        fprintf(stderr, "\nError: invalid raw image parameters\n");
2488*ec63e07aSXin Li-        fprintf(stderr, "Please use the Format option -F:\n");
2489*ec63e07aSXin Li-        fprintf(stderr,
2490*ec63e07aSXin Li-                "-F <width>,<height>,<ncomp>,<bitdepth>,{s,u}@<dx1>x<dy1>:...:<dxn>x<dyn>\n");
2491*ec63e07aSXin Li-        fprintf(stderr,
2492*ec63e07aSXin Li-                "If subsampling is omitted, 1x1 is assumed for all components\n");
2493*ec63e07aSXin Li-        fprintf(stderr,
2494*ec63e07aSXin Li-                "Example: -i image.raw -o image.j2k -F 512,512,3,8,u@1x1:2x2:2x2\n");
2495*ec63e07aSXin Li-        fprintf(stderr, "         for raw 512x512 image with 4:2:0 subsampling\n");
2496*ec63e07aSXin Li-        fprintf(stderr, "Aborting.\n");
2497*ec63e07aSXin Li-        return NULL;
2498*ec63e07aSXin Li-    }
2499*ec63e07aSXin Li-
2500*ec63e07aSXin Li-    f = fopen(filename, "rb");
2501*ec63e07aSXin Li-    if (!f) {
2502*ec63e07aSXin Li-        fprintf(stderr, "Failed to open %s for reading !!\n", filename);
2503*ec63e07aSXin Li-        fprintf(stderr, "Aborting\n");
2504*ec63e07aSXin Li-        return NULL;
2505*ec63e07aSXin Li-    }
2506*ec63e07aSXin Li-    numcomps = raw_cp->rawComp;
2507*ec63e07aSXin Li+  if (image->numcomps > ncomp) {
2508*ec63e07aSXin Li+    fprintf(stderr, "WARNING -> [PGM file] Only the first component\n");
2509*ec63e07aSXin Li+    fprintf(stderr, "           is written to the file\n");
2510*ec63e07aSXin Li+  }
2511*ec63e07aSXin Li+  destname = (char *)malloc(strlen(outfile) + 8);
2512*ec63e07aSXin Li+  if (destname == NULL) {
2513*ec63e07aSXin Li+    fprintf(stderr, "imagetopnm: memory out\n");
2514*ec63e07aSXin Li+    return 1;
2515*ec63e07aSXin Li+  }
2516*ec63e07aSXin Li+  for (compno = 0; compno < ncomp; compno++) {
2517*ec63e07aSXin Li+    if (ncomp > 1) {
2518*ec63e07aSXin Li+      /*sprintf(destname, "%d.%s", compno, outfile);*/
2519*ec63e07aSXin Li+      const size_t olen = strlen(outfile);
2520*ec63e07aSXin Li+      const size_t dotpos = olen - 4;
2521*ec63e07aSXin Li
2522*ec63e07aSXin Li-    /* FIXME ADE at this point, tcp_mct has not been properly set in calling function */
2523*ec63e07aSXin Li-    if (numcomps == 1) {
2524*ec63e07aSXin Li-        color_space = OPJ_CLRSPC_GRAY;
2525*ec63e07aSXin Li-    } else if ((numcomps >= 3) && (parameters->tcp_mct == 0)) {
2526*ec63e07aSXin Li-        color_space = OPJ_CLRSPC_SYCC;
2527*ec63e07aSXin Li-    } else if ((numcomps >= 3) && (parameters->tcp_mct != 2)) {
2528*ec63e07aSXin Li-        color_space = OPJ_CLRSPC_SRGB;
2529*ec63e07aSXin Li+      strncpy(destname, outfile, dotpos);
2530*ec63e07aSXin Li+      sprintf(destname + dotpos, "_%u.pgm", compno);
2531*ec63e07aSXin Li     } else {
2532*ec63e07aSXin Li-        color_space = OPJ_CLRSPC_UNKNOWN;
2533*ec63e07aSXin Li-    }
2534*ec63e07aSXin Li-    w = raw_cp->rawWidth;
2535*ec63e07aSXin Li-    h = raw_cp->rawHeight;
2536*ec63e07aSXin Li-    cmptparm = (opj_image_cmptparm_t*) calloc((OPJ_UINT32)numcomps,
2537*ec63e07aSXin Li-               sizeof(opj_image_cmptparm_t));
2538*ec63e07aSXin Li-    if (!cmptparm) {
2539*ec63e07aSXin Li-        fprintf(stderr, "Failed to allocate image components parameters !!\n");
2540*ec63e07aSXin Li-        fprintf(stderr, "Aborting\n");
2541*ec63e07aSXin Li-        fclose(f);
2542*ec63e07aSXin Li-        return NULL;
2543*ec63e07aSXin Li-    }
2544*ec63e07aSXin Li-    /* initialize image components */
2545*ec63e07aSXin Li-    for (i = 0; i < numcomps; i++) {
2546*ec63e07aSXin Li-        cmptparm[i].prec = (OPJ_UINT32)raw_cp->rawBitDepth;
2547*ec63e07aSXin Li-        cmptparm[i].bpp = (OPJ_UINT32)raw_cp->rawBitDepth;
2548*ec63e07aSXin Li-        cmptparm[i].sgnd = (OPJ_UINT32)raw_cp->rawSigned;
2549*ec63e07aSXin Li-        cmptparm[i].dx = (OPJ_UINT32)(subsampling_dx * raw_cp->rawComps[i].dx);
2550*ec63e07aSXin Li-        cmptparm[i].dy = (OPJ_UINT32)(subsampling_dy * raw_cp->rawComps[i].dy);
2551*ec63e07aSXin Li-        cmptparm[i].w = (OPJ_UINT32)w;
2552*ec63e07aSXin Li-        cmptparm[i].h = (OPJ_UINT32)h;
2553*ec63e07aSXin Li-    }
2554*ec63e07aSXin Li-    /* create the image */
2555*ec63e07aSXin Li-    image = opj_image_create((OPJ_UINT32)numcomps, &cmptparm[0], color_space);
2556*ec63e07aSXin Li-    free(cmptparm);
2557*ec63e07aSXin Li-    if (!image) {
2558*ec63e07aSXin Li-        fclose(f);
2559*ec63e07aSXin Li-        return NULL;
2560*ec63e07aSXin Li-    }
2561*ec63e07aSXin Li-    /* set image offset and reference grid */
2562*ec63e07aSXin Li-    image->x0 = (OPJ_UINT32)parameters->image_offset_x0;
2563*ec63e07aSXin Li-    image->y0 = (OPJ_UINT32)parameters->image_offset_y0;
2564*ec63e07aSXin Li-    image->x1 = (OPJ_UINT32)parameters->image_offset_x0 + (OPJ_UINT32)(w - 1) *
2565*ec63e07aSXin Li-                (OPJ_UINT32)subsampling_dx + 1;
2566*ec63e07aSXin Li-    image->y1 = (OPJ_UINT32)parameters->image_offset_y0 + (OPJ_UINT32)(h - 1) *
2567*ec63e07aSXin Li-                (OPJ_UINT32)subsampling_dy + 1;
2568*ec63e07aSXin Li-
2569*ec63e07aSXin Li-    if (raw_cp->rawBitDepth <= 8) {
2570*ec63e07aSXin Li-        unsigned char value = 0;
2571*ec63e07aSXin Li-        for (compno = 0; compno < numcomps; compno++) {
2572*ec63e07aSXin Li-            int nloop = (w * h) / (raw_cp->rawComps[compno].dx *
2573*ec63e07aSXin Li-                                   raw_cp->rawComps[compno].dy);
2574*ec63e07aSXin Li-            for (i = 0; i < nloop; i++) {
2575*ec63e07aSXin Li-                if (!fread(&value, 1, 1, f)) {
2576*ec63e07aSXin Li-                    fprintf(stderr, "Error reading raw file. End of file probably reached.\n");
2577*ec63e07aSXin Li-                    opj_image_destroy(image);
2578*ec63e07aSXin Li-                    fclose(f);
2579*ec63e07aSXin Li-                    return NULL;
2580*ec63e07aSXin Li-                }
2581*ec63e07aSXin Li-                image->comps[compno].data[i] = raw_cp->rawSigned ? (char)value : value;
2582*ec63e07aSXin Li-            }
2583*ec63e07aSXin Li-        }
2584*ec63e07aSXin Li-    } else if (raw_cp->rawBitDepth <= 16) {
2585*ec63e07aSXin Li-        unsigned short value;
2586*ec63e07aSXin Li-        for (compno = 0; compno < numcomps; compno++) {
2587*ec63e07aSXin Li-            int nloop = (w * h) / (raw_cp->rawComps[compno].dx *
2588*ec63e07aSXin Li-                                   raw_cp->rawComps[compno].dy);
2589*ec63e07aSXin Li-            for (i = 0; i < nloop; i++) {
2590*ec63e07aSXin Li-                unsigned char temp1;
2591*ec63e07aSXin Li-                unsigned char temp2;
2592*ec63e07aSXin Li-                if (!fread(&temp1, 1, 1, f)) {
2593*ec63e07aSXin Li-                    fprintf(stderr, "Error reading raw file. End of file probably reached.\n");
2594*ec63e07aSXin Li-                    opj_image_destroy(image);
2595*ec63e07aSXin Li-                    fclose(f);
2596*ec63e07aSXin Li-                    return NULL;
2597*ec63e07aSXin Li-                }
2598*ec63e07aSXin Li-                if (!fread(&temp2, 1, 1, f)) {
2599*ec63e07aSXin Li-                    fprintf(stderr, "Error reading raw file. End of file probably reached.\n");
2600*ec63e07aSXin Li-                    opj_image_destroy(image);
2601*ec63e07aSXin Li-                    fclose(f);
2602*ec63e07aSXin Li-                    return NULL;
2603*ec63e07aSXin Li-                }
2604*ec63e07aSXin Li-                if (big_endian) {
2605*ec63e07aSXin Li-                    value = (unsigned short)((temp1 << 8) + temp2);
2606*ec63e07aSXin Li-                } else {
2607*ec63e07aSXin Li-                    value = (unsigned short)((temp2 << 8) + temp1);
2608*ec63e07aSXin Li-                }
2609*ec63e07aSXin Li-                image->comps[compno].data[i] = raw_cp->rawSigned ? (short)value : value;
2610*ec63e07aSXin Li-            }
2611*ec63e07aSXin Li-        }
2612*ec63e07aSXin Li-    } else {
2613*ec63e07aSXin Li-        fprintf(stderr,
2614*ec63e07aSXin Li-                "OpenJPEG cannot encode raw components with bit depth higher than 16 bits.\n");
2615*ec63e07aSXin Li-        opj_image_destroy(image);
2616*ec63e07aSXin Li-        fclose(f);
2617*ec63e07aSXin Li-        return NULL;
2618*ec63e07aSXin Li+      sprintf(destname, "%s", outfile);
2619*ec63e07aSXin Li     }
2620*ec63e07aSXin Li
2621*ec63e07aSXin Li-    if (fread(&ch, 1, 1, f)) {
2622*ec63e07aSXin Li-        fprintf(stderr, "Warning. End of raw file not reached... processing anyway\n");
2623*ec63e07aSXin Li+    fdest = fopen(destname, "wb");
2624*ec63e07aSXin Li+    if (!fdest) {
2625*ec63e07aSXin Li+      fprintf(stderr, "ERROR -> failed to open %s for writing\n", destname);
2626*ec63e07aSXin Li+      free(destname);
2627*ec63e07aSXin Li+      return 1;
2628*ec63e07aSXin Li     }
2629*ec63e07aSXin Li-    fclose(f);
2630*ec63e07aSXin Li+    wr = (int)image->comps[compno].w;
2631*ec63e07aSXin Li+    hr = (int)image->comps[compno].h;
2632*ec63e07aSXin Li+    prec = (int)image->comps[compno].prec;
2633*ec63e07aSXin Li+    max = (1 << prec) - 1;
2634*ec63e07aSXin Li
2635*ec63e07aSXin Li-    return image;
2636*ec63e07aSXin Li-}
2637*ec63e07aSXin Li+    fprintf(fdest, "P5\n#OpenJPEG-%s\n%d %d\n%d\n", opj_version(), wr, hr, max);
2638*ec63e07aSXin Li
2639*ec63e07aSXin Li-opj_image_t* rawltoimage(const char *filename, opj_cparameters_t *parameters,
2640*ec63e07aSXin Li-                         raw_cparameters_t *raw_cp)
2641*ec63e07aSXin Li-{
2642*ec63e07aSXin Li-    return rawtoimage_common(filename, parameters, raw_cp, OPJ_FALSE);
2643*ec63e07aSXin Li-}
2644*ec63e07aSXin Li-
2645*ec63e07aSXin Li-opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters,
2646*ec63e07aSXin Li-                        raw_cparameters_t *raw_cp)
2647*ec63e07aSXin Li-{
2648*ec63e07aSXin Li-    return rawtoimage_common(filename, parameters, raw_cp, OPJ_TRUE);
2649*ec63e07aSXin Li-}
2650*ec63e07aSXin Li+    red = image->comps[compno].data;
2651*ec63e07aSXin Li
2652*ec63e07aSXin Li-static int imagetoraw_common(opj_image_t * image, const char *outfile,
2653*ec63e07aSXin Li-                             OPJ_BOOL big_endian)
2654*ec63e07aSXin Li-{
2655*ec63e07aSXin Li-    FILE *rawFile = NULL;
2656*ec63e07aSXin Li-    size_t res;
2657*ec63e07aSXin Li-    unsigned int compno, numcomps;
2658*ec63e07aSXin Li-    int w, h, fails;
2659*ec63e07aSXin Li-    int line, row, curr, mask;
2660*ec63e07aSXin Li-    int *ptr;
2661*ec63e07aSXin Li-    unsigned char uc;
2662*ec63e07aSXin Li-    (void)big_endian;
2663*ec63e07aSXin Li-
2664*ec63e07aSXin Li-    if ((image->numcomps * image->x1 * image->y1) == 0) {
2665*ec63e07aSXin Li-        fprintf(stderr, "\nError: invalid raw image parameters\n");
2666*ec63e07aSXin Li-        return 1;
2667*ec63e07aSXin Li+    if (!red) {
2668*ec63e07aSXin Li+      fclose(fdest);
2669*ec63e07aSXin Li+      continue;
2670*ec63e07aSXin Li     }
2671*ec63e07aSXin Li
2672*ec63e07aSXin Li-    numcomps = image->numcomps;
2673*ec63e07aSXin Li+    adjustR =
2674*ec63e07aSXin Li+        (image->comps[compno].sgnd ? 1 << (image->comps[compno].prec - 1) : 0);
2675*ec63e07aSXin Li
2676*ec63e07aSXin Li-    if (numcomps > 4) {
2677*ec63e07aSXin Li-        numcomps = 4;
2678*ec63e07aSXin Li-    }
2679*ec63e07aSXin Li-
2680*ec63e07aSXin Li-    for (compno = 1; compno < numcomps; ++compno) {
2681*ec63e07aSXin Li-        if (image->comps[0].dx != image->comps[compno].dx) {
2682*ec63e07aSXin Li-            break;
2683*ec63e07aSXin Li-        }
2684*ec63e07aSXin Li-        if (image->comps[0].dy != image->comps[compno].dy) {
2685*ec63e07aSXin Li-            break;
2686*ec63e07aSXin Li+    if (prec > 8) {
2687*ec63e07aSXin Li+      for (i = 0; i < wr * hr; i++) {
2688*ec63e07aSXin Li+        v = *red + adjustR;
2689*ec63e07aSXin Li+        ++red;
2690*ec63e07aSXin Li+        if (v > 65535) {
2691*ec63e07aSXin Li+          v = 65535;
2692*ec63e07aSXin Li+        } else if (v < 0) {
2693*ec63e07aSXin Li+          v = 0;
2694*ec63e07aSXin Li         }
2695*ec63e07aSXin Li-        if (image->comps[0].prec != image->comps[compno].prec) {
2696*ec63e07aSXin Li-            break;
2697*ec63e07aSXin Li-        }
2698*ec63e07aSXin Li-        if (image->comps[0].sgnd != image->comps[compno].sgnd) {
2699*ec63e07aSXin Li-            break;
2700*ec63e07aSXin Li-        }
2701*ec63e07aSXin Li-    }
2702*ec63e07aSXin Li-    if (compno != numcomps) {
2703*ec63e07aSXin Li-        fprintf(stderr,
2704*ec63e07aSXin Li-                "imagetoraw_common: All components shall have the same subsampling, same bit depth, same sign.\n");
2705*ec63e07aSXin Li-        fprintf(stderr, "\tAborting\n");
2706*ec63e07aSXin Li-        return 1;
2707*ec63e07aSXin Li-    }
2708*ec63e07aSXin Li
2709*ec63e07aSXin Li-    rawFile = fopen(outfile, "wb");
2710*ec63e07aSXin Li-    if (!rawFile) {
2711*ec63e07aSXin Li-        fprintf(stderr, "Failed to open %s for writing !!\n", outfile);
2712*ec63e07aSXin Li-        return 1;
2713*ec63e07aSXin Li-    }
2714*ec63e07aSXin Li-
2715*ec63e07aSXin Li-    fails = 1;
2716*ec63e07aSXin Li-    fprintf(stdout, "Raw image characteristics: %d components\n", image->numcomps);
2717*ec63e07aSXin Li+        /* netpbm: */
2718*ec63e07aSXin Li+        fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2719*ec63e07aSXin Li
2720*ec63e07aSXin Li-    for (compno = 0; compno < image->numcomps; compno++) {
2721*ec63e07aSXin Li-        fprintf(stdout, "Component %u characteristics: %dx%dx%d %s\n", compno,
2722*ec63e07aSXin Li-                image->comps[compno].w,
2723*ec63e07aSXin Li-                image->comps[compno].h, image->comps[compno].prec,
2724*ec63e07aSXin Li-                image->comps[compno].sgnd == 1 ? "signed" : "unsigned");
2725*ec63e07aSXin Li-
2726*ec63e07aSXin Li-        w = (int)image->comps[compno].w;
2727*ec63e07aSXin Li-        h = (int)image->comps[compno].h;
2728*ec63e07aSXin Li-
2729*ec63e07aSXin Li-        if (image->comps[compno].prec <= 8) {
2730*ec63e07aSXin Li-            if (image->comps[compno].sgnd == 1) {
2731*ec63e07aSXin Li-                mask = (1 << image->comps[compno].prec) - 1;
2732*ec63e07aSXin Li-                ptr = image->comps[compno].data;
2733*ec63e07aSXin Li-                for (line = 0; line < h; line++) {
2734*ec63e07aSXin Li-                    for (row = 0; row < w; row++)    {
2735*ec63e07aSXin Li-                        curr = *ptr;
2736*ec63e07aSXin Li-                        if (curr > 127) {
2737*ec63e07aSXin Li-                            curr = 127;
2738*ec63e07aSXin Li-                        } else if (curr < -128) {
2739*ec63e07aSXin Li-                            curr = -128;
2740*ec63e07aSXin Li-                        }
2741*ec63e07aSXin Li-                        uc = (unsigned char)(curr & mask);
2742*ec63e07aSXin Li-                        res = fwrite(&uc, 1, 1, rawFile);
2743*ec63e07aSXin Li-                        if (res < 1) {
2744*ec63e07aSXin Li-                            fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
2745*ec63e07aSXin Li-                            goto fin;
2746*ec63e07aSXin Li-                        }
2747*ec63e07aSXin Li-                        ptr++;
2748*ec63e07aSXin Li-                    }
2749*ec63e07aSXin Li-                }
2750*ec63e07aSXin Li-            } else if (image->comps[compno].sgnd == 0) {
2751*ec63e07aSXin Li-                mask = (1 << image->comps[compno].prec) - 1;
2752*ec63e07aSXin Li-                ptr = image->comps[compno].data;
2753*ec63e07aSXin Li-                for (line = 0; line < h; line++) {
2754*ec63e07aSXin Li-                    for (row = 0; row < w; row++)    {
2755*ec63e07aSXin Li-                        curr = *ptr;
2756*ec63e07aSXin Li-                        if (curr > 255) {
2757*ec63e07aSXin Li-                            curr = 255;
2758*ec63e07aSXin Li-                        } else if (curr < 0) {
2759*ec63e07aSXin Li-                            curr = 0;
2760*ec63e07aSXin Li-                        }
2761*ec63e07aSXin Li-                        uc = (unsigned char)(curr & mask);
2762*ec63e07aSXin Li-                        res = fwrite(&uc, 1, 1, rawFile);
2763*ec63e07aSXin Li-                        if (res < 1) {
2764*ec63e07aSXin Li-                            fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
2765*ec63e07aSXin Li-                            goto fin;
2766*ec63e07aSXin Li-                        }
2767*ec63e07aSXin Li-                        ptr++;
2768*ec63e07aSXin Li-                    }
2769*ec63e07aSXin Li-                }
2770*ec63e07aSXin Li-            }
2771*ec63e07aSXin Li-        } else if (image->comps[compno].prec <= 16) {
2772*ec63e07aSXin Li-            if (image->comps[compno].sgnd == 1) {
2773*ec63e07aSXin Li-                union {
2774*ec63e07aSXin Li-                    signed short val;
2775*ec63e07aSXin Li-                    signed char vals[2];
2776*ec63e07aSXin Li-                } uc16;
2777*ec63e07aSXin Li-                mask = (1 << image->comps[compno].prec) - 1;
2778*ec63e07aSXin Li-                ptr = image->comps[compno].data;
2779*ec63e07aSXin Li-                for (line = 0; line < h; line++) {
2780*ec63e07aSXin Li-                    for (row = 0; row < w; row++)    {
2781*ec63e07aSXin Li-                        curr = *ptr;
2782*ec63e07aSXin Li-                        if (curr > 32767) {
2783*ec63e07aSXin Li-                            curr = 32767;
2784*ec63e07aSXin Li-                        } else if (curr < -32768) {
2785*ec63e07aSXin Li-                            curr = -32768;
2786*ec63e07aSXin Li-                        }
2787*ec63e07aSXin Li-                        uc16.val = (signed short)(curr & mask);
2788*ec63e07aSXin Li-                        res = fwrite(uc16.vals, 1, 2, rawFile);
2789*ec63e07aSXin Li-                        if (res < 2) {
2790*ec63e07aSXin Li-                            fprintf(stderr, "failed to write 2 byte for %s\n", outfile);
2791*ec63e07aSXin Li-                            goto fin;
2792*ec63e07aSXin Li-                        }
2793*ec63e07aSXin Li-                        ptr++;
2794*ec63e07aSXin Li-                    }
2795*ec63e07aSXin Li-                }
2796*ec63e07aSXin Li-            } else if (image->comps[compno].sgnd == 0) {
2797*ec63e07aSXin Li-                union {
2798*ec63e07aSXin Li-                    unsigned short val;
2799*ec63e07aSXin Li-                    unsigned char vals[2];
2800*ec63e07aSXin Li-                } uc16;
2801*ec63e07aSXin Li-                mask = (1 << image->comps[compno].prec) - 1;
2802*ec63e07aSXin Li-                ptr = image->comps[compno].data;
2803*ec63e07aSXin Li-                for (line = 0; line < h; line++) {
2804*ec63e07aSXin Li-                    for (row = 0; row < w; row++)    {
2805*ec63e07aSXin Li-                        curr = *ptr;
2806*ec63e07aSXin Li-                        if (curr > 65535) {
2807*ec63e07aSXin Li-                            curr = 65535;
2808*ec63e07aSXin Li-                        } else if (curr < 0) {
2809*ec63e07aSXin Li-                            curr = 0;
2810*ec63e07aSXin Li-                        }
2811*ec63e07aSXin Li-                        uc16.val = (unsigned short)(curr & mask);
2812*ec63e07aSXin Li-                        res = fwrite(uc16.vals, 1, 2, rawFile);
2813*ec63e07aSXin Li-                        if (res < 2) {
2814*ec63e07aSXin Li-                            fprintf(stderr, "failed to write 2 byte for %s\n", outfile);
2815*ec63e07aSXin Li-                            goto fin;
2816*ec63e07aSXin Li-                        }
2817*ec63e07aSXin Li-                        ptr++;
2818*ec63e07aSXin Li-                    }
2819*ec63e07aSXin Li-                }
2820*ec63e07aSXin Li-            }
2821*ec63e07aSXin Li-        } else if (image->comps[compno].prec <= 32) {
2822*ec63e07aSXin Li-            fprintf(stderr, "More than 16 bits per component not handled yet\n");
2823*ec63e07aSXin Li-            goto fin;
2824*ec63e07aSXin Li-        } else {
2825*ec63e07aSXin Li-            fprintf(stderr, "Error: invalid precision: %d\n", image->comps[compno].prec);
2826*ec63e07aSXin Li-            goto fin;
2827*ec63e07aSXin Li+        if (has_alpha) {
2828*ec63e07aSXin Li+          v = *alpha++;
2829*ec63e07aSXin Li+          if (v > 65535) {
2830*ec63e07aSXin Li+            v = 65535;
2831*ec63e07aSXin Li+          } else if (v < 0) {
2832*ec63e07aSXin Li+            v = 0;
2833*ec63e07aSXin Li+          }
2834*ec63e07aSXin Li+
2835*ec63e07aSXin Li+          /* netpbm: */
2836*ec63e07aSXin Li+          fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
2837*ec63e07aSXin Li+        }
2838*ec63e07aSXin Li+      }      /* for(i */
2839*ec63e07aSXin Li+    } else { /* prec <= 8 */
2840*ec63e07aSXin Li+      for (i = 0; i < wr * hr; ++i) {
2841*ec63e07aSXin Li+        v = *red + adjustR;
2842*ec63e07aSXin Li+        ++red;
2843*ec63e07aSXin Li+        if (v > 255) {
2844*ec63e07aSXin Li+          v = 255;
2845*ec63e07aSXin Li+        } else if (v < 0) {
2846*ec63e07aSXin Li+          v = 0;
2847*ec63e07aSXin Li         }
2848*ec63e07aSXin Li+        fprintf(fdest, "%c", (unsigned char)v);
2849*ec63e07aSXin Li+      }
2850*ec63e07aSXin Li     }
2851*ec63e07aSXin Li-    fails = 0;
2852*ec63e07aSXin Li-fin:
2853*ec63e07aSXin Li-    fclose(rawFile);
2854*ec63e07aSXin Li-    return fails;
2855*ec63e07aSXin Li-}
2856*ec63e07aSXin Li-
2857*ec63e07aSXin Li-int imagetoraw(opj_image_t * image, const char *outfile)
2858*ec63e07aSXin Li-{
2859*ec63e07aSXin Li-    return imagetoraw_common(image, outfile, OPJ_TRUE);
2860*ec63e07aSXin Li-}
2861*ec63e07aSXin Li-
2862*ec63e07aSXin Li-int imagetorawl(opj_image_t * image, const char *outfile)
2863*ec63e07aSXin Li-{
2864*ec63e07aSXin Li-    return imagetoraw_common(image, outfile, OPJ_FALSE);
2865*ec63e07aSXin Li-}
2866*ec63e07aSXin Li+    fclose(fdest);
2867*ec63e07aSXin Li+  } /* for (compno */
2868*ec63e07aSXin Li+  free(destname);
2869*ec63e07aSXin Li
2870*ec63e07aSXin Li+  return 0;
2871*ec63e07aSXin Li+} /* imagetopnm() */
2872