]> Creatis software - gdcm.git/blob - src/gdcmjasper/src/libjasper/mif/mif_cod.c
ENH: Ok since OJ warnings are not going to be fixed anytime soon remove them
[gdcm.git] / src / gdcmjasper / src / libjasper / mif / mif_cod.c
1 /*
2  * Copyright (c) 2001-2002 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
68 #include "jasper/jas_tvp.h"
69 #include "jasper/jas_stream.h"
70 #include "jasper/jas_image.h"
71 #include "jasper/jas_string.h"
72 #include "jasper/jas_malloc.h"
73
74 #include "mif_cod.h"
75
76 /******************************************************************************\
77 * Local types.
78 \******************************************************************************/
79
80 typedef enum {
81   MIF_END = 0,
82   MIF_CMPT
83 } mif_tagid2_t;
84
85 typedef enum {
86   MIF_TLX = 0,
87   MIF_TLY,
88   MIF_WIDTH,
89   MIF_HEIGHT,
90   MIF_HSAMP,
91   MIF_VSAMP,
92   MIF_PREC,
93   MIF_SGND,
94   MIF_DATA
95 } mif_tagid_t;
96
97 /******************************************************************************\
98 * Local functions.
99 \******************************************************************************/
100
101 static mif_hdr_t *mif_hdr_create(int maxcmpts);
102 static void mif_hdr_destroy(mif_hdr_t *hdr);
103 static int mif_hdr_growcmpts(mif_hdr_t *hdr, int maxcmpts);
104 static mif_hdr_t *mif_hdr_get(jas_stream_t *in);
105 static int mif_process_cmpt(mif_hdr_t *hdr, char *buf);
106 static int mif_hdr_put(mif_hdr_t *hdr, jas_stream_t *out);
107 static int mif_hdr_addcmpt(mif_hdr_t *hdr, int cmptno, mif_cmpt_t *cmpt);
108 static mif_cmpt_t *mif_cmpt_create(void);
109 static void mif_cmpt_destroy(mif_cmpt_t *cmpt);
110 static char *mif_getline(jas_stream_t *jas_stream, char *buf, int bufsize);
111 static int mif_getc(jas_stream_t *in);
112 static mif_hdr_t *mif_makehdrfromimage(jas_image_t *image);
113
114 /******************************************************************************\
115 * Local data.
116 \******************************************************************************/
117
118 jas_taginfo_t mif_tags2[] = {
119   {MIF_CMPT, "component"},
120   {MIF_END, "end"},
121   {-1, 0}
122 };
123
124 jas_taginfo_t mif_tags[] = {
125   {MIF_TLX, "tlx"},
126   {MIF_TLY, "tly"},
127   {MIF_WIDTH, "width"},
128   {MIF_HEIGHT, "height"},
129   {MIF_HSAMP, "sampperx"},
130   {MIF_VSAMP, "samppery"},
131   {MIF_PREC, "prec"},
132   {MIF_SGND, "sgnd"},
133   {MIF_DATA, "data"},
134   {-1, 0}
135 };
136
137 /******************************************************************************\
138 * Code for load operation.
139 \******************************************************************************/
140
141 /* Load an image from a stream in the MIF format. */
142
143 jas_image_t *mif_decode(jas_stream_t *in, char *optstr)
144 {
145   mif_hdr_t *hdr;
146   jas_image_t *image;
147   jas_image_t *tmpimage;
148   jas_stream_t *tmpstream;
149   int cmptno;
150   mif_cmpt_t *cmpt;
151   jas_image_cmptparm_t cmptparm;
152   jas_seq2d_t *data;
153   int_fast32_t x;
154   int_fast32_t y;
155   int bias;
156
157   /* Avoid warnings about unused parameters. */
158   optstr = 0;
159
160   hdr = 0;
161   image = 0;
162   tmpimage = 0;
163   tmpstream = 0;
164   data = 0;
165
166   if (!(hdr = mif_hdr_get(in))) {
167     goto error;
168   }
169
170   if (!(image = jas_image_create0())) {
171     goto error;
172   }
173
174   for (cmptno = 0; cmptno < hdr->numcmpts; ++cmptno) {
175     cmpt = hdr->cmpts[cmptno];
176     tmpstream = cmpt->data ? jas_stream_fopen(cmpt->data, "rb") : in;
177     if (!tmpstream) {
178       goto error;
179     }
180     if (!(tmpimage = jas_image_decode(tmpstream, -1, 0))) {
181       goto error;
182     }
183     if (tmpstream != in) {
184       jas_stream_close(tmpstream);
185       tmpstream = 0;
186     }
187     if (!cmpt->width) {
188       cmpt->width = jas_image_cmptwidth(tmpimage, 0);
189     }
190     if (!cmpt->height) {
191       cmpt->height = jas_image_cmptwidth(tmpimage, 0);
192     }
193     if (!cmpt->prec) {
194       cmpt->prec = jas_image_cmptprec(tmpimage, 0);
195     }
196     if (cmpt->sgnd < 0) {
197       cmpt->sgnd = jas_image_cmptsgnd(tmpimage, 0);
198     }
199     cmptparm.tlx = cmpt->tlx;
200     cmptparm.tly = cmpt->tly;
201     cmptparm.hstep = cmpt->sampperx;
202     cmptparm.vstep = cmpt->samppery;
203     cmptparm.width = cmpt->width;
204     cmptparm.height = cmpt->height;
205     cmptparm.prec = cmpt->prec;
206     cmptparm.sgnd = cmpt->sgnd;
207     if (jas_image_addcmpt(image, jas_image_numcmpts(image), &cmptparm)) {
208       goto error;
209     }
210     if (!(data = jas_seq2d_create(0, 0, cmpt->width, cmpt->height))) {
211       goto error;
212     }
213     if (jas_image_readcmpt(tmpimage, 0, 0, 0, cmpt->width, cmpt->height,
214       data)) {
215       goto error;
216     }
217     if (cmpt->sgnd) {
218       bias = 1 << (cmpt->prec - 1);
219       for (y = 0; y < cmpt->height; ++y) {
220         for (x = 0; x < cmpt->width; ++x) {
221           *jas_seq2d_getref(data, x, y) -= bias;
222         }
223       }
224     }
225     if (jas_image_writecmpt(image, jas_image_numcmpts(image) - 1, 0, 0,
226       cmpt->width, cmpt->height, data)) {
227       goto error;
228     }
229     jas_seq2d_destroy(data);
230     data = 0;
231     jas_image_destroy(tmpimage);
232     tmpimage = 0;
233   }
234
235   mif_hdr_destroy(hdr);
236   hdr = 0;
237   return image;
238
239 error:
240   if (image) {
241     jas_image_destroy(image);
242   }
243   if (hdr) {
244     mif_hdr_destroy(hdr);
245   }
246   if (tmpstream && tmpstream != in) {
247     jas_stream_close(tmpstream);
248   }
249   if (tmpimage) {
250     jas_image_destroy(tmpimage);
251   }
252   if (data) {
253     jas_seq2d_destroy(data);
254   }
255   return 0;
256 }
257
258 /******************************************************************************\
259 * Code for save operation.
260 \******************************************************************************/
261
262 /* Save an image to a stream in the the MIF format. */
263
264 int mif_encode(jas_image_t *image, jas_stream_t *out, char *optstr)
265 {
266   mif_hdr_t *hdr;
267   jas_image_t *tmpimage;
268   int fmt;
269   int cmptno;
270   mif_cmpt_t *cmpt;
271   jas_image_cmptparm_t cmptparm;
272   jas_seq2d_t *data;
273   int_fast32_t x;
274   int_fast32_t y;
275   int bias;
276
277   hdr = 0;
278   tmpimage = 0;
279   data = 0;
280
281   if (optstr && *optstr != '\0') {
282     fprintf(stderr, "warning: ignoring unsupported options\n");
283   }
284
285   if ((fmt = jas_image_strtofmt("pnm")) < 0) {
286     fprintf(stderr, "error: PNM support required\n");
287     goto error;
288   }
289
290   if (!(hdr = mif_makehdrfromimage(image))) {
291     goto error;
292   }
293   if (mif_hdr_put(hdr, out)) {
294     goto error;
295   }
296
297   /* Output component data. */
298   for (cmptno = 0; cmptno < hdr->numcmpts; ++cmptno) {
299     cmpt = hdr->cmpts[cmptno];
300     if (!cmpt->data) {
301       if (!(tmpimage = jas_image_create0())) {
302         goto error;
303       }  
304       cmptparm.tlx = 0;
305       cmptparm.tly = 0;
306       cmptparm.hstep = cmpt->sampperx;
307       cmptparm.vstep = cmpt->samppery;
308       cmptparm.width = cmpt->width;
309       cmptparm.height = cmpt->height;
310       cmptparm.prec = cmpt->prec;
311       cmptparm.sgnd = false;
312       if (jas_image_addcmpt(tmpimage, jas_image_numcmpts(tmpimage), &cmptparm)) {
313         goto error;
314       }
315       if (!(data = jas_seq2d_create(0, 0, cmpt->width, cmpt->height))) {
316         goto error;
317       }
318       if (jas_image_readcmpt(image, cmptno, 0, 0, cmpt->width, cmpt->height,
319         data)) {
320         goto error;
321       }
322       if (cmpt->sgnd) {
323         bias = 1 << (cmpt->prec - 1);
324         for (y = 0; y < cmpt->height; ++y) {
325           for (x = 0; x < cmpt->width; ++x) {
326             *jas_seq2d_getref(data, x, y) += bias;
327           }
328         }
329       }
330       if (jas_image_writecmpt(tmpimage, 0, 0, 0, cmpt->width, cmpt->height,
331         data)) {
332         goto error;
333       }
334       jas_seq2d_destroy(data);
335       data = 0;
336       if (jas_image_encode(tmpimage, out, fmt, 0)) {
337         goto error;
338       }
339       jas_image_destroy(tmpimage);
340       tmpimage = 0;
341     }
342   }
343
344   mif_hdr_destroy(hdr);
345
346   return 0;
347
348 error:
349   if (hdr) {
350     mif_hdr_destroy(hdr);
351   }
352   if (tmpimage) {
353     jas_image_destroy(tmpimage);
354   }
355   if (data) {
356     jas_seq2d_destroy(data);
357   }
358   return -1;
359 }
360
361 /******************************************************************************\
362 * Code for validate operation.
363 \******************************************************************************/
364
365 int mif_validate(jas_stream_t *in)
366 {
367   uchar buf[MIF_MAGICLEN];
368   uint_fast32_t magic;
369   int i;
370   int n;
371
372   assert(JAS_STREAM_MAXPUTBACK >= MIF_MAGICLEN);
373
374   /* Read the validation data (i.e., the data used for detecting
375     the format). */
376   if ((n = jas_stream_read(in, buf, MIF_MAGICLEN)) < 0) {
377     return -1;
378   }
379
380   /* Put the validation data back onto the stream, so that the
381     stream position will not be changed. */
382   for (i = n - 1; i >= 0; --i) {
383     if (jas_stream_ungetc(in, buf[i]) == EOF) {
384       return -1;
385     }
386   }
387
388   /* Was enough data read? */
389   if (n < MIF_MAGICLEN) {
390     return -1;
391   }
392
393   /* Compute the signature value. */
394   magic = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
395
396   /* Ensure that the signature is correct for this format. */
397   if (magic != MIF_MAGIC) {
398     return -1;
399   }
400
401   return 0;
402 }
403
404 /******************************************************************************\
405 * Code for MIF header class.
406 \******************************************************************************/
407
408 static mif_hdr_t *mif_hdr_create(int maxcmpts)
409 {
410   mif_hdr_t *hdr;
411   if (!(hdr = jas_malloc(sizeof(mif_hdr_t)))) {
412     return 0;
413   }
414   hdr->numcmpts = 0;
415   hdr->maxcmpts = 0;
416   hdr->cmpts = 0;
417   if (mif_hdr_growcmpts(hdr, maxcmpts)) {
418     mif_hdr_destroy(hdr);
419     return 0;
420   }
421   return hdr;
422 }
423
424 static void mif_hdr_destroy(mif_hdr_t *hdr)
425 {
426   int cmptno;
427   if (hdr->cmpts) {
428     for (cmptno = 0; cmptno < hdr->numcmpts; ++cmptno) {
429       mif_cmpt_destroy(hdr->cmpts[cmptno]);
430     }
431     jas_free(hdr->cmpts);
432   }
433   jas_free(hdr);
434 }
435
436 static int mif_hdr_growcmpts(mif_hdr_t *hdr, int maxcmpts)
437 {
438   int cmptno;
439   mif_cmpt_t **newcmpts;
440   assert(maxcmpts >= hdr->numcmpts);
441   newcmpts = (!hdr->cmpts) ? jas_malloc(maxcmpts * sizeof(mif_cmpt_t *)) :
442     jas_realloc(hdr->cmpts, maxcmpts * sizeof(mif_cmpt_t *));
443   if (!newcmpts) {
444     return -1;
445   }
446   hdr->maxcmpts = maxcmpts;
447   hdr->cmpts = newcmpts;
448   for (cmptno = hdr->numcmpts; cmptno < hdr->maxcmpts; ++cmptno) {
449     hdr->cmpts[cmptno] = 0;
450   }
451   return 0;
452 }
453
454 static mif_hdr_t *mif_hdr_get(jas_stream_t *in)
455 {
456   uchar magicbuf[MIF_MAGICLEN];
457   char buf[4096];
458   mif_hdr_t *hdr;
459   bool done;
460   jas_tvparser_t *tvp;
461   int id;
462
463   hdr = 0;
464
465   if (jas_stream_read(in, magicbuf, MIF_MAGICLEN) != MIF_MAGICLEN) {
466     goto error;
467   }
468   if (magicbuf[0] != (MIF_MAGIC >> 24) || magicbuf[1] != ((MIF_MAGIC >> 16) &
469     0xff) || magicbuf[2] != ((MIF_MAGIC >> 8) & 0xff) || magicbuf[3] !=
470     (MIF_MAGIC & 0xff)) {
471     fprintf(stderr, "error: bad signature\n");
472     goto error;
473   }
474
475   if (!(hdr = mif_hdr_create(0))) {
476     goto error;
477   }
478
479   done = false;
480   do {
481     if (!mif_getline(in, buf, sizeof(buf))) {
482       goto error;
483     }
484     if (buf[0] == '\0') {
485       continue;
486     }
487     if (!(tvp = jas_tvparser_create(buf))) {
488       goto error;
489     }
490     if (jas_tvparser_next(tvp)) {
491       abort();
492     }
493     id = jas_taginfo_nonull(jas_taginfos_lookup(mif_tags2, jas_tvparser_gettag(tvp)))->id;
494     jas_tvparser_destroy(tvp);
495     switch (id) {
496     case MIF_CMPT:
497       mif_process_cmpt(hdr, buf);
498       break;
499     case MIF_END:
500       done = 1;
501       break;
502     }
503   } while (!done);
504
505   return hdr;
506
507 error:
508   if (hdr) {
509     mif_hdr_destroy(hdr);
510   }
511   return 0;
512 }
513
514 static int mif_process_cmpt(mif_hdr_t *hdr, char *buf)
515 {
516   jas_tvparser_t *tvp;
517   mif_cmpt_t *cmpt;
518   int id;
519
520   cmpt = 0;
521   tvp = 0;
522
523   if (!(cmpt = mif_cmpt_create())) {
524     goto error;
525   }
526   cmpt->tlx = 0;
527   cmpt->tly = 0;
528   cmpt->sampperx = 0;
529   cmpt->samppery = 0;
530   cmpt->width = 0;
531   cmpt->height = 0;
532   cmpt->prec = 0;
533   cmpt->sgnd = -1;
534   cmpt->data = 0;
535
536   if (!(tvp = jas_tvparser_create(buf))) {
537     goto error;
538   }
539   while (!(id = jas_tvparser_next(tvp))) {
540     switch (jas_taginfo_nonull(jas_taginfos_lookup(mif_tags,
541       jas_tvparser_gettag(tvp)))->id) {
542     case MIF_TLX:
543       cmpt->tlx = atoi(jas_tvparser_getval(tvp));
544       break;
545     case MIF_TLY:
546       cmpt->tly = atoi(jas_tvparser_getval(tvp));
547       break;
548     case MIF_WIDTH:
549       cmpt->width = atoi(jas_tvparser_getval(tvp));
550       break;
551     case MIF_HEIGHT:
552       cmpt->height = atoi(jas_tvparser_getval(tvp));
553       break;
554     case MIF_HSAMP:
555       cmpt->sampperx = atoi(jas_tvparser_getval(tvp));
556       break;
557     case MIF_VSAMP:
558       cmpt->samppery = atoi(jas_tvparser_getval(tvp));
559       break;
560     case MIF_PREC:
561       cmpt->prec = atoi(jas_tvparser_getval(tvp));
562       break;
563     case MIF_SGND:
564       cmpt->sgnd = atoi(jas_tvparser_getval(tvp));
565       break;
566     case MIF_DATA:
567       if (!(cmpt->data = jas_strdup(jas_tvparser_getval(tvp)))) {
568         return -1;
569       }
570       break;
571     }
572   }
573   jas_tvparser_destroy(tvp);
574   if (!cmpt->sampperx || !cmpt->samppery) {
575     goto error;
576   }
577   if (mif_hdr_addcmpt(hdr, hdr->numcmpts, cmpt)) {
578     goto error;
579   }
580   (void)id; /* is is assigned a value that is never used */
581   return 0;
582
583 error:
584   if (cmpt) {
585     mif_cmpt_destroy(cmpt);
586   }
587   if (tvp) {
588     jas_tvparser_destroy(tvp);
589   }
590   return -1;
591 }
592
593 static int mif_hdr_put(mif_hdr_t *hdr, jas_stream_t *out)
594 {
595   int cmptno;
596   mif_cmpt_t *cmpt;
597
598   /* Output signature. */
599   jas_stream_putc(out, (MIF_MAGIC >> 24) & 0xff);
600   jas_stream_putc(out, (MIF_MAGIC >> 16) & 0xff);
601   jas_stream_putc(out, (MIF_MAGIC >> 8) & 0xff);
602   jas_stream_putc(out, MIF_MAGIC & 0xff);
603
604   /* Output component information. */
605   for (cmptno = 0; cmptno < hdr->numcmpts; ++cmptno) {
606     cmpt = hdr->cmpts[cmptno];
607     jas_stream_printf(out, "component tlx=%ld tly=%ld "
608       "sampperx=%ld samppery=%ld width=%ld height=%ld prec=%d sgnd=%d",
609       cmpt->tlx, cmpt->tly, cmpt->sampperx, cmpt->samppery, cmpt->width,
610       cmpt->height, cmpt->prec, cmpt->sgnd);
611     if (cmpt->data) {
612       jas_stream_printf(out, " data=%s", cmpt->data);
613     }
614     jas_stream_printf(out, "\n");
615   }
616
617   /* Output end of header indicator. */
618   jas_stream_printf(out, "end\n");
619
620   return 0;
621 }
622
623 static int mif_hdr_addcmpt(mif_hdr_t *hdr, int cmptno, mif_cmpt_t *cmpt)
624 {
625   assert(cmptno >= hdr->numcmpts);
626   if (hdr->numcmpts >= hdr->maxcmpts) {
627     if (mif_hdr_growcmpts(hdr, hdr->numcmpts + 128)) {
628       return -1;
629     }
630   }
631   hdr->cmpts[hdr->numcmpts] = cmpt;
632   ++hdr->numcmpts;
633   return 0;
634 }
635
636 /******************************************************************************\
637 * Code for MIF component class.
638 \******************************************************************************/
639
640 static mif_cmpt_t *mif_cmpt_create()
641 {
642   mif_cmpt_t *cmpt;
643   if (!(cmpt = jas_malloc(sizeof(mif_cmpt_t)))) {
644     return 0;
645   }
646   memset(cmpt, 0, sizeof(mif_cmpt_t));
647   return cmpt;
648 }
649
650 static void mif_cmpt_destroy(mif_cmpt_t *cmpt)
651 {
652   if (cmpt->data) {
653     jas_free(cmpt->data);
654   }
655   jas_free(cmpt);
656 }
657
658 /******************************************************************************\
659 * MIF parsing code.
660 \******************************************************************************/
661
662 static char *mif_getline(jas_stream_t *stream, char *buf, int bufsize)
663 {
664   int c;
665   char *bufptr;
666   assert(bufsize > 0);
667
668   bufptr = buf;
669   while (bufsize > 1) {
670     if ((c = mif_getc(stream)) == EOF) {
671       break;
672     }
673     *bufptr++ = c;
674     --bufsize;
675     if (c == '\n') {
676       break;
677     }
678   }
679   *bufptr = '\0';
680   if (!(bufptr = strchr(buf, '\n'))) {
681     return 0;
682   }
683   *bufptr = '\0';
684   return buf;
685 }
686
687 static int mif_getc(jas_stream_t *in)
688 {
689   int c;
690   bool done;
691
692   done = false;
693   do {
694     switch (c = jas_stream_getc(in)) {
695     case EOF:
696       done = 1;
697       break;
698     case '#':
699       for (;;) {
700         if ((c = jas_stream_getc(in)) == EOF) {
701           done = 1;
702           break;
703         }  
704         if (c == '\n') {
705           break;
706         }
707       }
708       break;
709     case '\\':
710       if (jas_stream_peekc(in) == '\n') {
711         jas_stream_getc(in);
712       }
713       break;
714     default:
715       done = 1;
716       break;
717     }
718   } while (!done);
719
720   return c;
721 }
722
723 /******************************************************************************\
724 * Miscellaneous functions.
725 \******************************************************************************/
726
727 static mif_hdr_t *mif_makehdrfromimage(jas_image_t *image)
728 {
729   mif_hdr_t *hdr;
730   int cmptno;
731   mif_cmpt_t *cmpt;
732
733   if (!(hdr = mif_hdr_create(jas_image_numcmpts(image)))) {
734     return 0;
735   }
736   hdr->magic = MIF_MAGIC;
737   hdr->numcmpts = jas_image_numcmpts(image);
738   for (cmptno = 0; cmptno < hdr->numcmpts; ++cmptno) {
739     hdr->cmpts[cmptno] = jas_malloc(sizeof(mif_cmpt_t));
740     cmpt = hdr->cmpts[cmptno];
741     cmpt->tlx = jas_image_cmpttlx(image, cmptno);
742     cmpt->tly = jas_image_cmpttly(image, cmptno);
743     cmpt->width = jas_image_cmptwidth(image, cmptno);
744     cmpt->height = jas_image_cmptheight(image, cmptno);
745     cmpt->sampperx = jas_image_cmpthstep(image, cmptno);
746     cmpt->samppery = jas_image_cmptvstep(image, cmptno);
747     cmpt->prec = jas_image_cmptprec(image, cmptno);
748     cmpt->sgnd = jas_image_cmptsgnd(image, cmptno);
749     cmpt->data = 0;
750   }
751   return hdr;
752 }