]> Creatis software - gdcm.git/blob - src/gdcmjasper/src/libjasper/pgx/pgx_dec.c
2ea800c0fa07b6451c89b3d7915265f209ff0ecd
[gdcm.git] / src / gdcmjasper / src / libjasper / pgx / pgx_dec.c
1 /*
2  * Copyright (c) 2001-2003 Michael David Adams.
3  * All rights reserved.
4  */
5
6 /* __START_OF_JASPER_LICENSE__
7  * 
8  * JasPer License Version 2.0
9  * 
10  * Copyright (c) 1999-2000 Image Power, Inc.
11  * Copyright (c) 1999-2000 The University of British Columbia
12  * Copyright (c) 2001-2003 Michael David Adams
13  * 
14  * All rights reserved.
15  * 
16  * Permission is hereby granted, free of charge, to any person (the
17  * "User") obtaining a copy of this software and associated documentation
18  * files (the "Software"), to deal in the Software without restriction,
19  * including without limitation the rights to use, copy, modify, merge,
20  * publish, distribute, and/or sell copies of the Software, and to permit
21  * persons to whom the Software is furnished to do so, subject to the
22  * following conditions:
23  * 
24  * 1.  The above copyright notices and this permission notice (which
25  * includes the disclaimer below) shall be included in all copies or
26  * substantial portions of the Software.
27  * 
28  * 2.  The name of a copyright holder shall not be used to endorse or
29  * promote products derived from the Software without specific prior
30  * written permission.
31  * 
32  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
33  * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
34  * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
35  * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
36  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
37  * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
38  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
39  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
40  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
41  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
42  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
43  * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
44  * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
45  * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
46  * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
47  * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
48  * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
49  * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
50  * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
51  * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
52  * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
53  * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
54  * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
55  * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
56  * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
57  * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
58  * 
59  * __END_OF_JASPER_LICENSE__
60  */
61
62 /******************************************************************************\
63 * Includes.
64 \******************************************************************************/
65
66 #include <assert.h>
67 #include <ctype.h>
68
69 #include "jasper/jas_tvp.h"
70 #include "jasper/jas_stream.h"
71 #include "jasper/jas_image.h"
72 #include "jasper/jas_string.h"
73
74 #include "pgx_cod.h"
75
76 /******************************************************************************\
77 * Local prototypes.
78 \******************************************************************************/
79
80 static int pgx_gethdr(jas_stream_t *in, pgx_hdr_t *hdr);
81 static int pgx_getdata(jas_stream_t *in, pgx_hdr_t *hdr, jas_image_t *image);
82 static int_fast32_t pgx_getword(jas_stream_t *in, bool bigendian, int prec);
83 static int pgx_getsgnd(jas_stream_t *in, bool *sgnd);
84 static int pgx_getbyteorder(jas_stream_t *in, bool *bigendian);
85 static int pgx_getc(jas_stream_t *in);
86 static int pgx_getuint32(jas_stream_t *in, uint_fast32_t *val);
87 static jas_seqent_t pgx_wordtoint(uint_fast32_t word, int prec, bool sgnd);
88
89 /******************************************************************************\
90 * Code for load operation.
91 \******************************************************************************/
92
93 /* Load an image from a stream in the PGX format. */
94
95 jas_image_t *pgx_decode(jas_stream_t *in, char *optstr)
96 {
97   jas_image_t *image;
98   pgx_hdr_t hdr;
99   jas_image_cmptparm_t cmptparm;
100
101   /* Avoid compiler warnings about unused parameters. */
102   optstr = 0;
103
104   image = 0;
105
106   if (pgx_gethdr(in, &hdr)) {
107     goto error;
108   }
109
110 #ifdef PGX_DEBUG
111   pgx_dumphdr(stderr, &hdr);
112 #endif
113
114   if (!(image = jas_image_create0())) {
115     goto error;
116   }
117   cmptparm.tlx = 0;
118   cmptparm.tly = 0;
119   cmptparm.hstep = 1;
120   cmptparm.vstep = 1;
121   cmptparm.width = hdr.width;
122   cmptparm.height = hdr.height;
123   cmptparm.prec = hdr.prec;
124   cmptparm.sgnd = hdr.sgnd;
125   if (jas_image_addcmpt(image, 0, &cmptparm)) {
126     goto error;
127   }
128   if (pgx_getdata(in, &hdr, image)) {
129     goto error;
130   }
131
132   jas_image_setclrspc(image, JAS_CLRSPC_SGRAY);
133   jas_image_setcmpttype(image, 0,
134     JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
135
136   return image;
137
138 error:
139   if (image) {
140     jas_image_destroy(image);
141   }
142   return 0;
143 }
144
145 /******************************************************************************\
146 * Code for validate operation.
147 \******************************************************************************/
148
149 int pgx_validate(jas_stream_t *in)
150 {
151   uchar buf[PGX_MAGICLEN];
152   uint_fast32_t magic;
153   int i;
154   int n;
155
156   assert(JAS_STREAM_MAXPUTBACK >= PGX_MAGICLEN);
157
158   /* Read the validation data (i.e., the data used for detecting
159     the format). */
160   if ((n = jas_stream_read(in, buf, PGX_MAGICLEN)) < 0) {
161     return -1;
162   }
163
164   /* Put the validation data back onto the stream, so that the
165     stream position will not be changed. */
166   for (i = n - 1; i >= 0; --i) {
167     if (jas_stream_ungetc(in, buf[i]) == EOF) {
168       return -1;
169     }
170   }
171
172   /* Did we read enough data? */
173   if (n < PGX_MAGICLEN) {
174     return -1;
175   }
176
177   /* Compute the signature value. */
178   magic = (buf[0] << 8) | buf[1];
179
180   /* Ensure that the signature is correct for this format. */
181   if (magic != PGX_MAGIC) {
182     return -1;
183   }
184
185   return 0;
186 }
187
188 /******************************************************************************\
189 *
190 \******************************************************************************/
191
192 static int pgx_gethdr(jas_stream_t *in, pgx_hdr_t *hdr)
193 {
194   int c;
195   uchar buf[2];
196
197   if ((c = jas_stream_getc(in)) == EOF) {
198     goto error;
199   }
200   buf[0] = c;
201   if ((c = jas_stream_getc(in)) == EOF) {
202     goto error;
203   }
204   buf[1] = c;
205   hdr->magic = buf[0] << 8 | buf[1];
206   if (hdr->magic != PGX_MAGIC) {
207     goto error;
208   }
209   if ((c = pgx_getc(in)) == EOF || !isspace(c)) {
210     goto error;
211   }
212   if (pgx_getbyteorder(in, &hdr->bigendian)) {
213     goto error;
214   }
215   if (pgx_getsgnd(in, &hdr->sgnd)) {
216     goto error;
217   }
218   if (pgx_getuint32(in, &hdr->prec)) {
219     goto error;
220   }
221   if (pgx_getuint32(in, &hdr->width)) {
222     goto error;
223   }
224   if (pgx_getuint32(in, &hdr->height)) {
225     goto error;
226   }
227   return 0;
228
229 error:
230   return -1;
231 }
232
233 static int pgx_getdata(jas_stream_t *in, pgx_hdr_t *hdr, jas_image_t *image)
234 {
235   jas_matrix_t *data;
236   uint_fast32_t x;
237   uint_fast32_t y;
238   uint_fast32_t word;
239   int_fast32_t v;
240
241   data = 0;
242
243   if (!(data = jas_matrix_create(1, hdr->width))) {
244     goto error;
245   }
246   for (y = 0; y < hdr->height; ++y) {
247     for (x = 0; x < hdr->width; ++x) {
248       /* Need to adjust signed value. */
249       if ((v = pgx_getword(in, hdr->bigendian, hdr->prec)) < 0) {
250         goto error;
251       }
252       word = v;
253       v = pgx_wordtoint(word, hdr->prec, hdr->sgnd);
254       jas_matrix_set(data, 0, x, v);
255     }
256     if (jas_image_writecmpt(image, 0, 0, y, hdr->width, 1, data)) {
257       goto error;
258     }
259   }
260   jas_matrix_destroy(data);
261   return 0;
262
263 error:
264   if (data) {
265     jas_matrix_destroy(data);
266   }
267   return -1;
268 }
269
270 static int_fast32_t pgx_getword(jas_stream_t *in, bool bigendian, int prec)
271 {
272   uint_fast32_t val;
273   int i;
274   int j;
275   int c;
276   int wordsize;
277
278   wordsize = (prec + 7) / 8;
279
280   if (prec > 32) {
281     goto error;
282   }
283
284   val = 0;
285   for (i = 0; i < wordsize; ++i) {
286     if ((c = jas_stream_getc(in)) == EOF) {
287       goto error;
288     }
289     j = bigendian ? (wordsize - 1 - i) : i;
290     val = val | ((c & 0xff) << (8 * j));
291   }
292   val &= (1 << prec) - 1;
293   return val;
294
295 error:
296   return -1;
297 }
298
299 static int pgx_getc(jas_stream_t *in)
300 {
301   int c;
302   for (;;) {
303     if ((c = jas_stream_getc(in)) == EOF) {
304       return -1;
305     }
306     if (c != '#') {
307       return c;
308     }
309     do {
310       if ((c = jas_stream_getc(in)) == EOF) {
311         return -1;
312       }
313     } while (c != '\n' && c != '\r');
314   }
315 }
316
317 static int pgx_getbyteorder(jas_stream_t *in, bool *bigendian)
318 {
319   int c;
320   char buf[2];
321
322   do {
323     if ((c = pgx_getc(in)) == EOF) {
324       return -1;
325     }
326   } while (isspace(c));
327
328   buf[0] = c;
329   if ((c = pgx_getc(in)) == EOF) {
330     goto error;
331   }
332   buf[1] = c;
333   if (buf[0] == 'M' && buf[1] == 'L') {
334     *bigendian = true;
335   } else if (buf[0] == 'L' && buf[1] == 'M') {
336     *bigendian = false;
337   } else {
338     goto error;
339   }
340
341   while ((c = pgx_getc(in)) != EOF && !isspace(c)) {
342     ;
343   }
344   if (c == EOF) {
345     goto error;
346   }
347   return 0;
348
349 error:
350   return -1;
351 }
352
353 static int pgx_getsgnd(jas_stream_t *in, bool *sgnd)
354 {
355   int c;
356
357   do {
358     if ((c = pgx_getc(in)) == EOF) {
359       return -1;
360     }
361   } while (isspace(c));
362
363   if (c == '+') {
364     *sgnd = false;
365   } else if (c == '-') {
366     *sgnd = true;
367   } else {
368     goto error;
369   }
370   while ((c = pgx_getc(in)) != EOF && !isspace(c)) {
371     ;
372   }
373   if (c == EOF) {
374     goto error;
375   }
376   return 0;
377
378 error:
379   return -1;
380 }
381
382 static int pgx_getuint32(jas_stream_t *in, uint_fast32_t *val)
383 {
384   int c;
385   uint_fast32_t v;
386
387   do {
388     if ((c = pgx_getc(in)) == EOF) {
389       return -1;
390     }
391   } while (isspace(c));
392
393   v = 0;
394   while (isdigit(c)) {
395     v = 10 * v + c - '0';
396     if ((c = pgx_getc(in)) < 0) {
397       return -1;
398     }
399   }
400   if (!isspace(c)) {
401     return -1;
402   }
403   *val = v;
404
405   return 0;
406 }
407
408 static jas_seqent_t pgx_wordtoint(uint_fast32_t v, int prec, bool sgnd)
409 {
410   jas_seqent_t ret;
411   v &= (1 << prec) - 1;
412   ret = (sgnd && (v & (1 << (prec - 1)))) ? (v - (1 << prec)) : v;
413   return ret;
414 }