OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [MW_0_8_9PRE7/] [mw/] [src/] [engine/] [devimage.c] - Blame information for rev 673

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
#define FASTJPEG        1       /* =1 for temp quick jpeg 8bpp display */
2
#define HAVE_MMAP       1       /* =1 to use mmap if available         */
3
 
4
#if defined(HAVE_FILEIO)        /* temp for entire file*/
5
 
6
/*
7
 * Copyright (c) 2000, 2001 Greg Haerr <greg@censoft.com>
8
 * Portions Copyright (c) 2000 Martin Jolicoeur <martinj@visuaide.com>
9
 * Portions Copyright (c) 2000 Alex Holden <alex@linuxhacker.org>
10
 * Portions Copyright (c) Independant JPEG group (ijg)
11
 *
12
 * Image load/cache/resize/display routines
13
 *
14
 * GIF, BMP, JPEG, PPM, PGM, PBM, PNG, and XPM formats are supported.
15
 * JHC:  Instead of working with a file, we work with a buffer
16
 *       (either provided by the user or through mmap).  This
17
 *       improves speed, and provides a mechanism by which the
18
 *       client can send image data directly to the engine
19
 */
20
 
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <unistd.h>
25
#include <fcntl.h>
26
#include <ctype.h>
27
#include <sys/types.h>
28
#include <sys/stat.h>
29
 
30
#ifdef HAVE_MMAP
31
#include <sys/mman.h>
32
#endif
33
 
34
#include "device.h"
35
#include "swap.h"
36
 
37
/* cached image list*/
38
typedef struct {
39
        MWLIST          link;           /* link list*/
40
        int             id;             /* image id*/
41
        PMWIMAGEHDR     pimage;         /* image data*/
42
        PSD             psd;            /* FIXME shouldn't need this*/
43
} IMAGEITEM, *PIMAGEITEM;
44
 
45
static MWLISTHEAD imagehead;            /* global image list*/
46
static int nextimageid = 1;
47
 
48
typedef struct {  /* structure for reading images from buffer   */
49
  void *start;    /* The pointer to the beginning of the buffer */
50
  int offset;     /* The current offset within the buffer       */
51
  int size;       /* The total size of the buffer               */
52
} buffer_t;
53
 
54
 
55
static void ComputePitch(int bpp, int width, int *pitch, int *bytesperpixel);
56
#if defined(HAVE_BMP_SUPPORT)
57
static int  LoadBMP(buffer_t *src, PMWIMAGEHDR pimage);
58
#endif
59
#if defined(HAVE_JPEG_SUPPORT)
60
static int  LoadJPEG(buffer_t *src, PMWIMAGEHDR pimage, PSD psd,
61
                MWBOOL fast_grayscale);
62
#endif
63
#if defined(HAVE_PNG_SUPPORT)
64
static int  LoadPNG(buffer_t *src, PMWIMAGEHDR pimage);
65
#endif
66
#if defined(HAVE_GIF_SUPPORT)
67
static int  LoadGIF(buffer_t *src, PMWIMAGEHDR pimage);
68
#endif
69
#if defined(HAVE_PNM_SUPPORT)
70
static int LoadPNM(buffer_t *src, PMWIMAGEHDR pimage);
71
#endif
72
#if defined(HAVE_XPM_SUPPORT)
73
static int LoadXPM(buffer_t *src, PMWIMAGEHDR pimage, PSD psd) ;
74
#endif
75
 
76
/*
77
 * Buffered input functions to replace stdio functions
78
 */
79
static void
80
binit(void *in, int size, buffer_t *dest)
81
{
82
        dest->start = in;
83
        dest->offset = 0;
84
        dest->size = size;
85
}
86
 
87
static int
88
bseek(buffer_t *buffer, int offset, int whence)
89
{
90
        int new;
91
 
92
        switch(whence) {
93
        case SEEK_SET:
94
                if (offset >= buffer->size || offset < 0)
95
                        return(-1);
96
                buffer->offset = offset;
97
                return(0);
98
 
99
        case SEEK_CUR:
100
                new = buffer->offset + offset;
101
                if (new >= buffer->size || new < 0)
102
                        return(-1);
103
                buffer->offset = new;
104
                return(0);
105
 
106
        case SEEK_END:
107
                if (offset >= buffer->size || offset > 0)
108
                        return(-1);
109
                buffer->offset = (buffer->size - 1) - offset;
110
                return(0);
111
 
112
        default:
113
                return(-1);
114
        }
115
}
116
 
117
static int
118
bread(buffer_t *buffer, void *dest, int size)
119
{
120
        int copysize = size;
121
 
122
        if (buffer->offset == buffer->size)
123
                return(0);
124
 
125
        if (buffer->offset + size > buffer->size)
126
                copysize = (buffer->size - buffer->offset);
127
 
128
        memcpy((void *)dest, (void *)(buffer->start + buffer->offset),copysize);
129
 
130
        buffer->offset += copysize;
131
        return(copysize);
132
}
133
 
134
static int
135
bgetc(buffer_t *buffer)
136
{
137
        int ch;
138
 
139
        if (buffer->offset == buffer->size)
140
                return(EOF);
141
 
142
        ch = *((unsigned char *) (buffer->start + buffer->offset));
143
        buffer->offset++;
144
        return(ch);
145
}
146
 
147
static char *
148
bgets(buffer_t *buffer, char *dest, int size)
149
{
150
        int i,o;
151
        int copysize = size - 1;
152
 
153
        if (buffer->offset == buffer->size)
154
                return(0);
155
 
156
        if (buffer->offset + copysize > buffer->size)
157
                copysize = buffer->size - buffer->offset;
158
 
159
        for(o=0, i=buffer->offset; i < buffer->offset + copysize; i++, o++) {
160
                dest[o] = *((char *) (buffer->start + i));
161
                if (dest[o] == '\n')
162
                        break;
163
        }
164
 
165
        buffer->offset = i + 1;
166
        dest[o + 1] = 0;
167
 
168
        return(dest);
169
}
170
 
171
static int
172
beof(buffer_t *buffer)
173
{
174
        return (buffer->offset == buffer->size);
175
}
176
 
177
/*
178
 * Image decoding and display
179
 * NOTE: This routine and APIs will change in subsequent releases.
180
 *
181
 * Decodes and loads a graphics file, then resizes to width/height,
182
 * then displays image at x, y
183
 * If width/height == -1, don't resize, use image size.
184
 * Clipping is not currently supported, just stretch/shrink to fit.
185
 *
186
 */
187
 
188
static int GdDecodeImage(PSD psd, buffer_t *src, int flags);
189
 
190
int
191
GdLoadImageFromBuffer(PSD psd, void *buffer, int size, int flags)
192
{
193
        buffer_t src;
194
        binit(buffer, size, &src);
195
 
196
        return(GdDecodeImage(psd, &src, flags));
197
}
198
 
199
void
200
GdDrawImageFromBuffer(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width,
201
        MWCOORD height, void *buffer, int size, int flags)
202
{
203
        int id;
204
        buffer_t src;
205
 
206
        binit(buffer, size, &src);
207
        id = GdDecodeImage(psd, &src, flags);
208
 
209
        if (id) {
210
                GdDrawImageToFit(psd, x, y, width, height, id);
211
                GdFreeImage(id);
212
        }
213
}
214
 
215
void
216
GdDrawImageFromFile(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width,
217
        MWCOORD height, char *path, int flags)
218
{
219
        int     id;
220
 
221
        id = GdLoadImageFromFile(psd, path, flags);
222
        if (id) {
223
                GdDrawImageToFit(psd, x, y, width, height, id);
224
                GdFreeImage(id);
225
        }
226
}
227
 
228
int
229
GdLoadImageFromFile(PSD psd, char *path, int flags)
230
{
231
  int fd, id;
232
  struct stat s;
233
  void *buffer = 0;
234
  buffer_t src;
235
 
236
  fd = open(path, O_RDONLY);
237
  if (fd <= 0) {
238
    EPRINTF("GdLoadImageFromFile: can't open image: %s\n", path);
239
    return(0);
240
  }
241
 
242
  fstat(fd, &s);
243
 
244
#ifdef HAVE_MMAP
245
  buffer = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
246
 
247
  if (!buffer) {
248
    EPRINTF("GdLoadImageFromFile:  Couldn't map image %s\n", path);
249
    close(fd);
250
    return(0);
251
  }
252
#else
253
  buffer = malloc(s.st_size);
254
  if (!buffer) {
255
     EPRINTF("GdLoadImageFromFile:  Couldn't load image %s\n", path);
256
     close(fd);
257
     return(0);
258
  }
259
 
260
  if (read(fd, buffer, s.st_size) != s.st_size) {
261
    EPRINTF("GdLoadImageFromFile:  Couldn't load image %s\n", path);
262
    close(fd);
263
    return(0);
264
  }
265
#endif
266
 
267
  binit(buffer, s.st_size, &src);
268
  id = GdDecodeImage(psd, &src, flags);
269
 
270
#ifdef HAVE_MMAP
271
  munmap(buffer, s.st_size);
272
#else
273
  free(buffer);
274
#endif
275
 
276
  close(fd);
277
  return(id);
278
}
279
 
280
static int
281
GdDecodeImage(PSD psd, buffer_t * src, int flags)
282
{
283
        int         loadOK = 0;
284
        PMWIMAGEHDR pimage;
285
        PIMAGEITEM  pItem;
286
 
287
        /* allocate image struct*/
288
        pimage = (PMWIMAGEHDR)malloc(sizeof(MWIMAGEHDR));
289
        if(!pimage) {
290
                return 0;
291
        }
292
        pimage->imagebits = NULL;
293
        pimage->palette = NULL;
294
        pimage->transcolor = -1L;
295
 
296
#if defined(HAVE_BMP_SUPPORT)
297
        if (loadOK == 0)
298
                loadOK = LoadBMP(src, pimage);
299
#endif
300
#if defined(HAVE_GIF_SUPPORT)
301
        if (loadOK == 0)
302
                loadOK = LoadGIF(src, pimage);
303
#endif
304
#if defined(HAVE_JPEG_SUPPORT)
305
        if (loadOK == 0)
306
                loadOK = LoadJPEG(src, pimage, psd, flags);
307
#endif
308
#if defined(HAVE_PNG_SUPPORT)
309
        if (loadOK == 0)
310
                loadOK = LoadPNG(src, pimage);
311
#endif
312
#if defined(HAVE_PNM_SUPPORT)
313
        if(loadOK == 0)
314
                loadOK = LoadPNM(src, pimage);
315
#endif
316
#if defined(HAVE_XPM_SUPPORT)
317
        if (loadOK == 0)
318
                loadOK = LoadXPM(src, pimage, psd);
319
#endif
320
 
321
        if (loadOK == 0) {
322
                EPRINTF("GdLoadImageFromFile: unknown image type:\n");
323
          //            EPRINTF("GdLoadImageFromFile: unknown image type: \n", path);
324
                goto err;               /* image loading error*/
325
        }
326
        if (loadOK != 1)
327
                goto err;               /* image loading error*/
328
 
329
        /* allocate id*/
330
        pItem = GdItemNew(IMAGEITEM);
331
        if (!pItem)
332
                goto err;
333
        pItem->id = nextimageid++;
334
        pItem->pimage = pimage;
335
        pItem->psd = psd;
336
        GdListAdd(&imagehead, &pItem->link);
337
 
338
        return pItem->id;
339
 
340
err:
341
        free(pimage);
342
        return 0;                        /* image loading error*/
343
}
344
 
