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

Last change on this file since 2411 was 2411, checked in by Sam Hocevar, 12 years ago
  • Make cacaview use cucul_file_t functions.
  • Property svn:keywords set to Id
File size: 7.0 KB
RevLine 
[215]1/*
[739]2 *  Imaging tools for cacaview and img2irc
[769]3 *  Copyright (c) 2003-2006 Sam Hocevar <sam@zoy.org>
[268]4 *                All Rights Reserved
[215]5 *
[268]6 *  $Id: common-image.c 2411 2008-06-15 13:50:28Z sam $
[215]7 *
[1462]8 *  This program is free software. It comes without any warranty, to
[1452]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
[522]12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
[215]13 */
14
15#include "config.h"
16
[1048]17#if !defined(__KERNEL__)
18#   include <string.h>
19#   include <stdlib.h>
20#endif
[215]21
[1255]22#if defined(USE_IMLIB2)
[254]23#   include <Imlib2.h>
24#endif
[215]25
[524]26#include "cucul.h"
[2299]27
[739]28#include "common-image.h"
[215]29
[1255]30#if !defined(USE_IMLIB2)
[2411]31static unsigned int u32fread(cucul_file_t *);
32static unsigned int u16fread(cucul_file_t *);
33static unsigned int u8fread(cucul_file_t *);
[254]34#endif
[246]35
[739]36struct image * load_image(char const * name)
[215]37{
[739]38    struct image * im = malloc(sizeof(struct image));
39    unsigned int depth, bpp, rmask, gmask, bmask, amask;
[215]40
[1255]41#if defined(USE_IMLIB2)
[739]42    Imlib_Image image;
[299]43
[233]44    /* Load the new image */
45    image = imlib_load_image(name);
46
47    if(!image)
[739]48    {
49        free(im);
50        return NULL;
51    }
[233]52
53    imlib_context_set_image(image);
[739]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();
[254]57    rmask = 0x00ff0000;
58    gmask = 0x0000ff00;
59    bmask = 0x000000ff;
60    amask = 0xff000000;
61    bpp = 32;
62    depth = 4;
[233]63
[734]64    /* Create the libcucul dither */
[739]65    im->dither = cucul_create_dither(bpp, im->w, im->h, depth * im->w,
66                                     rmask, gmask, bmask, amask);
67    if(!im->dither)
[233]68    {
69        imlib_free_image();
[739]70        free(im);
71        return NULL;
[233]72    }
[254]73
[739]74    im->priv = (void *)image;
75
[254]76#else
77    /* Try to load a BMP file */
[739]78    unsigned int red[256], green[256], blue[256], alpha[256];
79    unsigned int i, colors, offset, tmp, planes;
[2411]80    cucul_file_t *f;
[254]81
[2411]82    f = cucul_file_open(name, "rb");
83    if(!f)
[739]84    {
85        free(im);
86        return NULL;
87    }
[254]88
[2411]89    if(u16fread(f) != 0x4d42)
[254]90    {
[2411]91        cucul_file_close(f);
[739]92        free(im);
93        return NULL;
[254]94    }
95
[2411]96    u32fread(f); /* size */
97    u16fread(f); /* reserved 1 */
98    u16fread(f); /* reserved 2 */
[254]99
[2411]100    offset = u32fread(f);
[254]101
[2411]102    tmp = u32fread(f); /* header size */
[254]103    if(tmp == 40)
104    {
[2411]105        im->w = u32fread(f);
106        im->h = u32fread(f);
107        planes = u16fread(f);
108        bpp = u16fread(f);
[254]109
[2411]110        tmp = u32fread(f); /* compression */
[254]111        if(tmp != 0)
112        {
[2411]113            cucul_file_close(f);
[739]114            free(im);
115            return NULL;
[254]116        }
117
[2411]118        u32fread(f); /* sizeimage */
119        u32fread(f); /* xpelspermeter */
120        u32fread(f); /* ypelspermeter */
121        u32fread(f); /* biclrused */
122        u32fread(f); /* biclrimportantn */
[254]123
124        colors = (offset - 54) / 4;
125        for(i = 0; i < colors && i < 256; i++)
126        {
[2411]127            blue[i] = u8fread(f) * 16;
128            green[i] = u8fread(f) * 16;
129            red[i] = u8fread(f) * 16;
[254]130            alpha[i] = 0;
[2411]131            u8fread(f);
[254]132        }
133    }
134    else if(tmp == 12)
135    {
[2411]136        im->w = u32fread(f);
137        im->h = u32fread(f);
138        planes = u16fread(f);
139        bpp = u16fread(f);
[254]140
141        colors = (offset - 26) / 3;
142        for(i = 0; i < colors && i < 256; i++)
143        {
[2411]144            blue[i] = u8fread(f);
145            green[i] = u8fread(f);
146            red[i] = u8fread(f);
[254]147            alpha[i] = 0;
148        }
149    }
150    else
151    {
[2411]152        cucul_file_close(f);
[739]153        free(im);
154        return NULL;
[254]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 */
[739]164    if(!im->w || im->w > 0x10000 || !im->h || im->h > 0x10000 || planes != 1)
[254]165    {
[2411]166        cucul_file_close(f);
[739]167        free(im);
168        return NULL;
[254]169    }
170
171    /* Allocate the pixel buffer */
[739]172    im->pixels = malloc(im->w * im->h * depth);
173    if(!im->pixels)
[254]174    {
[2411]175        cucul_file_close(f);
[739]176        free(im);
177        return NULL;
[254]178    }
179
[739]180    memset(im->pixels, 0, im->w * im->h * depth);
[254]181
[739]182    /* Read the bitmap data */
183    for(i = im->h; i--; )
[254]184    {
185        unsigned int j, k, bits = 0;
186
187        switch(bpp)
188        {
189            case 1:
[739]190                for(j = 0; j < im->w; j++)
[254]191                {
192                    k = j % 32;
193                    if(k == 0)
[2411]194                        bits = u32fread(f);
[739]195                    im->pixels[im->w * i * depth + j] =
[255]196                        (bits >> ((k & ~0xf) + 0xf - (k & 0xf))) & 0x1;
[254]197                }
198                break;
199            case 4:
[739]200                for(j = 0; j < im->w; j++)
[254]201                {
202                    k = j % 8;
203                    if(k == 0)
[2411]204                        bits = u32fread(f);
[739]205                    im->pixels[im->w * i * depth + j] =
[254]206                        (bits >> (4 * ((k & ~0x1) + 0x1 - (k & 0x1)))) & 0xf;
207                }
208                break;
209            default:
[255]210                /* Works for 8bpp, but also for 16, 24 etc. */
[2411]211                cucul_file_read(f, im->pixels + im->w * i * depth,
212                                im->w * depth);
[254]213                /* Pad reads to 4 bytes */
[739]214                tmp = (im->w * depth) % 4;
[255]215                tmp = (4 - tmp) % 4;
[254]216                while(tmp--)
[2411]217                    u8fread(f);
[254]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
[2411]243    cucul_file_close(f);
[254]244
[734]245    /* Create the libcucul dither */
[739]246    im->dither = cucul_create_dither(bpp, im->w, im->h, depth * im->w,
247                                     rmask, gmask, bmask, amask);
248    if(!im->dither)
[254]249    {
[739]250        free(im->pixels);
251        free(im);
252        return NULL;
[254]253    }
254
255    if(bpp == 8)
[739]256        cucul_set_dither_palette(im->dither, red, green, blue, alpha);
[254]257#endif
[739]258
259    return im;
[233]260}
261
[739]262void unload_image(struct image * im)
[246]263{
[1255]264#if defined(USE_IMLIB2)
[739]265    /* Imlib_Image image = (Imlib_Image)im->priv; */
266    imlib_free_image();
267#else
268    free(im->pixels);
269#endif
270    cucul_free_dither(im->dither);
[246]271}
272
[1255]273#if !defined(USE_IMLIB2)
[2411]274static unsigned int u32fread(cucul_file_t * f)
[254]275{
[2300]276    uint8_t buffer[4];
[2411]277    cucul_file_read(buffer, 4, 1, fp);
[740]278    return ((unsigned int)buffer[3] << 24) | ((unsigned int)buffer[2] << 16)
279             | ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]);
[254]280}
281
[2411]282static unsigned int u16fread(cucul_file_t * f)
[254]283{
[2300]284    uint8_t buffer[2];
[2411]285    cucul_file_read(buffer, 2, 1, fp);
[740]286    return ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]);
[254]287}
288
[2411]289static unsigned int u8fread(cucul_file_t * f)
[254]290{
[2300]291    uint8_t buffer;
[2411]292    cucul_file_read(&buffer, 1, 1, fp);
[740]293    return (unsigned int)buffer;
[254]294}
295#endif
296
Note: See TracBrowser for help on using the repository browser.