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

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