345
static PIMAGEITEM
346
findimage(int id)
347
{
348
        PMWLIST         p;
349
        PIMAGEITEM      pimagelist;
350
 
351
        for (p=imagehead.head; p; p=p->next) {
352
                pimagelist = GdItemAddr(p, IMAGEITEM, link);
353
                if (pimagelist->id == id)
354
                        return pimagelist;
355
        }
356
        return NULL;
357
}
358
 
359
void
360
GdDrawImageToFit(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
361
        int id)
362
{
363
        PIMAGEITEM      pItem;
364
        PMWIMAGEHDR     pimage;
365
 
366
        pItem = findimage(id);
367
        if (!pItem)
368
                return;
369
        pimage = pItem->pimage;
370
 
371
        /*
372
         * Display image, possibly stretch/shrink to resize
373
         */
374
        if (height < 0)
375
                height = pimage->height;
376
        if (width < 0)
377
                width = pimage->width;
378
 
379
        if (height != pimage->height || width != pimage->width) {
380
                MWCLIPRECT      rcDst;
381
                MWIMAGEHDR      image2;
382
 
383
                /* create similar image, different width/height*/
384
 
385
                image2.width = width;
386
                image2.height = height;
387
                image2.planes = pimage->planes;
388
                image2.bpp = pimage->bpp;
389
                ComputePitch(pimage->bpp, width, &image2.pitch,
390
                        &image2.bytesperpixel);
391
                image2.compression = pimage->compression;
392
                image2.palsize = pimage->palsize;
393
                image2.palette = pimage->palette;       /* already allocated*/
394
                image2.transcolor = pimage->transcolor;
395
                if( (image2.imagebits = malloc(image2.pitch*height)) == NULL) {
396
                        EPRINTF("GdDrawImageToFit: no memory\n");
397
                        return;
398
                }
399
 
400
                rcDst.x = 0;
401
                rcDst.y = 0;
402
                rcDst.width = width;
403
                rcDst.height = height;
404
 
405
                /* Stretch full soruce to destination rectangle*/
406
                GdStretchImage(pimage, NULL, &image2, &rcDst);
407
                GdDrawImage(psd, x, y, &image2);
408
                free(image2.imagebits);
409
        } else
410
                GdDrawImage(psd, x, y, pimage);
411
}
412
 
413
void
414
GdFreeImage(int id)
415
{
416
        PIMAGEITEM      pItem;
417
        PMWIMAGEHDR     pimage;
418
 
419
        pItem = findimage(id);
420
        if (pItem) {
421
                GdListRemove(&imagehead, &pItem->link);
422
                pimage = pItem->pimage;
423
 
424
                /* delete image bits*/
425
                if(pimage->imagebits)
426
                        free(pimage->imagebits);
427
                if(pimage->palette)
428
                        free(pimage->palette);
429
 
430
                free(pimage);
431
                GdItemFree(pItem);
432
        }
433
}
434
 
435
MWBOOL
436
GdGetImageInfo(int id, PMWIMAGEINFO pii)
437
{
438
        PMWIMAGEHDR     pimage;
439
        PIMAGEITEM      pItem;
440
        int             i;
441
 
442
        pItem = findimage(id);
443
        if (!pItem) {
444
                memset(pii, 0, sizeof(*pii));
445
                return FALSE;
446
        }
447
        pimage = pItem->pimage;
448
        pii->id = id;
449
        pii->width = pimage->width;
450
        pii->height = pimage->height;
451
        pii->planes = pimage->planes;
452
        pii->bpp = pimage->bpp;
453
        pii->pitch = pimage->pitch;
454
        pii->bytesperpixel = pimage->bytesperpixel;
455
        pii->compression = pimage->compression;
456
        pii->palsize = pimage->palsize;
457
        if (pimage->palsize) {
458
                if (pimage->palette) {
459
                        for (i=0; i<pimage->palsize; ++i)
460
                                pii->palette[i] = pimage->palette[i];
461
                } else {
462
                        /* FIXME handle jpeg's without palette*/
463
                        GdGetPalette(pItem->psd, 0, pimage->palsize,
464
                                pii->palette);
465
                }
466
        }
467
        return TRUE;
468
}
469
 
470
#define PIX2BYTES(n)    (((n)+7)/8)
471
/*
472
 * compute image line size and bytes per pixel
473
 * from bits per pixel and width
474
 */
475
static void
476
ComputePitch(int bpp, int width, int *pitch, int *bytesperpixel)
477
{
478
        int     linesize;
479
        int     bytespp = 1;
480
 
481
        if(bpp == 1)
482
                linesize = PIX2BYTES(width);
483
        else if(bpp <= 4)
484
                linesize = PIX2BYTES(width<<2);
485
        else if(bpp <= 8)
486
                linesize = width;
487
        else if(bpp <= 16) {
488
                linesize = width * 2;
489
                bytespp = 2;
490
        } else if(bpp <= 24) {
491
                linesize = width * 3;
492
                bytespp = 3;
493
        } else {
494
                linesize = width * 4;
495
                bytespp = 4;
496
        }
497
 
498
        /* rows are DWORD right aligned*/
499
        *pitch = (linesize + 3) & ~3;
500
        *bytesperpixel = bytespp;
501
}
502
 
503
/*
504
 * StretchImage - Resize an image
505
 *
506
 * Major portions from SDL Simple DirectMedia Layer by Sam Lantinga
507
 * Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga <slouken@devolution.com>
508
 * This a stretch blit implementation based on ideas given to me by
509
 *  Tomasz Cejner - thanks! :)
510
 */
511
/*
512
    This library is free software; you can redistribute it and/or
513
    modify it under the terms of the GNU Library General Public
514
    License as published by the Free Software Foundation; either
515
    version 2 of the License, or (at your option) any later version.
516
 
517
    This library is distributed in the hope that it will be useful,
518
    but WITHOUT ANY WARRANTY; without even the implied warranty of
519
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
520
    Library General Public License for more details.
521
 
522
    You should have received a copy of the GNU Library General Public
523
    License along with this library; if not, write to the Free
524
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
525
*/
526
 
527
#define DEFINE_COPY_ROW(name, type)                                     \
528
static void name(type *src, int src_w, type *dst, int dst_w)            \
529
{                                                                       \
530
        int i;                                                          \
531
        int pos, inc;                                                   \
532
        type pixel = 0;                                                  \
533
                                                                        \
534
        pos = 0x10000;                                                  \
535
        inc = (src_w << 16) / dst_w;                                    \
536
        for ( i=dst_w; i>0; --i ) {                                      \
537
                while ( pos >= 0x10000L ) {                             \
538
                        pixel = *src++;                                 \
539
                        pos -= 0x10000L;                                \
540
                }                                                       \
541
                *dst++ = pixel;                                         \
542
                pos += inc;                                             \
543
        }                                                               \
544
}
545
 
546
DEFINE_COPY_ROW(copy_row1, unsigned char)
547
DEFINE_COPY_ROW(copy_row2, unsigned short)
548
DEFINE_COPY_ROW(copy_row4, unsigned long)
549
 
550
static void copy_row3(unsigned char *src, int src_w, unsigned char *dst,
551
        int dst_w)
552
{
553
        int i;
554
        int pos, inc;
555
        unsigned char r = 0;
556
        unsigned char g = 0;
557
        unsigned char b = 0;
558
 
559
        pos = 0x10000;
560
        inc = (src_w << 16) / dst_w;
561
        for ( i=dst_w; i>0; --i ) {
562
                while ( pos >= 0x10000L ) {
563
                        b = *src++;
564
                        g = *src++;
565
                        r = *src++;
566
                        pos -= 0x10000L;
567
                }
568
                *dst++ = b;
569
                *dst++ = g;
570
                *dst++ = r;
571
                pos += inc;
572
        }
573
}
574
 
575
/* Perform a stretch blit between two image structs of the same format.*/
576
void
577
GdStretchImage(PMWIMAGEHDR src, MWCLIPRECT *srcrect, PMWIMAGEHDR dst,
578
        MWCLIPRECT *dstrect)
579
{
580
        int pos, inc;
581
        int bytesperpixel;
582
        int dst_maxrow;
583
        int src_row, dst_row;
584
        MWUCHAR *srcp = 0;
585
        MWUCHAR *dstp;
586
        MWCLIPRECT full_src;
587
        MWCLIPRECT full_dst;
588
 
589
        if ( src->bytesperpixel != dst->bytesperpixel ) {
590
                EPRINTF("GdStretchImage: bytesperpixel mismatch\n");
591
                return;
592
        }
593
 
594
        /* Verify the blit rectangles */
595
        if ( srcrect ) {
596
                if ( (srcrect->x < 0) || (srcrect->y < 0) ||
597
                     ((srcrect->x+srcrect->width) > src->width) ||
598
                     ((srcrect->y+srcrect->height) > src->height) ) {
599
                        EPRINTF("GdStretchImage: invalid source rect\n");
600
                        return;
601
                }
602
        } else {
603
                full_src.x = 0;
604
                full_src.y = 0;
605
                full_src.width = src->width;
606
                full_src.height = src->height;
607
                srcrect = &full_src;
608
        }
609
        if ( dstrect ) {
610
                /* if stretching to nothing, return*/
611
                if (!dstrect->width || !dstrect->height)
612
                        return;
613
                if ( (dstrect->x < 0) || (dstrect->y < 0) ||
614
                     ((dstrect->x+dstrect->width) > dst->width) ||
615
                     ((dstrect->y+dstrect->height) > dst->height) ) {
616
                        EPRINTF("GdStretchImage: invalid dest rect\n");
617
                        return;
618
                }
619
        } else {
620
                full_dst.x = 0;
621
                full_dst.y = 0;
622
                full_dst.width = dst->width;
623
                full_dst.height = dst->height;
624
                dstrect = &full_dst;
625
        }
626
 
627
        /* Set up the data... */
628
        pos = 0x10000;
629
        inc = (srcrect->height << 16) / dstrect->height;
630
        src_row = srcrect->y;
631
        dst_row = dstrect->y;
632
        bytesperpixel = dst->bytesperpixel;
633
 
634
        /* Perform the stretch blit */
635
        for ( dst_maxrow = dst_row+dstrect->height; dst_row<dst_maxrow;
636
                                                                ++dst_row ) {
637
                dstp = (MWUCHAR *)dst->imagebits + (dst_row*dst->pitch)
638
                                    + (dstrect->x*bytesperpixel);
639
                while ( pos >= 0x10000L ) {
640
                        srcp = (MWUCHAR *)src->imagebits + (src_row*src->pitch)
641
                                    + (srcrect->x*bytesperpixel);
642
                        ++src_row;
643
                        pos -= 0x10000L;
644
                }
645
 
646
                switch (bytesperpixel) {
647
                case 1:
648
                        copy_row1(srcp, srcrect->width, dstp, dstrect->width);
649
                        break;
650
                case 2:
651
                        copy_row2((unsigned short *)srcp, srcrect->width,
652
                                (unsigned short *)dstp, dstrect->width);
653
                        break;
654
                case 3:
655
                        copy_row3(srcp, srcrect->width, dstp, dstrect->width);
656
                        break;
657
                case 4:
658
                        copy_row4((unsigned long *)srcp, srcrect->width,
659
                                (unsigned long *)dstp, dstrect->width);
660
                        break;
661
                }
662
 
663
                pos += inc;
664
        }
665
}
666
 
