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

Last change on this file since 4333 was 4333, checked in by Sam Hocevar, 12 years ago

Large source code cleanup, getting rid of spaces, tabs, and svn keywords.

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