source: libcaca/trunk/src/common-image.c @ 905

Last change on this file since 905 was 859, checked in by Sam Hocevar, 15 years ago
  • Removed duplicate uint*_t defines from *_internal.h and included common.h in all .c files that needed it.
  • Property svn:keywords set to Id
File size: 6.8 KB
Line 
1/*
2 *  Imaging tools for cacaview and img2irc
3 *  Copyright (c) 2003-2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: common-image.c 859 2006-04-24 20:35:59Z sam $
7 *
8 *  This program is free software; you can redistribute it and/or
9 *  modify it under the terms of the Do What The Fuck You Want To
10 *  Public License, Version 2, as published by Sam Hocevar. See
11 *  http://sam.zoy.org/wtfpl/COPYING for more details.
12 */
13
14#include "config.h"
15#include "common.h"
16
17#include <stdio.h>
18#include <string.h>
19#include <stdlib.h>
20
21#if defined(HAVE_IMLIB2_H)
22#   include <Imlib2.h>
23#else
24#   include <stdio.h>
25#endif
26
27#include "cucul.h"
28#include "common-image.h"
29
30#if !defined(HAVE_IMLIB2_H)
31static unsigned int u32fread(FILE *);
32static unsigned int u16fread(FILE *);
33static unsigned int u8fread(FILE *);
34#endif
35
36struct image * load_image(char const * name)
37{
38    struct image * im = malloc(sizeof(struct image));
39    unsigned int depth, bpp, rmask, gmask, bmask, amask;
40
41#if defined(HAVE_IMLIB2_H)
42    Imlib_Image image;
43
44    /* Load the new image */
45    image = imlib_load_image(name);
46
47    if(!image)
48    {
49        free(im);
50        return NULL;
51    }
52
53    imlib_context_set_image(image);
54    im->pixels = (char *)imlib_image_get_data_for_reading_only();
55    im->w = imlib_image_get_width();
56    im->h = imlib_image_get_height();
57    rmask = 0x00ff0000;
58    gmask = 0x0000ff00;
59    bmask = 0x000000ff;
60    amask = 0xff000000;
61    bpp = 32;
62    depth = 4;
63
64    /* Create the libcucul dither */
65    im->dither = cucul_create_dither(bpp, im->w, im->h, depth * im->w,
66                                     rmask, gmask, bmask, amask);
67    if(!im->dither)
68    {
69        imlib_free_image();
70        free(im);
71        return NULL;
72    }
73
74    im->priv = (void *)image;
75
76#else
77    /* Try to load a BMP file */
78    unsigned int red[256], green[256], blue[256], alpha[256];
79    unsigned int i, colors, offset, tmp, planes;
80    FILE *fp;
81
82    fp = fopen(name, "rb");
83    if(!fp)
84    {
85        free(im);
86        return NULL;
87    }
88
89    if(u16fread(fp) != 0x4d42)
90    {
91        fclose(fp);
92        free(im);
93        return NULL;
94    }
95
96    u32fread(fp); /* size */
97    u16fread(fp); /* reserved 1 */
98    u16fread(fp); /* reserved 2 */
99
100    offset = u32fread(fp);
101
102    tmp = u32fread(fp); /* header size */
103    if(tmp == 40)
104    {
105        im->w = u32fread(fp);
106        im->h = u32fread(fp);
107        planes = u16fread(fp);
108        bpp = u16fread(fp);
109
110        tmp = u32fread(fp); /* compression */
111        if(tmp != 0)
112        {
113            fclose(fp);
114            free(im);
115            return NULL;
116        }
117
118        u32fread(fp); /* sizeimage */
119        u32fread(fp); /* xpelspermeter */
120        u32fread(fp); /* ypelspermeter */
121        u32fread(fp); /* biclrused */
122        u32fread(fp); /* biclrimportantn */
123
124        colors = (offset - 54) / 4;
125        for(i = 0; i < colors && i < 256; i++)
126        {
127            blue[i] = u8fread(fp) * 16;
128            green[i] = u8fread(fp) * 16;
129            red[i] = u8fread(fp) * 16;
130            alpha[i] = 0;
131            u8fread(fp);
132        }
133    }
134    else if(tmp == 12)
135    {
136        im->w = u32fread(fp);
137        im->h = u32fread(fp);
138        planes = u16fread(fp);
139        bpp = u16fread(fp);
140
141        colors = (offset - 26) / 3;
142        for(i = 0; i < colors && i < 256; i++)
143        {
144            blue[i] = u8fread(fp);
145            green[i] = u8fread(fp);
146            red[i] = u8fread(fp);
147            alpha[i] = 0;
148        }
149    }
150    else
151    {
152        fclose(fp);
153        free(im);
154        return NULL;
155    }
156
157    /* Fill the rest of the palette */
158    for(i = colors; i < 256; i++)
159        blue[i] = green[i] = red[i] = alpha[i] = 0;
160
161    depth = (bpp + 7) / 8;
162
163    /* Sanity check */
164    if(!im->w || im->w > 0x10000 || !im->h || im->h > 0x10000 || planes != 1)
165    {
166        fclose(fp);
167        free(im);
168        return NULL;
169    }
170
171    /* Allocate the pixel buffer */
172    im->pixels = malloc(im->w * im->h * depth);
173    if(!im->pixels)
174    {
175        fclose(fp);
176        free(im);
177        return NULL;
178    }
179
180    memset(im->pixels, 0, im->w * im->h * depth);
181
182    /* Read the bitmap data */
183    for(i = im->h; i--; )
184    {
185        unsigned int j, k, bits = 0;
186
187        switch(bpp)
188        {
189            case 1:
190                for(j = 0; j < im->w; j++)
191                {
192                    k = j % 32;
193                    if(k == 0)
194                        bits = u32fread(fp);
195                    im->pixels[im->w * i * depth + j] =
196                        (bits >> ((k & ~0xf) + 0xf - (k & 0xf))) & 0x1;
197                }
198                break;
199            case 4:
200                for(j = 0; j < im->w; j++)
201                {
202                    k = j % 8;
203                    if(k == 0)
204                        bits = u32fread(fp);
205                    im->pixels[im->w * i * depth + j] =
206                        (bits >> (4 * ((k & ~0x1) + 0x1 - (k & 0x1)))) & 0xf;
207                }
208                break;
209            default:
210                /* Works for 8bpp, but also for 16, 24 etc. */
211                fread(im->pixels + im->w * i * depth, im->w * depth, 1, fp);
212                /* Pad reads to 4 bytes */
213                tmp = (im->w * depth) % 4;
214                tmp = (4 - tmp) % 4;
215                while(tmp--)
216                    u8fread(fp);
217                break;
218        }
219    }
220
221    switch(depth)
222    {
223    case 3:
224        rmask = 0xff0000;
225        gmask = 0x00ff00;
226        bmask = 0x0000ff;
227        amask = 0x000000;
228        break;
229    case 2: /* XXX: those are the 16 bits values */
230        rmask = 0x7c00;
231        gmask = 0x03e0;
232        bmask = 0x001f;
233        amask = 0x0000;
234        break;
235    case 1:
236    default:
237        bpp = 8;
238        rmask = gmask = bmask = amask = 0;
239        break;
240    }
241
242    fclose(fp);
243
244    /* Create the libcucul dither */
245    im->dither = cucul_create_dither(bpp, im->w, im->h, depth * im->w,
246                                     rmask, gmask, bmask, amask);
247    if(!im->dither)
248    {
249        free(im->pixels);
250        free(im);
251        return NULL;
252    }
253
254    if(bpp == 8)
255        cucul_set_dither_palette(im->dither, red, green, blue, alpha);
256#endif
257
258    return im;
259}
260
261void unload_image(struct image * im)
262{
263#if defined(HAVE_IMLIB2_H)
264    /* Imlib_Image image = (Imlib_Image)im->priv; */
265    imlib_free_image();
266#else
267    free(im->pixels);
268#endif
269    cucul_free_dither(im->dither);
270}
271
272#if !defined(HAVE_IMLIB2_H)
273static unsigned int u32fread(FILE *fp)
274{
275    unsigned char buffer[4];
276    fread(buffer, 4, 1, fp);
277    return ((unsigned int)buffer[3] << 24) | ((unsigned int)buffer[2] << 16)
278             | ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]);
279}
280
281static unsigned int u16fread(FILE *fp)
282{
283    unsigned char buffer[2];
284    fread(buffer, 2, 1, fp);
285    return ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]);
286}
287
288static unsigned int u8fread(FILE *fp)
289{
290    unsigned char buffer;
291    fread(&buffer, 1, 1, fp);
292    return (unsigned int)buffer;
293}
294#endif
295
Note: See TracBrowser for help on using the repository browser.