667
#if defined(HAVE_FILEIO) && defined(HAVE_JPEG_SUPPORT)
668
#include "jpeglib.h"
669
/*
670
 * JPEG decompression routine
671
 *
672
 * JPEG support must be enabled (see README.txt in contrib/jpeg)
673
 *
674
 * SOME FINE POINTS: (from libjpeg)
675
 * In the below code, we ignored the return value of jpeg_read_scanlines,
676
 * which is the number of scanlines actually read.  We could get away with
677
 * this because we asked for only one line at a time and we weren't using
678
 * a suspending data source.  See libjpeg.doc for more info.
679
 *
680
 * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
681
 * we should have done it beforehand to ensure that the space would be
682
 * counted against the JPEG max_memory setting.  In some systems the above
683
 * code would risk an out-of-memory error.  However, in general we don't
684
 * know the output image dimensions before jpeg_start_decompress(), unless we
685
 * call jpeg_calc_output_dimensions().  See libjpeg.doc for more about this.
686
 *
687
 * Scanlines are returned in the same order as they appear in the JPEG file,
688
 * which is standardly top-to-bottom.  If you must emit data bottom-to-top,
689
 * you can use one of the virtual arrays provided by the JPEG memory manager
690
 * to invert the data.  See wrbmp.c for an example.
691
 *
692
 * As with compression, some operating modes may require temporary files.
693
 * On some systems you may need to set up a signal handler to ensure that
694
 * temporary files are deleted if the program is interrupted.  See libjpeg.doc.
695
 */
696
static int
697
LoadJPEG(buffer_t *src, PMWIMAGEHDR pimage, PSD psd, MWBOOL fast_grayscale)
698
{
699
  int   i;
700
  int   ret = 2;        /* image load error*/
701
  unsigned char magic[4];
702
 
703
#if FASTJPEG
704
  extern MWPALENTRY mwstdpal8[256];
705
#else
706
  MWPALENTRY palette[256];
707
#endif
708
 
709
  struct jpeg_source_mgr smgr;
710
  struct jpeg_decompress_struct cinfo;
711
  struct jpeg_error_mgr jerr;
712
 
713
  static void init_source(j_compress_ptr dinfo) {
714
    smgr.next_input_byte = src->start;
715
    smgr.bytes_in_buffer = src->size;
716
  }
717
 
718
  static void fill_input_buffer(j_compress_ptr dinfo) {
719
    return;
720
  }
721
 
722
  static void skip_input_data(j_compress_ptr dinfo, int num_bytes) {
723
    if (num_bytes >= src->size) return;
724
    smgr.next_input_byte += num_bytes;
725
    smgr.bytes_in_buffer -= num_bytes;
726
  }
727
 
728
  static int resync_to_restart(j_compress_ptr dinfo, int desired ) {
729
    return(jpeg_resync_to_restart(dinfo, desired));
730
  }
731
 
732
  static void term_source(j_compress_ptr dinfo) {
733
    return;
734
  }
735
 
736
  /* first determine if JPEG file since decoder will error if not*/
737
  bseek(src, 0, SEEK_SET);
738
 
739
  if (!bread(src, magic, 2))
740
    return(0);
741
 
742
  if (magic[0] != 0xFF || magic[1] != 0xD8)
743
    return(0);           /* not JPEG image*/
744
 
745
 
746
  bread(src, magic, 4);
747
  bread(src, magic, 4);
748
 
749
  if (strncmp(magic, "JFIF", 4) != 0)
750
    return(0);           /* not JPEG image*/
751
 
752
  bread(src, 0, SEEK_SET);
753
  pimage->imagebits = NULL;
754
  pimage->palette = NULL;
755
 
756
  /* Step 1: allocate and initialize JPEG decompression object */
757
 
758
  /* We set up the normal JPEG error routines. */
759
  cinfo.err = jpeg_std_error (&jerr);
760
 
761
  /* Now we can initialize the JPEG decompression object. */
762
  jpeg_create_decompress (&cinfo);
763
 
764
 
765
  /* Step 2:  Setup the source manager */
766
 
767
  smgr.init_source = init_source;
768
  smgr.fill_input_buffer = fill_input_buffer;
769
  smgr.skip_input_data = skip_input_data;
770
  smgr.resync_to_restart = resync_to_restart;
771
  smgr.term_source = term_source;
772
 
773
  cinfo.src = &smgr;
774
 
775
  /* Step 2: specify data source (eg, a file) */
776
  /* jpeg_stdio_src (&cinfo, fp); */
777
 
778
  /* Step 3: read file parameters with jpeg_read_header() */
779
  jpeg_read_header (&cinfo, TRUE);
780
 
781
        /* Step 4: set parameters for decompression */
782
        cinfo.out_color_space = fast_grayscale? JCS_GRAYSCALE: JCS_RGB;
783
        cinfo.quantize_colors = FALSE;
784
 
785
#if FASTJPEG
786
        goto fastjpeg;
787
#endif
788
        if (!fast_grayscale)
789
        {
790
                if (psd->pixtype == MWPF_PALETTE)
791
                {
792
fastjpeg:
793
                        cinfo.quantize_colors = TRUE;
794
 
795
#if FASTJPEG
796
                        cinfo.actual_number_of_colors = 256;
797
#else
798
                        /* Get system palette */
799
                        cinfo.actual_number_of_colors =
800
                                GdGetPalette(psd, 0, psd->ncolors, palette);
801
#endif
802
 
803
                        /* Allocate jpeg colormap space */
804
                        cinfo.colormap = (*cinfo.mem->alloc_sarray)
805
                                ((j_common_ptr) &cinfo, JPOOL_IMAGE,
806
                                (JDIMENSION)cinfo.actual_number_of_colors,
807
                                (JDIMENSION)3);
808
 
809
                        /* Set colormap from system palette */
810
                        for(i = 0; i < cinfo.actual_number_of_colors; ++i)
811
                        {
812
#if FASTJPEG
813
                                cinfo.colormap[0][i] = mwstdpal8[i].r;
814
                                cinfo.colormap[1][i] = mwstdpal8[i].g;
815
                                cinfo.colormap[2][i] = mwstdpal8[i].b;
816
#else
817
                                cinfo.colormap[0][i] = palette[i].r;
818
                                cinfo.colormap[1][i] = palette[i].g;
819
                                cinfo.colormap[2][i] = palette[i].b;
820
#endif
821
                        }
822
                }
823
        }
824
        else
825
        {
826
                /* Grayscale output asked */
827
                cinfo.quantize_colors = TRUE;
828
                cinfo.out_color_space = JCS_GRAYSCALE;
829
                cinfo.desired_number_of_colors = psd->ncolors;
830
        }
831
        jpeg_calc_output_dimensions(&cinfo);
832
 
833
        pimage->width = cinfo.output_width;
834
        pimage->height = cinfo.output_height;
835
        pimage->planes = 1;
836
#if FASTJPEG
837
        pimage->bpp = 8;
838
#else
839
        pimage->bpp = (fast_grayscale || psd->pixtype == MWPF_PALETTE)?
840
                8: cinfo.output_components*8;
841
#endif
842
        ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
843
                &pimage->bytesperpixel);
844
        pimage->compression = MWIMAGE_RGB;      /* RGB not BGR order*/
845
        pimage->palsize = (pimage->bpp == 8)? 256: 0;
846
        pimage->imagebits = malloc(pimage->pitch * pimage->height);
847
        if(!pimage->imagebits)
848
                goto err;
849
        pimage->palette = NULL;
850
#if FASTJPEG
851
        if(pimage->bpp == 8) {
852
                pimage->palette = malloc(256*sizeof(MWPALENTRY));
853
                if(!pimage->palette)
854
                        goto err;
855
                for (i=0; i<256; ++i)
856
                        pimage->palette[i] = mwstdpal8[i];
857
        }
858
#endif
859
 
860
        /* Step 5: Start decompressor */
861
        jpeg_start_decompress (&cinfo);
862
 
863
        /* Step 6: while (scan lines remain to be read) */
864
        while(cinfo.output_scanline < cinfo.output_height) {
865
                JSAMPROW rowptr[1];
866
                rowptr[0] = (JSAMPROW)(pimage->imagebits +
867
                        cinfo.output_scanline * pimage->pitch);
868
                jpeg_read_scanlines (&cinfo, rowptr, 1);
869
        }
870
        ret = 1;
871
 
872
err:
873
        /* Step 7: Finish decompression */
874
        jpeg_finish_decompress (&cinfo);
875
 
876
        /* Step 8: Release JPEG decompression object */
877
        jpeg_destroy_decompress (&cinfo);
878
 
879
        /* May want to check to see whether any corrupt-data
880
         * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
881
         */
882
        return ret;
883
}
884
#endif /* defined(HAVE_FILEIO) && defined(HAVE_JPEG_SUPPORT)*/
885
 
886
#if defined(HAVE_FILEIO) && defined(HAVE_PNG_SUPPORT)
887
#include "png.h"
888
/* png_jmpbuf() macro is not defined prior to libpng-1.0.6*/
889
#ifndef png_jmpbuf
890
#define png_jmpbuf(png_ptr)     ((png_ptr)->jmpbuf)
891
#endif
892
/*
893
 * Load a PNG file.
894
 * Currently for simplicity we get the PNG library to convert the file to
895
 * 24 bit RGB format with no alpha channel information even if we could
896
 * potentially store the image more efficiently by taking note of the image
897
 * type and depth and acting accordingly. Similarly, > 8 bits per channel,
898
 * gamma correction, etc. are not supported.
899
 */
900
static int
901
LoadPNG(buffer_t * src, PMWIMAGEHDR pimage)
902
{
903
        unsigned char hdr[8], **rows;
904
        png_structp state;
905
        png_infop pnginfo;
906
        png_uint_32 width, height;
907
        int bit_depth, colourtype, i;
908
 
909
        bseek(src, 0L, 0);
910
 
911
        if(bread(src, hdr, 8) != 8) return 0;
912
 
913
        if(png_sig_cmp(hdr, 0, 8)) return 0;
914
 
915
        if(!(state = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
916
                                                NULL, NULL))) goto nomem;
917
 
918
        if(!(pnginfo = png_create_info_struct(state))) {
919
                png_destroy_read_struct(&state, NULL, NULL);
920
                goto nomem;
921
        }
922
 
923
        if(setjmp(png_jmpbuf(state))) {
924
                png_destroy_read_struct(&state, &pnginfo, NULL);
925
                return 2;
926
        }
927
 
928
        png_init_io(state, fp);
929
        png_set_sig_bytes(state, 8);
930
        png_read_info(state, pnginfo);
931
        png_get_IHDR(state, pnginfo, &width, &height, &bit_depth, &colourtype,
932
                                                        NULL, NULL, NULL);
933
 
934
        pimage->width = width;
935
        pimage->height = height;
936
        pimage->bpp = 24;
937
        pimage->planes = 1;
938
        ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
939
                                                &pimage->bytesperpixel);
940
        pimage->compression = MWIMAGE_RGB;
941
        if(!(pimage->imagebits = malloc(pimage->pitch * pimage->height))) {
942
                png_destroy_read_struct(&state, &pnginfo, NULL);
943
                goto nomem;
944
        }
