You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

301 lines
6.9 KiB

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