Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

297 lignes
7.1 KiB

  1. /*
  2. * Imaging tools for cacaview and img2irc
  3. * Copyright © 2002—2021 Sam Hocevar <sam@hocevar.net>
  4. * All Rights Reserved
  5. *
  6. * This program is free software. It comes without any warranty, to
  7. * the extent permitted by applicable law. You can redistribute it
  8. * and/or modify it under the terms of the Do What the Fuck You Want
  9. * to Public License, Version 2, as published by the WTFPL Task Force.
  10. * See http://www.wtfpl.net/ for more details.
  11. */
  12. #include "config.h"
  13. #if !defined(__KERNEL__)
  14. # include <string.h>
  15. # include <stdlib.h>
  16. #endif
  17. #if defined(USE_IMLIB2)
  18. # include <Imlib2.h>
  19. #endif
  20. #include "caca.h"
  21. #include "common-image.h"
  22. #if !defined(USE_IMLIB2)
  23. static unsigned int u32fread(caca_file_t *);
  24. static unsigned int u16fread(caca_file_t *);
  25. static unsigned int u8fread(caca_file_t *);
  26. static void *_caca_alloc2d(size_t width, size_t height, size_t elem_size)
  27. {
  28. if (width == 0 || height == 0 || elem_size == 0 || SIZE_MAX / width / height < elem_size)
  29. return NULL;
  30. return malloc(width * height * elem_size);
  31. }
  32. #endif
  33. struct image * load_image(char const * name)
  34. {
  35. struct image * im = malloc(sizeof(struct image));
  36. unsigned int rmask, gmask, bmask, amask;
  37. #if defined(USE_IMLIB2)
  38. Imlib_Image image;
  39. /* Load the new image */
  40. image = imlib_load_image(name);
  41. if(!image)
  42. {
  43. free(im);
  44. return NULL;
  45. }
  46. imlib_context_set_image(image);
  47. im->pixels = (char *)imlib_image_get_data_for_reading_only();
  48. im->w = imlib_image_get_width();
  49. im->h = imlib_image_get_height();
  50. rmask = 0x00ff0000;
  51. gmask = 0x0000ff00;
  52. bmask = 0x000000ff;
  53. amask = 0xff000000;
  54. uint32_t bpp = 32;
  55. uint32_t depth = 4;
  56. /* Create the libcaca dither */
  57. im->dither = caca_create_dither(bpp, im->w, im->h, depth * im->w,
  58. rmask, gmask, bmask, amask);
  59. if(!im->dither)
  60. {
  61. imlib_free_image();
  62. free(im);
  63. return NULL;
  64. }
  65. im->priv = (void *)image;
  66. #else
  67. /* Try to load a BMP file */
  68. uint32_t red[256], green[256], blue[256], alpha[256];
  69. unsigned int tmp;
  70. caca_file_t *f = caca_file_open(name, "rb");
  71. if (!f)
  72. {
  73. free(im);
  74. return NULL;
  75. }
  76. if (u16fread(f) != 0x4d42)
  77. {
  78. caca_file_close(f);
  79. free(im);
  80. return NULL;
  81. }
  82. u32fread(f); /* size */
  83. u16fread(f); /* reserved 1 */
  84. u16fread(f); /* reserved 2 */
  85. uint32_t offset = u32fread(f);
  86. uint32_t header_size = u32fread(f); /* header size */
  87. im->w = u32fread(f);
  88. im->h = u32fread(f);
  89. uint32_t planes = u16fread(f);
  90. uint32_t bpp = u16fread(f);
  91. uint32_t colors = 0;
  92. /* Sanity check */
  93. if (planes != 1)
  94. {
  95. caca_file_close(f);
  96. free(im);
  97. return NULL;
  98. }
  99. if (header_size == 40)
  100. {
  101. if (u32fread(f) != 0) /* compression */
  102. {
  103. caca_file_close(f);
  104. free(im);
  105. return NULL;
  106. }
  107. u32fread(f); /* sizeimage */
  108. u32fread(f); /* xpelspermeter */
  109. u32fread(f); /* ypelspermeter */
  110. u32fread(f); /* biclrused */
  111. u32fread(f); /* biclrimportantn */
  112. colors = (offset - 54) / 4;
  113. for (uint32_t i = 0; i < colors && i < 256; i++)
  114. {
  115. blue[i] = u8fread(f) * 16;
  116. green[i] = u8fread(f) * 16;
  117. red[i] = u8fread(f) * 16;
  118. alpha[i] = 0;
  119. u8fread(f);
  120. }
  121. }
  122. else if (header_size == 12)
  123. {
  124. colors = (offset - 26) / 3;
  125. for (uint32_t i = 0; i < colors && i < 256; i++)
  126. {
  127. blue[i] = u8fread(f);
  128. green[i] = u8fread(f);
  129. red[i] = u8fread(f);
  130. alpha[i] = 0;
  131. }
  132. }
  133. else
  134. {
  135. caca_file_close(f);
  136. free(im);
  137. return NULL;
  138. }
  139. /* Fill the rest of the palette */
  140. for (uint32_t i = colors; i < 256; i++)
  141. blue[i] = green[i] = red[i] = alpha[i] = 0;
  142. uint32_t depth = (bpp + 7) / 8;
  143. /* Allocate the pixel buffer */
  144. im->pixels = _caca_alloc2d(im->w, im->h, depth);
  145. if (!im->pixels)
  146. {
  147. caca_file_close(f);
  148. free(im);
  149. return NULL;
  150. }
  151. memset(im->pixels, 0, im->w * im->h * depth);
  152. /* Read the bitmap data */
  153. for (size_t y = im->h; y--; )
  154. {
  155. uint32_t bits = 0;
  156. switch (bpp)
  157. {
  158. case 1:
  159. for (size_t x = 0; x < im->w; x++)
  160. {
  161. size_t k = x % 32;
  162. if (k == 0)
  163. bits = u32fread(f);
  164. im->pixels[im->w * y * depth + x] =
  165. (bits >> ((k & ~0xf) + 0xf - (k & 0xf))) & 0x1;
  166. }
  167. break;
  168. case 4:
  169. for (size_t x = 0; x < im->w; x++)
  170. {
  171. size_t k = x % 8;
  172. if (k == 0)
  173. bits = u32fread(f);
  174. im->pixels[im->w * y * depth + x] =
  175. (bits >> (4 * ((k & ~0x1) + 0x1 - (k & 0x1)))) & 0xf;
  176. }
  177. break;
  178. default:
  179. /* Works for 8bpp, but also for 16, 24 etc. */
  180. caca_file_read(f, im->pixels + im->w * y * depth,
  181. im->w * depth);
  182. /* Pad reads to 4 bytes */
  183. tmp = (im->w * depth) % 4;
  184. tmp = (4 - tmp) % 4;
  185. while (tmp--)
  186. u8fread(f);
  187. break;
  188. }
  189. }
  190. switch(depth)
  191. {
  192. case 3:
  193. rmask = 0xff0000;
  194. gmask = 0x00ff00;
  195. bmask = 0x0000ff;
  196. amask = 0x000000;
  197. break;
  198. case 2: /* XXX: those are the 16 bits values */
  199. rmask = 0x7c00;
  200. gmask = 0x03e0;
  201. bmask = 0x001f;
  202. amask = 0x0000;
  203. break;
  204. case 1:
  205. default:
  206. bpp = 8;
  207. rmask = gmask = bmask = amask = 0;
  208. break;
  209. }
  210. caca_file_close(f);
  211. /* Create the libcaca dither */
  212. im->dither = caca_create_dither(bpp, im->w, im->h, depth * im->w,
  213. rmask, gmask, bmask, amask);
  214. if(!im->dither)
  215. {
  216. free(im->pixels);
  217. free(im);
  218. return NULL;
  219. }
  220. if (bpp == 8)
  221. caca_set_dither_palette(im->dither, red, green, blue, alpha);
  222. #endif
  223. return im;
  224. }
  225. void unload_image(struct image * im)
  226. {
  227. #if defined(USE_IMLIB2)
  228. /* Imlib_Image image = (Imlib_Image)im->priv; */
  229. imlib_free_image();
  230. #else
  231. free(im->pixels);
  232. #endif
  233. caca_free_dither(im->dither);
  234. }
  235. #if !defined(USE_IMLIB2)
  236. static unsigned int u32fread(caca_file_t * f)
  237. {
  238. uint8_t buffer[4] = { 0 };
  239. caca_file_read(f, buffer, 4);
  240. return ((unsigned int)buffer[3] << 24) | ((unsigned int)buffer[2] << 16)
  241. | ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]);
  242. }
  243. static unsigned int u16fread(caca_file_t * f)
  244. {
  245. uint8_t buffer[2] = { 0 };
  246. caca_file_read(f, buffer, 2);
  247. return ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]);
  248. }
  249. static unsigned int u8fread(caca_file_t * f)
  250. {
  251. uint8_t buffer[1] = { 0 };
  252. caca_file_read(f, buffer, 1);
  253. return (unsigned int)buffer[0];
  254. }
  255. #endif