945
        if(!(rows = malloc(pimage->height * sizeof(unsigned char *)))) {
946
                png_destroy_read_struct(&state, &pnginfo, NULL);
947
                goto nomem;
948
        }
949
        for(i = 0; i < pimage->height; i++)
950
                rows[i] = pimage->imagebits + (i * pimage->pitch);
951
 
952
        png_set_expand(state);
953
        if(bit_depth == 16)
954
                png_set_strip_16(state);
955
        if(colourtype & PNG_COLOR_MASK_ALPHA)
956
                png_set_strip_alpha(state);
957
        if(colourtype == PNG_COLOR_TYPE_GRAY ||
958
                        colourtype == PNG_COLOR_TYPE_GRAY_ALPHA)
959
                png_set_gray_to_rgb(state);
960
 
961
        png_read_image(state, rows);
962
 
963
        png_read_end(state, NULL);
964
        free(rows);
965
        png_destroy_read_struct(&state, &pnginfo, NULL);
966
 
967
        return 1;
968
 
969
nomem:
970
        EPRINTF("LoadPNG: Out of memory\n");
971
        return 2;
972
}
973
#endif /* defined(HAVE_FILEIO) && defined(HAVE_PNG_SUPPORT)*/
974
 
975
#if defined(HAVE_FILEIO) && defined(HAVE_BMP_SUPPORT)
976
/* BMP stuff*/
977
#define BI_RGB          0L
978
#define BI_RLE8         1L
979
#define BI_RLE4         2L
980
#define BI_BITFIELDS    3L
981
 
982
typedef unsigned char   BYTE;
983
typedef unsigned short  WORD;
984
typedef unsigned long   DWORD;
985
typedef long            LONG;
986
 
987
typedef struct {
988
        /* BITMAPFILEHEADER*/
989
        BYTE    bfType[2];
990
        DWORD   bfSize;
991
        WORD    bfReserved1;
992
        WORD    bfReserved2;
993
        DWORD   bfOffBits;
994
} BMPFILEHEAD;
995
 
996
#define FILEHEADSIZE 14
997
 
998
/* windows style*/
999
typedef struct {
1000
        /* BITMAPINFOHEADER*/
1001
        DWORD   BiSize;
1002
        DWORD   BiWidth;
1003
        DWORD   BiHeight;
1004
        WORD    BiPlanes;
1005
        WORD    BiBitCount;
1006
        DWORD   BiCompression;
1007
        DWORD   BiSizeImage;
1008
        DWORD   BiXpelsPerMeter;
1009
        DWORD   BiYpelsPerMeter;
1010
        DWORD   BiClrUsed;
1011
        DWORD   BiClrImportant;
1012
} BMPINFOHEAD;
1013
 
1014
#define INFOHEADSIZE 40
1015
 
1016
/* os/2 style*/
1017
typedef struct {
1018
        /* BITMAPCOREHEADER*/
1019
        DWORD   bcSize;
1020
        WORD    bcWidth;
1021
        WORD    bcHeight;
1022
        WORD    bcPlanes;
1023
        WORD    bcBitCount;
1024
} BMPCOREHEAD;
1025
 
1026
#define COREHEADSIZE 12
1027
 
1028
static int      DecodeRLE8(MWUCHAR *buf, buffer_t *src);
1029
static int      DecodeRLE4(MWUCHAR *buf, buffer_t *src);
1030
static void     put4(int b);
1031
 
1032
/*
1033
 * BMP decoding routine
1034
 */
1035
 
1036
/* Changed by JHC to allow a buffer instead of a filename */
1037
 
1038
static int
1039
LoadBMP(buffer_t *src, PMWIMAGEHDR pimage)
1040
{
1041
        int             h, i, compression;
1042
        int             headsize;
1043
        MWUCHAR         *imagebits;
1044
        BMPFILEHEAD     bmpf;
1045
        BMPINFOHEAD     bmpi;
1046
        BMPCOREHEAD     bmpc;
1047
        MWUCHAR         headbuffer[INFOHEADSIZE];
1048
 
1049
        bseek(src, 0, SEEK_SET);
1050
 
1051
        pimage->imagebits = NULL;
1052
        pimage->palette = NULL;
1053
 
1054
        /* read BMP file header*/
1055
        if (bread(src, &headbuffer, FILEHEADSIZE) != FILEHEADSIZE)
1056
          return(0);
1057
 
1058
        bmpf.bfType[0] = headbuffer[0];
1059
        bmpf.bfType[1] = headbuffer[1];
1060
 
1061
        /* Is it really a bmp file ? */
1062
        if (*(WORD*)&bmpf.bfType[0] != wswap(0x4D42)) /* 'BM' */
1063
                return 0;        /* not bmp image*/
1064
 
1065
        /*bmpf.bfSize = dwswap(dwread(&headbuffer[2]));*/
1066
        bmpf.bfOffBits = dwswap(dwread(&headbuffer[10]));
1067
 
1068
        /* Read remaining header size */
1069
        if (bread(src,&headsize,sizeof(DWORD)) != sizeof(DWORD))
1070
                return 0;        /* not bmp image*/
1071
        headsize = dwswap(headsize);
1072
 
1073
        /* might be windows or os/2 header */
1074
        if(headsize == COREHEADSIZE) {
1075
 
1076
                /* read os/2 header */
1077
                if(bread(src, &headbuffer, COREHEADSIZE-sizeof(DWORD)) !=
1078
                        COREHEADSIZE-sizeof(DWORD))
1079
                                return 0;        /* not bmp image*/
1080
 
1081
                /* Get data */
1082
                bmpc.bcWidth = wswap(*(WORD*)&headbuffer[0]);
1083
                bmpc.bcHeight = wswap(*(WORD*)&headbuffer[2]);
1084
                bmpc.bcPlanes = wswap(*(WORD*)&headbuffer[4]);
1085
                bmpc.bcBitCount = wswap(*(WORD*)&headbuffer[6]);
1086
 
1087
                pimage->width = (int)bmpc.bcWidth;
1088
                pimage->height = (int)bmpc.bcHeight;
1089
                pimage->bpp = bmpc.bcBitCount;
1090
                if (pimage->bpp <= 8)
1091
                        pimage->palsize = 1 << pimage->bpp;
1092
                else pimage->palsize = 0;
1093
                compression = BI_RGB;
1094
        } else {
1095
                /* read windows header */
1096
                if(bread(src, &headbuffer, INFOHEADSIZE-sizeof(DWORD)) !=
1097
                        INFOHEADSIZE-sizeof(DWORD))
1098
                                return 0;        /* not bmp image*/
1099
 
1100
                /* Get data */
1101
                bmpi.BiWidth = dwswap(*(DWORD*)&headbuffer[0]);
1102
                bmpi.BiHeight = dwswap(*(DWORD*)&headbuffer[4]);
1103
                bmpi.BiPlanes = wswap(*(WORD*)&headbuffer[8]);
1104
                bmpi.BiBitCount = wswap(*(WORD*)&headbuffer[10]);
1105
                bmpi.BiCompression = dwswap(*(DWORD*)&headbuffer[12]);
1106
                bmpi.BiSizeImage = dwswap(*(DWORD*)&headbuffer[16]);
1107
                bmpi.BiXpelsPerMeter = dwswap(*(DWORD*)&headbuffer[20]);
1108
                bmpi.BiYpelsPerMeter = dwswap(*(DWORD*)&headbuffer[24]);
1109
                bmpi.BiClrUsed = dwswap(*(DWORD*)&headbuffer[28]);
1110
                bmpi.BiClrImportant = dwswap(*(DWORD*)&headbuffer[32]);
1111
 
1112
                pimage->width = (int)bmpi.BiWidth;
1113
                pimage->height = (int)bmpi.BiHeight;
1114
                pimage->bpp = bmpi.BiBitCount;
1115
                pimage->palsize = (int)bmpi.BiClrUsed;
1116
                if (pimage->palsize > 256)
1117
                        pimage->palsize = 0;
1118
                else if(pimage->palsize == 0 && pimage->bpp <= 8)
1119
                        pimage->palsize = 1 << pimage->bpp;
1120
                compression = bmpi.BiCompression;
1121
        }
1122
        pimage->compression = MWIMAGE_BGR;      /* right side up, BGR order*/
1123
        pimage->planes = 1;
1124
 
1125
        /* currently only 1, 4, 8 and 24 bpp bitmaps*/
1126
        if(pimage->bpp > 8 && pimage->bpp != 24) {
1127
                EPRINTF("LoadBMP: image bpp not 1, 4, 8 or 24\n");
1128
                return 2;       /* image loading error*/
1129
        }
1130
 
1131
        /* compute byte line size and bytes per pixel*/
1132
        ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
1133
                &pimage->bytesperpixel);
1134
 
1135
        /* Allocate image */
1136
        if( (pimage->imagebits = malloc(pimage->pitch*pimage->height)) == NULL)
1137
                goto err;
1138
        if( (pimage->palette = malloc(256*sizeof(MWPALENTRY))) == NULL)
1139
                goto err;
1140
 
1141
        /* get colormap*/
1142
        if(pimage->bpp <= 8) {
1143
                for(i=0; i<pimage->palsize; i++) {
1144
                        pimage->palette[i].b = bgetc(src);
1145
                        pimage->palette[i].g = bgetc(src);
1146
                        pimage->palette[i].r = bgetc(src);
1147
                        if(headsize != COREHEADSIZE)
1148
                                bgetc(src);
1149
                }
1150
        }
1151
 
1152
        /* decode image data*/
1153
        bseek(src, bmpf.bfOffBits, SEEK_SET);
1154
 
1155
        h = pimage->height;
1156
        /* For every row ... */
1157
        while (--h >= 0) {
1158
                /* turn image rightside up*/
1159
                imagebits = pimage->imagebits + h*pimage->pitch;
1160
 
1161
                /* Get row data from file */
1162
                if(compression == BI_RLE8) {
1163
                        if(!DecodeRLE8(imagebits, src))
1164
                                break;
1165
                } else if(compression == BI_RLE4) {
1166
                        if(!DecodeRLE4(imagebits, src))
1167
                                break;
1168
                } else {
1169
                        if(bread(src, imagebits, pimage->pitch) !=
1170
                                pimage->pitch)
1171
                                        goto err;
1172
                }
1173
        }
1174
        return 1;               /* bmp image ok*/
1175
 
1176
err:
1177
        EPRINTF("LoadBMP: image loading error\n");
1178
        if(pimage->imagebits)
1179
                free(pimage->imagebits);
1180
        if(pimage->palette)
1181
                free(pimage->palette);
1182
        return 2;               /* bmp image error*/
1183
}
1184
 
1185
/*
1186
 * Decode one line of RLE8, return 0 when done with all bitmap data
1187
 */
