[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 2821 2008-09-27 13:12:46Z 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 | |
---|
[2821] | 26 | #include "caca.h" |
---|
[2299] | 27 | |
---|
[739] | 28 | #include "common-image.h" |
---|
[215] | 29 | |
---|
[1255] | 30 | #if !defined(USE_IMLIB2) |
---|
[2821] | 31 | static unsigned int u32fread(caca_file_t *); |
---|
| 32 | static unsigned int u16fread(caca_file_t *); |
---|
| 33 | static unsigned int u8fread(caca_file_t *); |
---|
[254] | 34 | #endif |
---|
[246] | 35 | |
---|
[739] | 36 | struct 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 | |
---|
[2821] | 64 | /* Create the libcaca dither */ |
---|
| 65 | im->dither = caca_create_dither(bpp, im->w, im->h, depth * im->w, |
---|
[739] | 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; |
---|
[2821] | 80 | caca_file_t *f; |
---|
[254] | 81 | |
---|
[2821] | 82 | f = caca_file_open(name, "rb"); |
---|
[2411] | 83 | if(!f) |
---|
[739] | 84 | { |
---|
| 85 | free(im); |
---|
| 86 | return NULL; |
---|
| 87 | } |
---|
[254] | 88 | |
---|
[2411] | 89 | if(u16fread(f) != 0x4d42) |
---|
[254] | 90 | { |
---|
[2821] | 91 | caca_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 | { |
---|
[2821] | 113 | caca_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 | { |
---|
[2821] | 152 | caca_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 | { |
---|
[2821] | 166 | caca_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 | { |
---|
[2821] | 175 | caca_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. */ |
---|
[2821] | 211 | caca_file_read(f, im->pixels + im->w * i * depth, |
---|
[2411] | 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 | |
---|
[2821] | 243 | caca_file_close(f); |
---|
[254] | 244 | |
---|
[2821] | 245 | /* Create the libcaca dither */ |
---|
| 246 | im->dither = caca_create_dither(bpp, im->w, im->h, depth * im->w, |
---|
[739] | 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) |
---|
[2821] | 256 | caca_set_dither_palette(im->dither, red, green, blue, alpha); |
---|
[254] | 257 | #endif |
---|
[739] | 258 | |
---|
| 259 | return im; |
---|
[233] | 260 | } |
---|
| 261 | |
---|
[739] | 262 | void 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 |
---|
[2821] | 270 | caca_free_dither(im->dither); |
---|
[246] | 271 | } |
---|
| 272 | |
---|
[1255] | 273 | #if !defined(USE_IMLIB2) |
---|
[2821] | 274 | static unsigned int u32fread(caca_file_t * f) |
---|
[254] | 275 | { |
---|
[2300] | 276 | uint8_t buffer[4]; |
---|
[2821] | 277 | caca_file_read(f, buffer, 4); |
---|
[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 | |
---|
[2821] | 282 | static unsigned int u16fread(caca_file_t * f) |
---|
[254] | 283 | { |
---|
[2300] | 284 | uint8_t buffer[2]; |
---|
[2821] | 285 | caca_file_read(f, buffer, 2); |
---|
[740] | 286 | return ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]); |
---|
[254] | 287 | } |
---|
| 288 | |
---|
[2821] | 289 | static unsigned int u8fread(caca_file_t * f) |
---|
[254] | 290 | { |
---|
[2300] | 291 | uint8_t buffer; |
---|
[2821] | 292 | caca_file_read(f, &buffer, 1); |
---|
[740] | 293 | return (unsigned int)buffer; |
---|
[254] | 294 | } |
---|
| 295 | #endif |
---|
| 296 | |
---|