Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

276 строки
8.2 KiB

  1. /*
  2. * libpipi Pathetic image processing interface library
  3. * Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library 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. /*
  15. * pixels.c: pixel-level image manipulation
  16. */
  17. #include "config.h"
  18. #include "common.h"
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <math.h>
  23. #include "pipi.h"
  24. #include "pipi_internals.h"
  25. static void init_tables(void);
  26. static double global_gamma = 2.2;
  27. static int done = 0;
  28. static float u8tof32_table[256];
  29. static inline float u8tof32(uint8_t p) { return u8tof32_table[(int)p]; }
  30. /* Return a direct pointer to an image's pixels. */
  31. pipi_pixels_t *pipi_getpixels(pipi_image_t *img, pipi_format_t type)
  32. {
  33. size_t bytes = 0;
  34. int x, y, i, bpp = 0;
  35. if(type < 0 || type >= PIPI_PIXELS_MAX)
  36. return NULL;
  37. if(img->last_modified == type)
  38. return &img->p[type];
  39. /* Handle special cases */
  40. if(type == PIPI_PIXELS_MASK_C)
  41. return &img->p[type];
  42. /* Preliminary conversions */
  43. if(img->last_modified == PIPI_PIXELS_RGBA_C
  44. && type == PIPI_PIXELS_Y_F)
  45. pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
  46. else if(img->last_modified == PIPI_PIXELS_BGR_C
  47. && type == PIPI_PIXELS_Y_F)
  48. pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
  49. else if(img->last_modified == PIPI_PIXELS_Y_F
  50. && type == PIPI_PIXELS_RGBA_C)
  51. pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
  52. else if(img->last_modified == PIPI_PIXELS_Y_F
  53. && type == PIPI_PIXELS_BGR_C)
  54. pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
  55. /* Allocate pixels if necessary */
  56. if(!img->p[type].pixels)
  57. {
  58. switch(type)
  59. {
  60. case PIPI_PIXELS_RGBA_C:
  61. bytes = img->w * img->h * 4 * sizeof(uint8_t);
  62. bpp = 4 * sizeof(uint8_t);
  63. break;
  64. case PIPI_PIXELS_BGR_C:
  65. bytes = img->w * img->h * 3 * sizeof(uint8_t);
  66. bpp = 3 * sizeof(uint8_t);
  67. break;
  68. case PIPI_PIXELS_RGBA_F:
  69. bytes = img->w * img->h * 4 * sizeof(float);
  70. bpp = 4 * sizeof(float);
  71. break;
  72. case PIPI_PIXELS_Y_F:
  73. bytes = img->w * img->h * sizeof(float);
  74. bpp = sizeof(float);
  75. break;
  76. default:
  77. return NULL;
  78. }
  79. img->p[type].pixels = malloc(bytes);
  80. img->p[type].bytes = bytes;
  81. img->p[type].bpp = bpp;
  82. img->p[type].w = img->w;
  83. img->p[type].h = img->h;
  84. }
  85. /* Convert pixels */
  86. if(img->last_modified == PIPI_PIXELS_RGBA_C
  87. && type == PIPI_PIXELS_RGBA_F)
  88. {
  89. uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_RGBA_C].pixels;
  90. float *dest = (float *)img->p[type].pixels;
  91. init_tables();
  92. for(y = 0; y < img->h; y++)
  93. for(x = 0; x < img->w; x++)
  94. for(i = 0; i < 4; i++)
  95. dest[4 * (y * img->w + x) + i]
  96. = u8tof32(src[4 * (y * img->w + x) + i]);
  97. }
  98. else if(img->last_modified == PIPI_PIXELS_BGR_C
  99. && type == PIPI_PIXELS_RGBA_F)
  100. {
  101. uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_BGR_C].pixels;
  102. float *dest = (float *)img->p[type].pixels;
  103. init_tables();
  104. for(y = 0; y < img->h; y++)
  105. for(x = 0; x < img->w; x++)
  106. {
  107. dest[4 * (y * img->w + x)]
  108. = u8tof32(src[3 * (y * img->w + x) + 2]);
  109. dest[4 * (y * img->w + x) + 1]
  110. = u8tof32(src[3 * (y * img->w + x) + 1]);
  111. dest[4 * (y * img->w + x) + 2]
  112. = u8tof32(src[3 * (y * img->w + x)]);
  113. dest[4 * (y * img->w + x) + 3] = 1.0;
  114. }
  115. }
  116. else if(img->last_modified == PIPI_PIXELS_RGBA_F
  117. && type == PIPI_PIXELS_RGBA_C)
  118. {
  119. float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
  120. uint8_t *dest = (uint8_t *)img->p[type].pixels;
  121. init_tables();
  122. for(y = 0; y < img->h; y++)
  123. for(x = 0; x < img->w; x++)
  124. for(i = 0; i < 4; i++)
  125. {
  126. double p, e;
  127. uint8_t d;
  128. p = src[4 * (y * img->w + x) + i];
  129. if(p < 0.) d = 0.;
  130. else if(p > 1.) d = 255;
  131. else d = (int)(255.999 * pow(p, 1. / global_gamma));
  132. dest[4 * (y * img->w + x) + i] = d;
  133. e = (p - u8tof32(d)) / 16;
  134. if(x < img->w - 1)
  135. src[4 * (y * img->w + x + 1) + i] += e * 7;
  136. if(y < img->h - 1)
  137. {
  138. if(x > 0)
  139. src[4 * ((y + 1) * img->w + x - 1) + i] += e * 3;
  140. src[4 * ((y + 1) * img->w + x) + i] += e * 5;
  141. if(x < img->w - 1)
  142. src[4 * ((y + 1) * img->w + x + 1) + i] += e;
  143. }
  144. }
  145. }
  146. else if(img->last_modified == PIPI_PIXELS_RGBA_F
  147. && type == PIPI_PIXELS_BGR_C)
  148. {
  149. float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
  150. uint8_t *dest = (uint8_t *)img->p[type].pixels;
  151. init_tables();
  152. for(y = 0; y < img->h; y++)
  153. for(x = 0; x < img->w; x++)
  154. for(i = 0; i < 3; i++)
  155. {
  156. double p, e;
  157. uint8_t d;
  158. p = src[4 * (y * img->w + x) + i];
  159. if(p < 0.) d = 0.;
  160. else if(p > 1.) d = 255;
  161. else d = (int)(255.999 * pow(p, 1. / global_gamma));
  162. dest[3 * (y * img->w + x) + i] = d;
  163. e = (p - u8tof32(d)) / 16;
  164. if(x < img->w - 1)
  165. src[4 * (y * img->w + x + 1) + i] += e * 7;
  166. if(y < img->h - 1)
  167. {
  168. if(x > 0)
  169. src[4 * ((y + 1) * img->w + x - 1) + i] += e * 3;
  170. src[4 * ((y + 1) * img->w + x) + i] += e * 5;
  171. if(x < img->w - 1)
  172. src[4 * ((y + 1) * img->w + x + 1) + i] += e;
  173. }
  174. }
  175. }
  176. else if(img->last_modified == PIPI_PIXELS_Y_F
  177. && type == PIPI_PIXELS_RGBA_F)
  178. {
  179. float *src = (float *)img->p[PIPI_PIXELS_Y_F].pixels;
  180. float *dest = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
  181. init_tables();
  182. for(y = 0; y < img->h; y++)
  183. for(x = 0; x < img->w; x++)
  184. {
  185. float p = src[y * img->w + x];
  186. dest[4 * (y * img->w + x)] = p;
  187. dest[4 * (y * img->w + x) + 1] = p;
  188. dest[4 * (y * img->w + x) + 2] = p;
  189. dest[4 * (y * img->w + x) + 3] = 1.0;
  190. }
  191. }
  192. else if(img->last_modified == PIPI_PIXELS_RGBA_F
  193. && type == PIPI_PIXELS_Y_F)
  194. {
  195. float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
  196. float *dest = (float *)img->p[PIPI_PIXELS_Y_F].pixels;
  197. init_tables();
  198. for(y = 0; y < img->h; y++)
  199. for(x = 0; x < img->w; x++)
  200. {
  201. float p = 0.;
  202. p += 0.299 * src[4 * (y * img->w + x)];
  203. p += 0.587 * src[4 * (y * img->w + x) + 1];
  204. p += 0.114 * src[4 * (y * img->w + x) + 2];
  205. dest[y * img->w + x] = p;
  206. }
  207. }
  208. else
  209. {
  210. memset(img->p[type].pixels, 0, bytes);
  211. }
  212. img->last_modified = type;
  213. return &img->p[type];
  214. }
  215. void pipi_set_gamma(double g)
  216. {
  217. if(g > 0.)
  218. {
  219. global_gamma = g;
  220. done = 0;
  221. }
  222. }
  223. static void init_tables(void)
  224. {
  225. int i;
  226. if(done)
  227. return;
  228. for(i = 0; i < 256; i++)
  229. u8tof32_table[i] = pow((double)i / 255., global_gamma);
  230. done = 1;
  231. }