1188
static int
1189
DecodeRLE8(MWUCHAR *buf, buffer_t *src)
1190
{
1191
        int             c, n;
1192
        MWUCHAR *       p = buf;
1193
 
1194
        for( ;;) {
1195
          switch( n = bgetc(src)) {
1196
          case EOF:
1197
            return( 0);
1198
          case 0:                        /* 0 = escape*/
1199
            switch( n = bgetc(src)) {
1200
            case 0:      /* 0 0 = end of current scan line*/
1201
              return( 1);
1202
            case 1:             /* 0 1 = end of data*/
1203
              return( 1);
1204
            case 2:             /* 0 2 xx yy delta mode NOT SUPPORTED*/
1205
              (void)bgetc(src);
1206
              (void)bgetc(src);
1207
              continue;
1208
            default:    /* 0 3..255 xx nn uncompressed data*/
1209
              for( c=0; c<n; c++)
1210
                *p++ = bgetc(src);
1211
              if( n & 1)
1212
                (void)bgetc(src);
1213
              continue;
1214
            }
1215
          default:
1216
            c = bgetc(src);
1217
            while( n--)
1218
              *p++ = c;
1219
            continue;
1220
          }
1221
        }
1222
}
1223
 
1224
/*
1225
 * Decode one line of RLE4, return 0 when done with all bitmap data
1226
 */
1227
static MWUCHAR *p;
1228
static int      once;
1229
 
1230
static void
1231
put4(int b)
1232
{
1233
        static int      last;
1234
 
1235
        last = (last << 4) | b;
1236
        if( ++once == 2) {
1237
                *p++ = last;
1238
                once = 0;
1239
        }
1240
}
1241
 
1242
static int
1243
DecodeRLE4(MWUCHAR *buf, buffer_t *src)
1244
{
1245
        int             c, n, c1, c2;
1246
 
1247
        p = buf;
1248
        once = 0;
1249
        c1 = 0;
1250
 
1251
        for( ;;) {
1252
          switch( n = bgetc(src)) {
1253
          case EOF:
1254
            return( 0);
1255
          case 0:                        /* 0 = escape*/
1256
            switch( n = bgetc(src)) {
1257
            case 0:      /* 0 0 = end of current scan line*/
1258
              if( once)
1259
                put4( 0);
1260
              return( 1);
1261
            case 1:             /* 0 1 = end of data*/
1262
              if( once)
1263
                put4( 0);
1264
              return( 1);
1265
            case 2:             /* 0 2 xx yy delta mode NOT SUPPORTED*/
1266
              (void)bgetc(src);
1267
              (void)bgetc(src);
1268
              continue;
1269
            default:    /* 0 3..255 xx nn uncompressed data*/
1270
              c2 = (n+3) & ~3;
1271
              for( c=0; c<c2; c++) {
1272
                if( (c & 1) == 0)
1273
                  c1 = bgetc(src);
1274
                if( c < n)
1275
                  put4( (c1 >> 4) & 0x0f);
1276
                c1 <<= 4;
1277
              }
1278
              continue;
1279
            }
1280
          default:
1281
            c = bgetc(src);
1282
            c1 = (c >> 4) & 0x0f;
1283
            c2 = c & 0x0f;
1284
            for( c=0; c<n; c++)
1285
              put4( (c&1)? c2: c1);
1286
            continue;
1287
          }
1288
        }
1289
}
1290
#endif /* defined(HAVE_FILEIO) && defined(HAVE_BMP_SUPPORT)*/
1291
 
1292
#if 0
1293
void print_image(PMWIMAGEHDR image)
1294
{
1295
        int i;
1296
 
1297
        DPRINTF("Image:\n\n");
1298
        DPRINTF("height: %d\n", image->height);
1299
        DPRINTF("width: %d\n", image->width);
1300
        DPRINTF("planes: %d\n", image->planes);
1301
        DPRINTF("bpp: %d\n", image->bpp);
1302
        DPRINTF("compression: %d\n", image->compression);
1303
        DPRINTF("palsize: %d\n", image->palsize);
1304
 
1305
        for (i=0;i<image->palsize;i++)
1306
                DPRINTF("palette: %d, %d, %d\n", image->palette[i].r,
1307
                        image->palette[i].g, image->palette[i].b);
1308
 
1309
        for(i=0;i<(image->width*image->height);i++)
1310
                DPRINTF("imagebits: %d\n", image->imagebits[i]);
1311
}
1312
#endif
1313
 
1314
#if defined(HAVE_FILEIO) && defined(HAVE_GIF_SUPPORT)
1315
/* Code for GIF decoding has been adapted from XPaint:                   */
1316
/* +-------------------------------------------------------------------+ */
1317
/* | Copyright 1990, 1991, 1993 David Koblas.                          | */
1318
/* | Copyright 1996 Torsten Martinsen.                                 | */
1319
/* |   Permission to use, copy, modify, and distribute this software   | */
1320
/* |   and its documentation for any purpose and without fee is hereby | */
1321
/* |   granted, provided that the above copyright notice appear in all | */
1322
/* |   copies and that both that copyright notice and this permission  | */
1323
/* |   notice appear in supporting documentation.  This software is    | */
1324
/* |   provided "as is" without express or implied warranty.           | */
1325
/* +-------------------------------------------------------------------+ */
1326
/* Portions Copyright (C) 1999  Sam Lantinga*/
1327
/* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */
1328
/*
1329
    This library is free software; you can redistribute it and/or
1330
    modify it under the terms of the GNU Library General Public
1331
    License as published by the Free Software Foundation; either
1332
    version 2 of the License, or (at your option) any later version.
1333
 
1334
    This library is distributed in the hope that it will be useful,
1335
    but WITHOUT ANY WARRANTY; without even the implied warranty of
1336
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1337
    Library General Public License for more details.
1338
 
1339
    You should have received a copy of the GNU Library General Public
1340
    License along with this library; if not, write to the Free
1341
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1342
*/
1343
/* GIF stuff*/
1344
/*
1345
 * GIF decoding routine
1346
 */
1347
#define MAXCOLORMAPSIZE         256
1348
#define MAX_LWZ_BITS            12
1349
#define INTERLACE               0x40
1350
#define LOCALCOLORMAP           0x80
1351
 
1352
#define CM_RED          0
1353
#define CM_GREEN        1
1354
#define CM_BLUE         2
1355
 
1356
#define BitSet(byte, bit)       (((byte) & (bit)) == (bit))
1357
#define ReadOK(src,buffer,len)  bread(src, buffer, len)
1358
#define LM_to_uint(a,b)         (((b)<<8)|(a))
1359
 
1360
struct {
1361
    unsigned int Width;
1362
    unsigned int Height;
1363
    unsigned char ColorMap[3][MAXCOLORMAPSIZE];
1364
    unsigned int BitPixel;
1365
    unsigned int ColorResolution;
1366
    unsigned int Background;
1367
    unsigned int AspectRatio;
1368
    int GrayScale;
1369
} GifScreen;
1370
 
1371
static struct {
1372
    int transparent;
1373
    int delayTime;
1374
    int inputFlag;
1375
    int disposal;
1376
} Gif89;
1377
 
1378
static int ReadColorMap(buffer_t *src, int number,
1379
                unsigned char buffer[3][MAXCOLORMAPSIZE], int *flag);
1380
static int DoExtension(buffer_t *src, int label);
1381
static int GetDataBlock(buffer_t *src, unsigned char *buf);
1382
static int GetCode(buffer_t *src, int code_size, int flag);
1383
static int LWZReadByte(buffer_t *src, int flag, int input_code_size);
1384
static int ReadImage(buffer_t *src, PMWIMAGEHDR pimage, int len, int height, int,
1385
                unsigned char cmap[3][MAXCOLORMAPSIZE],
1386
                int gray, int interlace, int ignore);
1387
 
1388
static int
1389
LoadGIF(buffer_t *src, PMWIMAGEHDR pimage)
1390
{
1391
    unsigned char buf[16];
1392
    unsigned char c;
1393
    unsigned char localColorMap[3][MAXCOLORMAPSIZE];
1394
    int grayScale;
1395
    int useGlobalColormap;
1396
    int bitPixel;
1397
    int imageCount = 0;
1398
    char version[4];
1399
    int imageNumber = 1;
1400
    int ok = 0;
1401
 
1402
    bseek(src, 0, SEEK_SET);
1403
 
1404
    pimage->imagebits = NULL;
1405
    pimage->palette = NULL;
1406
 
1407
    if (!ReadOK(src, buf, 6))
1408
        return 0;                /* not gif image*/
1409
    if (strncmp((char *) buf, "GIF", 3) != 0)
1410
        return 0;
1411
    strncpy(version, (char *) buf + 3, 3);
1412
    version[3] = '\0';
1413
 
1414
    if (strcmp(version, "87a") != 0 && strcmp(version, "89a") != 0) {
1415
        EPRINTF("LoadGIF: GIF version number not 87a or 89a\n");
1416
        return 2;               /* image loading error*/
1417
    }
1418
    Gif89.transparent = -1;
1419
    Gif89.delayTime = -1;
1420
    Gif89.inputFlag = -1;
1421
    Gif89.disposal = 0;
1422
 
1423
    if (!ReadOK(src, buf, 7)) {
1424
        EPRINTF("LoadGIF: bad screen descriptor\n");
1425
        return 2;               /* image loading error*/
1426
    }
1427
    GifScreen.Width = LM_to_uint(buf[0], buf[1]);
1428
    GifScreen.Height = LM_to_uint(buf[2], buf[3]);
1429
    GifScreen.BitPixel = 2 << (buf[4] & 0x07);
1430
    GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
1431
    GifScreen.Background = buf[5];
1432
    GifScreen.AspectRatio = buf[6];
1433
 
1434
    if (BitSet(buf[4], LOCALCOLORMAP)) {        /* Global Colormap */
1435
        if (ReadColorMap(src, GifScreen.BitPixel, GifScreen.ColorMap,
1436
                         &GifScreen.GrayScale)) {
1437
            EPRINTF("LoadGIF: bad global colormap\n");
1438
            return 2;           /* image loading error*/
1439
        }
1440
    }
1441
 
1442
    do {
1443
        if (!ReadOK(src, &c, 1)) {
1444
            EPRINTF("LoadGIF: EOF on image data\n");
1445
            goto done;
1446
        }
1447
        if (c == ';') {         /* GIF terminator */
1448
            if (imageCount < imageNumber) {
1449
                EPRINTF("LoadGIF: no image %d of %d\n", imageNumber,imageCount);
1450
                goto done;
1451
            }
1452
        }
1453
        if (c == '!') {         /* Extension */
1454
            if (!ReadOK(src, &c, 1)) {
1455
                EPRINTF("LoadGIF: EOF on extension function code\n");
1456
                goto done;
1457
            }
1458
            DoExtension(src, c);
1459
            continue;
1460
        }
1461
        if (c != ',') {         /* Not a valid start character */
1462
            continue;
1463
        }
1464
        ++imageCount;
1465
 
1466
        if (!ReadOK(src, buf, 9)) {
1467
            EPRINTF("LoadGIF: bad image size\n");
1468
            goto done;
1469
        }
1470
        useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP);
1471
 
1472
        bitPixel = 1 << ((buf[8] & 0x07) + 1);
1473
 
1474
        if (!useGlobalColormap) {
1475
            if (ReadColorMap(src, bitPixel, localColorMap, &grayScale)) {
1476
                EPRINTF("LoadGIF: bad local colormap\n");
1477
                goto done;
1478
            }
1479
            ok = ReadImage(src, pimage, LM_to_uint(buf[4], buf[5]),
1480
                              LM_to_uint(buf[6], buf[7]),
1481
                              bitPixel, localColorMap, grayScale,
1482
                              BitSet(buf[8], INTERLACE),
1483
                              imageCount != imageNumber);
1484
        } else {
1485
            ok = ReadImage(src, pimage, LM_to_uint(buf[4], buf[5]),
1486
                              LM_to_uint(buf[6], buf[7]),
1487
                              GifScreen.BitPixel, GifScreen.ColorMap,
1488
                              GifScreen.GrayScale, BitSet(buf[8], INTERLACE),
1489
                              imageCount != imageNumber);
1490
        }
1491
    } while (ok == 0);
