Access.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * The Python Imaging Library
  3. * $Id$
  4. *
  5. * imaging access objects
  6. *
  7. * Copyright (c) Fredrik Lundh 2009.
  8. *
  9. * See the README file for information on usage and redistribution.
  10. */
  11. #include "Imaging.h"
  12. /* use make_hash.py from the pillow-scripts repository to calculate these values */
  13. #define ACCESS_TABLE_SIZE 35
  14. #define ACCESS_TABLE_HASH 8940
  15. static struct ImagingAccessInstance access_table[ACCESS_TABLE_SIZE];
  16. static inline UINT32
  17. hash(const char *mode) {
  18. UINT32 i = ACCESS_TABLE_HASH;
  19. while (*mode) {
  20. i = ((i << 5) + i) ^ (UINT8)*mode++;
  21. }
  22. return i % ACCESS_TABLE_SIZE;
  23. }
  24. static ImagingAccess
  25. add_item(const char *mode) {
  26. UINT32 i = hash(mode);
  27. /* printf("hash %s => %d\n", mode, i); */
  28. if (access_table[i].mode && strcmp(access_table[i].mode, mode) != 0) {
  29. fprintf(
  30. stderr,
  31. "AccessInit: hash collision: %d for both %s and %s\n",
  32. i,
  33. mode,
  34. access_table[i].mode);
  35. exit(1);
  36. }
  37. access_table[i].mode = mode;
  38. return &access_table[i];
  39. }
  40. /* fetch individual pixel */
  41. static void
  42. get_pixel_32_2bands(Imaging im, int x, int y, void *color) {
  43. char *out = color;
  44. UINT8 *p = (UINT8 *)&im->image32[y][x];
  45. out[0] = p[0];
  46. out[1] = p[3];
  47. }
  48. static void
  49. get_pixel_8(Imaging im, int x, int y, void *color) {
  50. char *out = color;
  51. out[0] = im->image8[y][x];
  52. }
  53. static void
  54. get_pixel_16L(Imaging im, int x, int y, void *color) {
  55. UINT8 *in = (UINT8 *)&im->image[y][x + x];
  56. #ifdef WORDS_BIGENDIAN
  57. UINT16 out = in[0] + (in[1] << 8);
  58. memcpy(color, &out, sizeof(out));
  59. #else
  60. memcpy(color, in, sizeof(UINT16));
  61. #endif
  62. }
  63. static void
  64. get_pixel_16B(Imaging im, int x, int y, void *color) {
  65. UINT8 *in = (UINT8 *)&im->image[y][x + x];
  66. #ifdef WORDS_BIGENDIAN
  67. memcpy(color, in, sizeof(UINT16));
  68. #else
  69. UINT16 out = in[1] + (in[0] << 8);
  70. memcpy(color, &out, sizeof(out));
  71. #endif
  72. }
  73. static void
  74. get_pixel_16(Imaging im, int x, int y, void *color) {
  75. UINT8 *in = (UINT8 *)&im->image[y][x + x];
  76. memcpy(color, in, sizeof(UINT16));
  77. }
  78. static void
  79. get_pixel_BGR15(Imaging im, int x, int y, void *color) {
  80. UINT8 *in = (UINT8 *)&im->image8[y][x * 2];
  81. UINT16 pixel = in[0] + (in[1] << 8);
  82. char *out = color;
  83. out[0] = (pixel & 31) * 255 / 31;
  84. out[1] = ((pixel >> 5) & 31) * 255 / 31;
  85. out[2] = ((pixel >> 10) & 31) * 255 / 31;
  86. }
  87. static void
  88. get_pixel_BGR16(Imaging im, int x, int y, void *color) {
  89. UINT8 *in = (UINT8 *)&im->image8[y][x * 2];
  90. UINT16 pixel = in[0] + (in[1] << 8);
  91. char *out = color;
  92. out[0] = (pixel & 31) * 255 / 31;
  93. out[1] = ((pixel >> 5) & 63) * 255 / 63;
  94. out[2] = ((pixel >> 11) & 31) * 255 / 31;
  95. }
  96. static void
  97. get_pixel_BGR24(Imaging im, int x, int y, void *color) {
  98. memcpy(color, &im->image8[y][x * 3], sizeof(UINT8) * 3);
  99. }
  100. static void
  101. get_pixel_32(Imaging im, int x, int y, void *color) {
  102. memcpy(color, &im->image32[y][x], sizeof(INT32));
  103. }
  104. static void
  105. get_pixel_32L(Imaging im, int x, int y, void *color) {
  106. UINT8 *in = (UINT8 *)&im->image[y][x * 4];
  107. #ifdef WORDS_BIGENDIAN
  108. INT32 out = in[0] + (in[1] << 8) + (in[2] << 16) + (in[3] << 24);
  109. memcpy(color, &out, sizeof(out));
  110. #else
  111. memcpy(color, in, sizeof(INT32));
  112. #endif
  113. }
  114. static void
  115. get_pixel_32B(Imaging im, int x, int y, void *color) {
  116. UINT8 *in = (UINT8 *)&im->image[y][x * 4];
  117. #ifdef WORDS_BIGENDIAN
  118. memcpy(color, in, sizeof(INT32));
  119. #else
  120. INT32 out = in[3] + (in[2] << 8) + (in[1] << 16) + (in[0] << 24);
  121. memcpy(color, &out, sizeof(out));
  122. #endif
  123. }
  124. /* store individual pixel */
  125. static void
  126. put_pixel_8(Imaging im, int x, int y, const void *color) {
  127. im->image8[y][x] = *((UINT8 *)color);
  128. }
  129. static void
  130. put_pixel_16L(Imaging im, int x, int y, const void *color) {
  131. memcpy(&im->image8[y][x + x], color, 2);
  132. }
  133. static void
  134. put_pixel_16B(Imaging im, int x, int y, const void *color) {
  135. const char *in = color;
  136. UINT8 *out = (UINT8 *)&im->image8[y][x + x];
  137. out[0] = in[1];
  138. out[1] = in[0];
  139. }
  140. static void
  141. put_pixel_BGR1516(Imaging im, int x, int y, const void *color) {
  142. memcpy(&im->image8[y][x * 2], color, 2);
  143. }
  144. static void
  145. put_pixel_BGR24(Imaging im, int x, int y, const void *color) {
  146. memcpy(&im->image8[y][x * 3], color, 3);
  147. }
  148. static void
  149. put_pixel_32L(Imaging im, int x, int y, const void *color) {
  150. memcpy(&im->image8[y][x * 4], color, 4);
  151. }
  152. static void
  153. put_pixel_32B(Imaging im, int x, int y, const void *color) {
  154. const char *in = color;
  155. UINT8 *out = (UINT8 *)&im->image8[y][x * 4];
  156. out[0] = in[3];
  157. out[1] = in[2];
  158. out[2] = in[1];
  159. out[3] = in[0];
  160. }
  161. static void
  162. put_pixel_32(Imaging im, int x, int y, const void *color) {
  163. memcpy(&im->image32[y][x], color, sizeof(INT32));
  164. }
  165. void
  166. ImagingAccessInit() {
  167. #define ADD(mode_, get_pixel_, put_pixel_) \
  168. { \
  169. ImagingAccess access = add_item(mode_); \
  170. access->get_pixel = get_pixel_; \
  171. access->put_pixel = put_pixel_; \
  172. }
  173. /* populate access table */
  174. ADD("1", get_pixel_8, put_pixel_8);
  175. ADD("L", get_pixel_8, put_pixel_8);
  176. ADD("LA", get_pixel_32_2bands, put_pixel_32);
  177. ADD("La", get_pixel_32_2bands, put_pixel_32);
  178. ADD("I", get_pixel_32, put_pixel_32);
  179. ADD("I;16", get_pixel_16L, put_pixel_16L);
  180. ADD("I;16L", get_pixel_16L, put_pixel_16L);
  181. ADD("I;16B", get_pixel_16B, put_pixel_16B);
  182. ADD("I;16N", get_pixel_16, put_pixel_16L);
  183. ADD("I;32L", get_pixel_32L, put_pixel_32L);
  184. ADD("I;32B", get_pixel_32B, put_pixel_32B);
  185. ADD("F", get_pixel_32, put_pixel_32);
  186. ADD("P", get_pixel_8, put_pixel_8);
  187. ADD("PA", get_pixel_32_2bands, put_pixel_32);
  188. ADD("BGR;15", get_pixel_BGR15, put_pixel_BGR1516);
  189. ADD("BGR;16", get_pixel_BGR16, put_pixel_BGR1516);
  190. ADD("BGR;24", get_pixel_BGR24, put_pixel_BGR24);
  191. ADD("RGB", get_pixel_32, put_pixel_32);
  192. ADD("RGBA", get_pixel_32, put_pixel_32);
  193. ADD("RGBa", get_pixel_32, put_pixel_32);
  194. ADD("RGBX", get_pixel_32, put_pixel_32);
  195. ADD("CMYK", get_pixel_32, put_pixel_32);
  196. ADD("YCbCr", get_pixel_32, put_pixel_32);
  197. ADD("LAB", get_pixel_32, put_pixel_32);
  198. ADD("HSV", get_pixel_32, put_pixel_32);
  199. }
  200. ImagingAccess
  201. ImagingAccessNew(Imaging im) {
  202. ImagingAccess access = &access_table[hash(im->mode)];
  203. if (im->mode[0] != access->mode[0] || strcmp(im->mode, access->mode) != 0) {
  204. return NULL;
  205. }
  206. return access;
  207. }
  208. void
  209. _ImagingAccessDelete(Imaging im, ImagingAccess access) {}