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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [engine/] [devimage.c] - Blame information for rev 27

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

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

powered by: WebSVN 2.1.0

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