1492
 
1493
    /* set transparent color, if any*/
1494
    pimage->transcolor = Gif89.transparent;
1495
 
1496
    if (ok)
1497
            return 1;           /* image load ok*/
1498
 
1499
done:
1500
    if (pimage->imagebits)
1501
            free(pimage->imagebits);
1502
    if (pimage->palette)
1503
            free(pimage->palette);
1504
    return 2;                   /* image load error*/
1505
}
1506
 
1507
static int
1508
ReadColorMap(buffer_t *src, int number, unsigned char buffer[3][MAXCOLORMAPSIZE],
1509
    int *gray)
1510
{
1511
    int i;
1512
    unsigned char rgb[3];
1513
    int flag;
1514
 
1515
    flag = TRUE;
1516
 
1517
    for (i = 0; i < number; ++i) {
1518
        if (!ReadOK(src, rgb, sizeof(rgb)))
1519
            return 1;
1520
        buffer[CM_RED][i] = rgb[0];
1521
        buffer[CM_GREEN][i] = rgb[1];
1522
        buffer[CM_BLUE][i] = rgb[2];
1523
        flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
1524
    }
1525
 
1526
#if 0
1527
    if (flag)
1528
        *gray = (number == 2) ? PBM_TYPE : PGM_TYPE;
1529
    else
1530
        *gray = PPM_TYPE;
1531
#else
1532
    *gray = 0;
1533
#endif
1534
 
1535
    return FALSE;
1536
}
1537
 
1538
static int
1539
DoExtension(buffer_t *src, int label)
1540
{
1541
    static unsigned char buf[256];
1542
 
1543
    switch (label) {
1544
    case 0x01:                  /* Plain Text Extension */
1545
        break;
1546
    case 0xff:                  /* Application Extension */
1547
        break;
1548
    case 0xfe:                  /* Comment Extension */
1549
        while (GetDataBlock(src, (unsigned char *) buf) != 0);
1550
        return FALSE;
1551
    case 0xf9:                  /* Graphic Control Extension */
1552
        GetDataBlock(src, (unsigned char *) buf);
1553
        Gif89.disposal = (buf[0] >> 2) & 0x7;
1554
        Gif89.inputFlag = (buf[0] >> 1) & 0x1;
1555
        Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
1556
        if ((buf[0] & 0x1) != 0)
1557
            Gif89.transparent = buf[3];
1558
 
1559
        while (GetDataBlock(src, (unsigned char *) buf) != 0);
1560
        return FALSE;
1561
    default:
1562
        break;
1563
    }
1564
 
1565
    while (GetDataBlock(src, (unsigned char *) buf) != 0);
1566
 
1567
    return FALSE;
1568
}
1569
 
1570
static int ZeroDataBlock = FALSE;
1571
 
1572
static int
1573
GetDataBlock(buffer_t *src, unsigned char *buf)
1574
{
1575
    unsigned char count;
1576
 
1577
    if (!ReadOK(src, &count, 1))
1578
        return -1;
1579
    ZeroDataBlock = count == 0;
1580
 
1581
    if ((count != 0) && (!ReadOK(src, buf, count)))
1582
        return -1;
1583
    return count;
1584
}
1585
 
1586
static int
1587
GetCode(buffer_t *src, int code_size, int flag)
1588
{
1589
    static unsigned char buf[280];
1590
    static int curbit, lastbit, done, last_byte;
1591
    int i, j, ret;
1592
    unsigned char count;
1593
 
1594
    if (flag) {
1595
        curbit = 0;
1596
        lastbit = 0;
1597
        done = FALSE;
1598
        return 0;
1599
    }
1600
    if ((curbit + code_size) >= lastbit) {
1601
        if (done) {
1602
            if (curbit >= lastbit)
1603
                EPRINTF("LoadGIF: bad decode\n");
1604
            return -1;
1605
        }
1606
        buf[0] = buf[last_byte - 2];
1607
        buf[1] = buf[last_byte - 1];
1608
 
1609
        if ((count = GetDataBlock(src, &buf[2])) == 0)
1610
            done = TRUE;
1611
 
1612
        last_byte = 2 + count;
1613
        curbit = (curbit - lastbit) + 16;
1614
        lastbit = (2 + count) * 8;
1615
    }
1616
    ret = 0;
1617
    for (i = curbit, j = 0; j < code_size; ++i, ++j)
1618
        ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
1619
 
1620
    curbit += code_size;
1621
 
1622
    return ret;
1623
}
1624
 
1625
static int
1626
LWZReadByte(buffer_t *src, int flag, int input_code_size)
1627
{
1628
    int code, incode;
1629
    register int i;
1630
    static int fresh = FALSE;
1631
    static int code_size, set_code_size;
1632
    static int max_code, max_code_size;
1633
    static int firstcode, oldcode;
1634
    static int clear_code, end_code;
1635
    static int table[2][(1 << MAX_LWZ_BITS)];
1636
    static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
1637
 
1638
    if (flag) {
1639
        set_code_size = input_code_size;
1640
        code_size = set_code_size + 1;
1641
        clear_code = 1 << set_code_size;
1642
        end_code = clear_code + 1;
1643
        max_code_size = 2 * clear_code;
1644
        max_code = clear_code + 2;
1645
 
1646
        GetCode(src, 0, TRUE);
1647
 
1648
        fresh = TRUE;
1649
 
1650
        for (i = 0; i < clear_code; ++i) {
1651
            table[0][i] = 0;
1652
            table[1][i] = i;
1653
        }
1654
        for (; i < (1 << MAX_LWZ_BITS); ++i)
1655
            table[0][i] = table[1][0] = 0;
1656
 
1657
        sp = stack;
1658
 
1659
        return 0;
1660
    } else if (fresh) {
1661
        fresh = FALSE;
1662
        do {
1663
            firstcode = oldcode = GetCode(src, code_size, FALSE);
1664
        } while (firstcode == clear_code);
1665
        return firstcode;
1666
    }
1667
    if (sp > stack)
1668
        return *--sp;
1669
 
1670
    while ((code = GetCode(src, code_size, FALSE)) >= 0) {
1671
        if (code == clear_code) {
1672
            for (i = 0; i < clear_code; ++i) {
1673
                table[0][i] = 0;
1674
                table[1][i] = i;
1675
            }
1676
            for (; i < (1 << MAX_LWZ_BITS); ++i)
1677
                table[0][i] = table[1][i] = 0;
1678
            code_size = set_code_size + 1;
1679
            max_code_size = 2 * clear_code;
1680
            max_code = clear_code + 2;
1681
            sp = stack;
1682
            firstcode = oldcode = GetCode(src, code_size, FALSE);
1683
            return firstcode;
1684
        } else if (code == end_code) {
1685
            int count;
1686
            unsigned char buf[260];
1687
 
1688
            if (ZeroDataBlock)
1689
                return -2;
1690
 
1691
            while ((count = GetDataBlock(src, buf)) > 0);
1692
 
1693
            if (count != 0) {
1694
                /*
1695
                 * EPRINTF("missing EOD in data stream (common occurence)");
1696
                 */
1697
            }
1698
            return -2;
1699
        }
1700
        incode = code;
1701
 
1702
        if (code >= max_code) {
1703
            *sp++ = firstcode;
1704
            code = oldcode;
1705
        }
1706
        while (code >= clear_code) {
1707
            *sp++ = table[1][code];
1708
            if (code == table[0][code])
1709
                EPRINTF("LoadGIF: circular table entry\n");
1710
            code = table[0][code];
1711
        }
1712
 
1713
        *sp++ = firstcode = table[1][code];
1714
 
1715
        if ((code = max_code) < (1 << MAX_LWZ_BITS)) {
1716
            table[0][code] = oldcode;
1717
            table[1][code] = firstcode;
1718
            ++max_code;
1719
            if ((max_code >= max_code_size) &&
1720
                (max_code_size < (1 << MAX_LWZ_BITS))) {
1721
                max_code_size *= 2;
1722
                ++code_size;
1723
            }
1724
        }
1725
        oldcode = incode;
1726
 
1727
        if (sp > stack)
1728
            return *--sp;
1729
    }
1730
    return code;
1731
}
1732
 
1733
static int
1734
ReadImage(buffer_t* src, PMWIMAGEHDR pimage, int len, int height, int cmapSize,
1735
          unsigned char cmap[3][MAXCOLORMAPSIZE],
1736
          int gray, int interlace, int ignore)
1737
{
1738
    unsigned char c;
1739
    int i, v;
1740
    int xpos = 0, ypos = 0, pass = 0;
1741
 
1742
    /*
1743
     *  Initialize the compression routines
1744
     */
1745
    if (!ReadOK(src, &c, 1)) {
1746
        EPRINTF("LoadGIF: EOF on image data\n");
1747
        return 0;
1748
    }
1749
    if (LWZReadByte(src, TRUE, c) < 0) {
1750
        EPRINTF("LoadGIF: error reading image\n");
1751
        return 0;
1752
    }
1753
 
1754
    /*
1755
     *  If this is an "uninteresting picture" ignore it.
1756
     */
1757
    if (ignore) {
1758
        while (LWZReadByte(src, FALSE, c) >= 0);
1759
        return 0;
1760
    }
1761
    /*image = ImageNewCmap(len, height, cmapSize);*/
1762
    pimage->width = len;
1763
    pimage->height = height;
1764
    pimage->planes = 1;
1765
    pimage->bpp = 8;
1766
    ComputePitch(8, len, &pimage->pitch, &pimage->bytesperpixel);
1767
    pimage->compression = 0;
1768
    pimage->palsize = cmapSize;
1769
    pimage->palette = malloc(256*sizeof(MWPALENTRY));
1770
    pimage->imagebits = malloc(height*pimage->pitch);
1771
    if(!pimage->imagebits || !pimage->palette)
1772
            return 0;
1773
 
1774
    for (i = 0; i < cmapSize; i++) {
1775
        /*ImageSetCmap(image, i, cmap[CM_RED][i],
1776
                     cmap[CM_GREEN][i], cmap[CM_BLUE][i]);*/
1777
        pimage->palette[i].r = cmap[CM_RED][i];
1778
        pimage->palette[i].g = cmap[CM_GREEN][i];
1779
        pimage->palette[i].b = cmap[CM_BLUE][i];
1780
    }
1781
 
1782
    while ((v = LWZReadByte(src, FALSE, c)) >= 0) {
1783
        pimage->imagebits[ypos * pimage->pitch + xpos] = v;
1784
 
1785
        ++xpos;
1786
        if (xpos == len) {
1787
            xpos = 0;
1788
            if (interlace) {
1789
                switch (pass) {
1790
                case 0:
1791
                case 1:
1792
                    ypos += 8;
1793
                    break;
1794
                case 2:
1795
                    ypos += 4;
1796
                    break;
1797
                case 3:
1798
                    ypos += 2;
1799
                    break;
1800
                }
1801
 
1802
                if (ypos >= height) {
1803
                    ++pass;
1804
                    switch (pass) {
1805
                    case 1:
1806
                        ypos = 4;
1807
                        break;
1808
                    case 2:
1809
                        ypos = 2;
1810
                        break;
1811
                    case 3:
1812
                        ypos = 1;
1813
                        break;
1814
                    default:
1815
                        goto fini;
1816
                    }
1817
                }
1818
            } else {
1819
                ++ypos;
1820
            }
1821
        }
1822
        if (ypos >= height)
1823
            break;
1824
    }
1825
 
1826
fini:
1827
    return 1;
1828
}
1829
#endif /* defined(HAVE_FILEIO) && defined(HAVE_GIF_SUPPORT)*/
1830
 
