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

Last change on this file since 2821 was 2821, checked in by Sam Hocevar, 11 years ago

Starting refactoring to get rid of libcucul. The initial reason for the
split is rendered moot by the plugin system: when enabled, binaries do
not link directly with libX11 or libGL. I hope this is a step towards
more consisteny and clarity.

  • 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@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: common-image.c 2821 2008-09-27 13:12:46Z sam $
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15#include "config.h"
16
17#if !defined(__KERNEL__)
18#   include <string.h>
19#   include <stdlib.h>
20#endif
21
22#if defined(USE_IMLIB2)
23#   include <Imlib2.h>
24#endif
25
26#include "caca.h"
27
28#include "common-image.h"
29
30#if !defined(USE_IMLIB2)
31static unsigned int u32fread(caca_file_t *);
32static unsigned int u16fread(caca_file_t *);
33static unsigned int u8fread(caca_file_t *);
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(USE_IMLIB2)
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 libcaca dither */
65    im->dither = caca_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    caca_file_t *f;
81
82    f = caca_file_open(name, "rb");
83    if(!f)
84    {
85        free(im);
86        return NULL;
87    }
88
89    if(u16fread(f) != 0x4d42)
90    {
91        caca_file_close(f);
92        free(im);
93        return NULL;
94    }
95
96    u32fread(f); /* size */
97    u16fread(f); /* reserved 1 */
98    u16fread(f); /* reserved 2 */
99
100    offset = u32fread(f);
101
102    tmp = u32fread(f); /* header size */
103    if(tmp == 40)
104    {
105        im->w = u32fread(f);
106        im->h = u32fread(f);
107        planes = u16fread(f);
108        bpp = u16fread(f);
109
110        tmp = u32fread(f); /* compression */
111        if(tmp != 0)
112        {
113            caca_file_close(f);
114            free(im);
115            return NULL;
116        }
117
118        u32fread(f); /* sizeimage */
119        u32fread(f); /* xpelspermeter */
120        u32fread(f); /* ypelspermeter */
121        u32fread(f); /* biclrused */
122        u32fread(f); /* biclrimportantn */
123
124        colors = (offset - 54) / 4;
125        for(i = 0; i < colors && i < 256; i++)
126        {
127            blue[i] = u8fread(f) * 16;
128            green[i] = u8fread(f) * 16;
129            red[i] = u8fread(f) * 16;
130            alpha[i] = 0;
131            u8fread(f);
132        }
133    }
134    else if(tmp == 12)
135    {
136        im->w = u32fread(f);
137        im->h = u32fread(f);
138        planes = u16fread(f);
139        bpp = u16fread(f);
140
141        colors = (offset - 26) / 3;
142        for(i = 0; i < colors && i < 256; i++)
143        {
144            blue[i] = u8fread(f);
145            green[i] = u8fread(f);
146            red[i] = u8fread(f);
147            alpha[i] = 0;
148        }
149    }
150    else
151    {
152        caca_file_close(f);
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        caca_file_close(f);
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        caca_file_close(f);
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(f);
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(f);
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                caca_file_read(f, im->pixels + im->w * i * depth,
212                                im->w * depth);
213                /* Pad reads to 4 bytes */
214                tmp = (im->w * depth) % 4;
215                tmp = (4 - tmp) % 4;
216                while(tmp--)
217                    u8fread(f);
218                break;
219        }
220    }
221
222    switch(depth)
223    {
224    case 3:
225        rmask = 0xff0000;
226        gmask = 0x00ff00;
227        bmask = 0x0000ff;
228        amask = 0x000000;
229        break;
230    case 2: /* XXX: those are the 16 bits values */
231        rmask = 0x7c00;
232        gmask = 0x03e0;
233        bmask = 0x001f;
234        amask = 0x0000;
235        break;
236    case 1:
237    default:
238        bpp = 8;
239        rmask = gmask = bmask = amask = 0;
240        break;
241    }
242
243    caca_file_close(f);
244
245    /* Create the libcaca dither */
246    im->dither = caca_create_dither(bpp, im->w, im->h, depth * im->w,
247                                     rmask, gmask, bmask, amask);
248    if(!im->dither)
249    {
250        free(im->pixels);
251        free(im);
252        return NULL;
253    }
254
255    if(bpp == 8)
256        caca_set_dither_palette(im->dither, red, green, blue, alpha);
257#endif
258
259    return im;
260}
261
262void unload_image(struct image * im)
263{
264#if defined(USE_IMLIB2)
265    /* Imlib_Image image = (Imlib_Image)im->priv; */
266    imlib_free_image();
267#else
268    free(im->pixels);
269#endif
270    caca_free_dither(im->dither);
271}
272
273#if !defined(USE_IMLIB2)
274static unsigned int u32fread(caca_file_t * f)
275{
276    uint8_t buffer[4];
277    caca_file_read(f, buffer, 4);
278    return ((unsigned int)buffer[3] << 24) | ((unsigned int)buffer[2] << 16)
279             | ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]);
280}
281
282static unsigned int u16fread(caca_file_t * f)
283{
284    uint8_t buffer[2];
285    caca_file_read(f, buffer, 2);
286    return ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]);
287}
288
289static unsigned int u8fread(caca_file_t * f)
290{
291    uint8_t buffer;
292    caca_file_read(f, &buffer, 1);
293    return (unsigned int)buffer;
294}
295#endif
296
Note: See TracBrowser for help on using the repository browser.