1831
#if defined(HAVE_FILEIO) && defined(HAVE_PNM_SUPPORT)
1832
enum {
1833
        PNM_TYPE_NOTPNM,
1834
        PNM_TYPE_PBM,
1835
        PNM_TYPE_PGM,
1836
        PNM_TYPE_PPM
1837
};
1838
static int LoadPNM(buffer_t *src, PMWIMAGEHDR pimage)
1839
{
1840
        char buf[256], *p;
1841
        int type = PNM_TYPE_NOTPNM, binary = 0, gothdrs = 0, scale = 0;
1842
        int ch, x = 0, y = 0, i, n, mask, col1, col2, col3;
1843
 
1844
        bseek(src, 0L, 0);
1845
 
1846
        if(!bgets(src,buf, 4)) return 0;
1847
 
1848
        if(!strcmp("P1\n", buf)) type = PNM_TYPE_PBM;
1849
        else if(!strcmp("P2\n", buf)) type = PNM_TYPE_PGM;
1850
        else if(!strcmp("P3\n", buf)) type = PNM_TYPE_PPM;
1851
        else if(!strcmp("P4\n", buf)) {
1852
                type = PNM_TYPE_PBM;
1853
                binary = 1;
1854
        }
1855
        else if(!strcmp("P5\n", buf)) {
1856
                type = PNM_TYPE_PGM;
1857
                binary = 1;
1858
        }
1859
        else if(!strcmp("P6\n", buf)) {
1860
                type = PNM_TYPE_PPM;
1861
                binary = 1;
1862
        }
1863
 
1864
        if(type == PNM_TYPE_NOTPNM) return 0;
1865
 
1866
        n = 0;
1867
        while((p = bgets(src, buf, 256))) {
1868
                if(*buf == '#') continue;
1869
                if(type == PNM_TYPE_PBM) {
1870
                        if(sscanf(buf, "%i %i", &pimage->width,
1871
                                        &pimage->height) == 2) {
1872
                                pimage->bpp = 1;
1873
                                gothdrs = 1;
1874
                                if(!(pimage->palette = malloc(
1875
                                                sizeof(MWPALENTRY) * 2))) {
1876
                                        EPRINTF("Out of memory\n");
1877
                                        return 2;
1878
                                }
1879
                                pimage->palsize = 2;
1880
                                pimage->palette[0].r = 0xff;
1881
                                pimage->palette[0].g = 0xff;
1882
                                pimage->palette[0].b = 0xff;
1883
                                pimage->palette[1].r = 0;
1884
                                pimage->palette[1].g = 0;
1885
                                pimage->palette[1].b = 0;
1886
                        }
1887
                        break;
1888
                }
1889
                if((type == PNM_TYPE_PGM) || (type == PNM_TYPE_PPM)) {
1890
                        if(!n++) {
1891
                                if(sscanf(buf, "%i %i", &pimage->width,
1892
                                        &pimage->height) != 2) break;
1893
                        } else {
1894
                                if(sscanf(buf, "%i", &i) != 1) break;
1895
                                pimage->bpp = 24;
1896
                                if(i > 255) {
1897
                                        EPRINTF("LoadPNM: PPM files must be "
1898
                                                "24bpp\n");
1899
                                        return 2;
1900
                                }
1901
                                for(scale = 7, n = 2; scale; scale--, n *= 2)
1902
                                        if(i < n) break;
1903
                                gothdrs = 1;
1904
                                break;
1905
                        }
1906
                }
1907
        }
1908
 
1909
        if(!gothdrs) {
1910
                EPRINTF("LoadPNM: bad image headers\n");
1911
                if(pimage->palette) free(pimage->palette);
1912
                return 2;
1913
        }
1914
 
1915
        pimage->planes = 1;
1916
        ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
1917
                                                &pimage->bytesperpixel);
1918
        pimage->compression = MWIMAGE_RGB;
1919
        if(!(pimage->imagebits = malloc(pimage->pitch * pimage->height))) {
1920
                EPRINTF("LoadPNM: couldn't allocate memory for image\n");
1921
                if(pimage->palette) free(pimage->palette);
1922
                return 2;
1923
        }
1924
 
1925
        p = pimage->imagebits;
1926
 
1927
        if(type == PNM_TYPE_PBM) {
1928
                if(binary) {
1929
                        x = 0;
1930
                        y = 0;
1931
                        while((ch = bgetc(src)) != EOF) {
1932
                                for(i = 0; i < 8; i++) {
1933
                                        mask = 0x80 >> i;
1934
                                        if(ch & mask) *p |= mask;
1935
                                        else *p &= ~mask;
1936
                                        if(++x == pimage->width) {
1937
                                                if(++y == pimage->height)
1938
                                                        return 1;
1939
                                                p = pimage->imagebits - 1 +
1940
                                                        (y * pimage->pitch);
1941
                                                x = 0;
1942
                                                break;
1943
                                        }
1944
                                }
1945
                                p++;
1946
                        }
1947
                } else {
1948
                        n = 0;
1949
                        while((ch = bgetc(src)) != EOF) {
1950
                                if(isspace(ch)) continue;
1951
                                mask = 0x80 >> n;
1952
                                if(ch == '1') *p |= mask;
1953
                                else if(ch == '0') *p &= ~mask;
1954
                                else goto baddata;
1955
                                if(++n == 8) {
1956
                                        n = 0;
1957
                                        p++;
1958
                                }
1959
                                if(++x == pimage->width) {
1960
                                        if(++y == pimage->height)
1961
                                                return 1;
1962
                                        p = pimage->imagebits +
1963
                                                (y * pimage->pitch);
1964
                                        n = 0;
1965
                                        x = 0;
1966
                                }
1967
                        }
1968
                }
1969
        } else {
1970
                while(1) {
1971
                        if(type == PNM_TYPE_PGM) {
1972
                                if(binary) {
1973
                                        if((ch = bgetc(src)) == EOF)
1974
                                                goto baddata;
1975
                                } else {
1976
                                  //                                    if(fscanf(fp, "%i", &ch) != 1)
1977
                                                goto baddata;
1978
                                }
1979
                                *p++ = ch << scale;
1980
                                *p++ = ch << scale;
1981
                                *p++ = ch << scale;
1982
                        } else {
1983
                                if(binary) {
1984
                                        if(((col1 = bgetc(src)) == EOF) ||
1985
                                                ((col2 = bgetc(src)) == EOF) ||
1986
                                                ((col3 = bgetc(src)) == EOF))
1987
                                                goto baddata;
1988
                                } else {
1989
                                  //                                    if(fscanf(fp, "%i %i %i", &col1, &col2,
1990
                                  //                                                            &col3) != 3)
1991
                                                goto baddata;
1992
                                }
1993
                                *p++ = col1 << scale;
1994
                                *p++ = col2 << scale;
1995
                                *p++ = col3 << scale;
1996
                        }
1997
                        if(++x == pimage->width) {
1998
                                if(++y == pimage->height) return 1;
1999
                                p = pimage->imagebits + (y * pimage->pitch);
2000
                                x = 0;
2001
                        }
2002
                }
2003
        }
2004
 
2005
baddata:
2006
        EPRINTF("LoadPNM: bad image data\n");
2007
        free(pimage->imagebits);
2008
        if(pimage->palette) free(pimage->palette);
2009
        return 2;
2010
}
2011
#endif /* defined(HAVE_FILEIO) && defined(HAVE_PNM_SUPPORT) */
2012
 
2013
#if defined(HAVE_FILEIO) && defined(HAVE_XPM_SUPPORT)
2014
struct xpm_cmap {
2015
  char mapstr[3];
2016
  long palette_entry;
2017
  long color;
2018
  struct xpm_cmap *next;
2019
};
2020
 
2021
 
2022
static long XPM_parse_color(char *color)
2023
{
2024
  /* This will parse the string into a color value of some sort */
2025
 
2026
  if (color[0] != '#')
2027
    {
2028
      if (!strcmp(color, "None"))
2029
        return(-1); /* Transparent */
2030
      else
2031
        return(0); /* If its an X color, then we bail */
2032
    }
2033
  else
2034
    {
2035
      /* This is ugly! */
2036
 
2037
      char *sptr = color + 1;
2038
      char rstr[5], gstr[5], bstr[5];
2039
      long r,g,b;
2040
 
2041
      switch(strlen(sptr))
2042
        {
2043
        case 6:
2044
          return(strtol(sptr, NULL, 16));
2045
 
2046
        case 9: /* RRRGGGBBB */
2047
          strncpy(rstr, sptr, 3);
2048
          strncpy(gstr, sptr + 3, 3);
2049
          strncpy(bstr, sptr + 6, 3);
2050
 
2051
          rstr[3] = 0;
2052
          gstr[3] = 0;
2053
          bstr[3] = 0;
2054
 
2055
          r = strtol(rstr, NULL, 16) >> 4;
2056
          g = strtol(gstr, NULL, 16) >> 4;
2057
          b = strtol(bstr, NULL, 16) >> 4;
2058
 
2059
          return( (long) ( r << 16 | g << 8 | b));
2060
 
2061
        case 12:
2062
          strncpy(rstr, sptr, 4);
2063
          strncpy(gstr, sptr + 4, 4);
2064
          strncpy(bstr, sptr + 8, 4);
2065
 
2066
          rstr[4] = 0;
2067
          gstr[4] = 0;
2068
          bstr[4] = 0;
2069
 
2070
          r = strtol(rstr, NULL, 16) >> 8;
2071
          g = strtol(gstr, NULL, 16) >> 8;
2072
          b = strtol(bstr, NULL, 16) >> 8;
2073
 
2074
          return( (long) ( (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)));
2075
        }
2076
    }
2077
 
2078
  return(0);
2079
}
2080
 
2081
/* A series of status indicators that let us know whats going on */
2082
/* It could be an enum if you want */
2083
 
2084
#define LOAD_HEADER 1
2085
#define LOAD_COLORS 2
2086
#define LOAD_PALETTE 3
2087
#define LOAD_PIXELS 4
2088
#define LOAD_DONE 5
2089
 
2090
/* The magic that "should" indicate an XPM (does it really?) */
2091
#define XPM_MAGIC "/* XPM */"
2092
#define XPM_TRANSCOLOR 0x01000000
2093
 
2094
static int LoadXPM(buffer_t *src, PMWIMAGEHDR pimage, PSD psd)
2095
{
2096
  struct xpm_cmap *colorheap = 0;  /* A "heap" of color structs */
2097
  struct xpm_cmap *colormap[256];  /* A quick hash of 256 spots for colors */
2098
 
2099
  unsigned char *imageptr = 0;
2100
 
2101
  MWSCREENINFO sinfo;
2102
 
2103
  char xline[300];
2104
  char dline[300];
2105
 
2106
  char *c;
2107
  int a;
2108
 
2109
  int col, row, colors, cpp;
2110
  int in_color = 0;
2111
  int read_xline = 0;
2112
 
2113
  int status = LOAD_HEADER;
2114
 
2115
  /* Very first thing, get the screen info */
2116
  GdGetScreenInfo(psd, &sinfo);
2117
 
2118
  for(a = 0; a < 256; a++)
2119
    colormap[a] = 0;
2120
 
2121
  pimage->imagebits = NULL;
2122
  pimage->palette = NULL;
2123
 
2124
  /* Start over at the beginning with the file */
2125
  bseek(src, 0, SEEK_SET);
2126
 
2127
  bgets(src, xline, 300);
2128
 
2129
  /* Chop the EOL */
2130
  xline[strlen(xline) - 1] = 0;
2131
 
2132
  /* Check the magic */
2133
  if (strncmp(xline, XPM_MAGIC, sizeof(XPM_MAGIC))) return(0);
2134
 
2135
  while(!beof(src))
2136
    {
2137
      /* Get the next line from the file */
2138
      bgets(src,xline, 300);
2139
      xline[strlen(xline) - 1] = 0;
2140
 
2141
      /* Check it out */
2142
      if (xline[0] == '/' && xline[1] == '*') /* Comment */
2143
        continue;
2144
 
2145
      if (xline[0] != '\"')
2146
        continue;
2147
 
2148
      /* remove the quotes from the line */
2149
      for(c = xline + 1, a = 0; *c != '\"' && *c != 0; c++, a++)
2150
        dline[a] = *c;
2151
 
2152
      dline[a] = 0;
2153
 
2154
      /* Is it the header? */
2155
      if (status == LOAD_HEADER)
2156
        {
2157
          sscanf(dline, "%i %i %i %i", &col, &row, &colors, &cpp);
2158
 
2159
          pimage->width = col;
2160
          pimage->height = row;
2161
          pimage->planes = 1;
2162
 
2163
          if (sinfo.bpp <= 8)
2164
            {
2165
              pimage->bpp = sinfo.bpp;
2166
              pimage->compression = 0;
2167
              pimage->transcolor = -1;
2168
            }
2169
          else
2170
            {
2171
              pimage->bpp = 32;
2172
              pimage->transcolor = XPM_TRANSCOLOR;
2173
              pimage->compression = MWIMAGE_BGR;
2174
            }
2175
 
2176
          pimage->palsize = colors;
2177
 
2178
          ComputePitch(pimage->bpp, col, &pimage->pitch, &pimage->bytesperpixel);
2179
 
2180
          pimage->imagebits = malloc(pimage->pitch * pimage->height);
2181
          imageptr = (unsigned char *) pimage->imagebits;
2182
 
2183
          /* Allocate enough room for all the colors */
2184
          colorheap = (struct xpm_cmap *) malloc(colors * sizeof(struct xpm_cmap));
2185
 
2186
          /* Allocate the palette space (if required) */
2187
 
2188
          if (sinfo.bpp <= 8)
2189
              pimage->palette = malloc(256*sizeof(MWPALENTRY));
2190
 
2191
          if (!colorheap)
2192
            {
2193
              EPRINTF("Couldn't allocate any memory for the colors\n");
2194
              return(0);
2195
            }
2196
 
2197
          status = LOAD_COLORS;
2198
          in_color = 0;
2199
          continue;
2200
        }
2201
 
2202
      /* Are we in load colors? */
2203
      if (status == LOAD_COLORS)
2204
        {
2205
          struct xpm_cmap *n;
2206
 
2207
          char tstr[5];
2208
          char cstr[256];
2209
 
2210
          unsigned char m;
2211
 
2212
          c = dline;
2213
 
2214
          /* Go at at least 1 charater, and then count until we have
2215
             two spaces in a row */
2216
 
2217
          strncpy(tstr, c, cpp);
2218
 
2219
          c += cpp;
2220
          for(; *c == '\t' || *c == ' '; c++); /* Skip over whitespace */
2221
 
2222
          /* FIXME: We assume that a 'c' follows.  What if it doesn't? */
2223
          c +=2;
2224
 
2225
          tstr[cpp] = 0;
2226
 
2227
          /* Now we put it into the array for easy lookup   */
2228
          /* We base it off the first charater, even though */
2229
          /* there may be up to 4                           */
2230
 
2231
          m = tstr[0];
2232
 
2233
          if (colormap[m])
2234
            {
2235
              n = colormap[m];
2236
 
2237
              while(n->next) n = n->next;
2238
              n->next = &colorheap[in_color];
2239
              n = n->next;
2240
            }
2241
          else
2242
            {
2243
              colormap[m] = &colorheap[in_color];
2244
              n = colormap[m];
2245
            }
2246
 
2247
          n->next = 0;
2248
 
2249
          /* Record the string */
2250
          strncpy(n->mapstr, tstr, cpp);
2251
          n->mapstr[cpp] = 0;
2252
 
2253
          /* Now record the palette entry */
2254
          n->palette_entry = (long) in_color;
2255
 
2256
          /* This is the color */
2257
          sscanf(c, "%65535s", cstr);
2258
 
2259
          /* Turn it into a real value */
2260
          n->color = XPM_parse_color(cstr);
2261
 
2262
          /* If we are in palette mode, then we need to */
2263
          /* load the palette (duh..) */
2264
 
2265
          if (sinfo.bpp <= 8)
2266
            {
2267
              if (n->color == -1)
2268
                {
2269
                  pimage->transcolor = in_color;
2270
                  n->color = -1;
2271
                }
2272
 
2273
              pimage->palette[in_color].r = (n->color >> 16) & 0xFF;
2274
              pimage->palette[in_color].g = (n->color >> 8) & 0xFF;
2275
              pimage->palette[in_color].b = n->color & 0xFF;
2276
            }
2277
          else
2278
            {
2279
              if (n->color == -1)
2280
                n->color = XPM_TRANSCOLOR;
2281
            }
2282
 
2283
          if (++in_color == colors)
2284
            {
2285
              read_xline = 0;
2286
              status = LOAD_PIXELS;
2287
            }
2288
 
2289
          continue;
2290
        }
2291
 
2292
      if (status == LOAD_PIXELS)
2293
      {
2294
        int bytecount = 0;
2295
        int bitcount = 0;
2296
        long dwordcolor = 0;
2297
        int i;
2298
        char pxlstr[3];
2299
 
2300
        c = dline;
2301
 
2302
        while(*c)
2303
          {
2304
            unsigned char z = 0;
2305
 
2306
            if (cpp == 1)
2307
              {
2308
                z = *c;
2309
 
2310
                if (!colormap[z])
2311
                  {
2312
                    EPRINTF("No color entry for (%c)\n", z);
2313
                    return(0);
2314
                  }
2315
 
2316
                if (sinfo.bpp <= 8)
2317
                  dwordcolor = (long) colormap[z]->palette_entry;
2318
                else
2319
                  dwordcolor = colormap[z]->color;
2320
 
2321
                c++;
2322
              }
2323
            else
2324
              {
2325
                struct xpm_cmap *n;
2326
 
2327
                /* We grab the largest possible, and then compare */
2328
 
2329
                strncpy(pxlstr, c, cpp);
2330
                z = pxlstr[0];
2331
 
2332
                if (!colormap[z])
2333
                  {
2334
                    EPRINTF("No color entry for (%s)\n", pxlstr);
2335
                    return(0);
2336
                  }
2337
 
2338
                n = colormap[z];
2339
 
2340
                while(n)
2341
                  {
2342
                    if (!strncmp(n->mapstr, pxlstr, cpp))
2343
                      break;
2344
 
2345
                    n = n->next;
2346
                  }
2347
 
2348
                if (!n)
2349
                  {
2350
                    EPRINTF("No color found for (%s)\n", pxlstr);
2351
                    return(0);
2352
                  }
2353
 
2354
                if (sinfo.bpp <= 8)
2355
                  dwordcolor = (long) n->palette_entry;
2356
                else
2357
                  dwordcolor = n->color;
2358
 
2359
                c += cpp;
2360
              }
2361
 
2362
            /*
2363
             * This ugly thing is needed to ensure that we
2364
             * work well in all modes.
2365
             */
2366
            switch(sinfo.bpp)
2367
              {
2368
              case 2:
2369
                if (bitcount == 0)
2370
                  imageptr[0] = 0;
2371
 
2372
                imageptr[0] |= (dwordcolor & 0x3) << (4 - bitcount);
2373
                bitcount++;
2374
 
2375
                if (bitcount == 4)
2376
                  {
2377
                    imageptr++;
2378
                    bytecount += pimage->bytesperpixel;
2379
                    bitcount = 0;
2380
                  }
2381
 
2382
                break;
2383
 
2384
              case 4:
2385
                if (bitcount == 0)
2386
                  imageptr[0] = 0;
2387
 
2388
                imageptr[0] |= (dwordcolor & 0xF) << (2 - bitcount);
2389
                bitcount++;
2390
 
2391
                if (bitcount == 2)
2392
                  {
2393
                    imageptr++;
2394
                    bytecount += pimage->bytesperpixel;
2395
                    bitcount = 0;
2396
                  }
2397
 
2398
                break;
2399
 
2400
              case 8:
2401
              case 16:
2402
              case 24:
2403
              case 32:
2404
 
2405
                for(i = 0; i < pimage->bytesperpixel; i++)
2406
                  imageptr[i] = (dwordcolor >> (8 * i)) & 0xFF;
2407
 
2408
                imageptr += pimage->bytesperpixel;
2409
                bytecount += pimage->bytesperpixel;
2410
                break;
2411
 
2412
#ifdef NOTUSED
2413
              case 8:
2414
                imageptr[0] = (unsigned char) (dwordcolor & 0xFF);
2415
                imageptr += pimage->bytesperpixel;
2416
                bytecount += pimage->bytesperpixel;
2417
                break;
2418
 
2419
              case 16:
2420
              case 24:
2421
              case 32:
2422
                imageptr[0] = (unsigned char) (dwordcolor >> 24) & 0xFF;
2423
                imageptr[1] = (unsigned char) (dwordcolor >> 16) & 0xFF;
2424
                imageptr[2] = (unsigned char) (dwordcolor >> 8) & 0xFF;
2425
                imageptr[3] = (unsigned char) (dwordcolor & 0xFF);
2426
                imageptr += pimage->bytesperpixel;
2427
                bytecount += pimage->bytesperpixel;
2428
                break;
2429
#endif
2430
              }
2431
          }
2432
 
2433
        /* Pad to the end of the line */
2434
        if (bytecount < pimage->pitch)
2435
          for(i = 0; i < (pimage->pitch - bytecount); i++)
2436
            *imageptr++ = 0x00;
2437
 
2438
        read_xline++;
2439
 
2440
        if (read_xline == row)
2441
          status = LOAD_DONE;
2442
 
2443
        continue;
2444
      }
2445
    }
2446
 
2447
  free(colorheap);
2448
 
2449
  if (status != LOAD_DONE)
2450
    return(-1);
2451
  return(1);
2452
}
2453
#endif /* defined(HAVE_FILEIO) && defined(HAVE_XPM_SUPPORT)*/
2454
 
2455
#endif /* defined(HAVE_FILEIO)*/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.