2010-07-31 06:52:47 +04:00
|
|
|
/*
|
|
|
|
* The Python Imaging Library
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* imaging access objects
|
|
|
|
*
|
|
|
|
* Copyright (c) Fredrik Lundh 2009.
|
|
|
|
*
|
|
|
|
* See the README file for information on usage and redistribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "Imaging.h"
|
|
|
|
|
2021-08-08 06:08:42 +03:00
|
|
|
/* use make_hash.py from the pillow-scripts repository to calculate these values */
|
2014-07-22 09:31:32 +04:00
|
|
|
#define ACCESS_TABLE_SIZE 27
|
|
|
|
#define ACCESS_TABLE_HASH 3078
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
static struct ImagingAccessInstance access_table[ACCESS_TABLE_SIZE];
|
2013-07-01 02:42:19 +04:00
|
|
|
|
2010-07-31 06:52:47 +04:00
|
|
|
static inline UINT32
|
2021-01-03 06:17:51 +03:00
|
|
|
hash(const char *mode) {
|
2010-07-31 06:52:47 +04:00
|
|
|
UINT32 i = ACCESS_TABLE_HASH;
|
2020-05-10 12:56:36 +03:00
|
|
|
while (*mode) {
|
2021-01-03 06:17:51 +03:00
|
|
|
i = ((i << 5) + i) ^ (UINT8)*mode++;
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
return i % ACCESS_TABLE_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ImagingAccess
|
2021-01-03 06:17:51 +03:00
|
|
|
add_item(const char *mode) {
|
2010-07-31 06:52:47 +04:00
|
|
|
UINT32 i = hash(mode);
|
|
|
|
/* printf("hash %s => %d\n", mode, i); */
|
2016-12-20 18:40:06 +03:00
|
|
|
if (access_table[i].mode && strcmp(access_table[i].mode, mode) != 0) {
|
2021-01-03 06:17:51 +03:00
|
|
|
fprintf(
|
|
|
|
stderr,
|
|
|
|
"AccessInit: hash collision: %d for both %s and %s\n",
|
|
|
|
i,
|
|
|
|
mode,
|
|
|
|
access_table[i].mode);
|
2010-07-31 06:52:47 +04:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
access_table[i].mode = mode;
|
|
|
|
return &access_table[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fetch pointer to pixel line */
|
|
|
|
|
2021-01-03 06:17:51 +03:00
|
|
|
static void *
|
|
|
|
line_8(Imaging im, int x, int y) {
|
2010-07-31 06:52:47 +04:00
|
|
|
return &im->image8[y][x];
|
|
|
|
}
|
|
|
|
|
2021-01-03 06:17:51 +03:00
|
|
|
static void *
|
|
|
|
line_16(Imaging im, int x, int y) {
|
|
|
|
return &im->image8[y][x + x];
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
2021-01-03 06:17:51 +03:00
|
|
|
static void *
|
|
|
|
line_32(Imaging im, int x, int y) {
|
2010-07-31 06:52:47 +04:00
|
|
|
return &im->image32[y][x];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fetch individual pixel */
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
get_pixel(Imaging im, int x, int y, void *color) {
|
|
|
|
char *out = color;
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
/* generic pixel access*/
|
|
|
|
|
|
|
|
if (im->image8) {
|
|
|
|
out[0] = im->image8[y][x];
|
|
|
|
} else {
|
2021-01-03 06:17:51 +03:00
|
|
|
UINT8 *p = (UINT8 *)&im->image32[y][x];
|
2010-07-31 06:52:47 +04:00
|
|
|
if (im->type == IMAGING_TYPE_UINT8 && im->bands == 2) {
|
|
|
|
out[0] = p[0];
|
|
|
|
out[1] = p[3];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
memcpy(out, p, im->pixelsize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
get_pixel_8(Imaging im, int x, int y, void *color) {
|
|
|
|
char *out = color;
|
2010-07-31 06:52:47 +04:00
|
|
|
out[0] = im->image8[y][x];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
get_pixel_16L(Imaging im, int x, int y, void *color) {
|
|
|
|
UINT8 *in = (UINT8 *)&im->image[y][x + x];
|
2010-07-31 06:52:47 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
2021-01-03 06:17:51 +03:00
|
|
|
UINT16 out = in[0] + (in[1] << 8);
|
2018-07-01 13:47:59 +03:00
|
|
|
memcpy(color, &out, sizeof(out));
|
2010-07-31 06:52:47 +04:00
|
|
|
#else
|
2018-06-29 23:33:08 +03:00
|
|
|
memcpy(color, in, sizeof(UINT16));
|
2010-07-31 06:52:47 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
get_pixel_16B(Imaging im, int x, int y, void *color) {
|
|
|
|
UINT8 *in = (UINT8 *)&im->image[y][x + x];
|
2010-07-31 06:52:47 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
2018-06-29 23:33:08 +03:00
|
|
|
memcpy(color, in, sizeof(UINT16));
|
2010-07-31 06:52:47 +04:00
|
|
|
#else
|
2021-01-03 06:17:51 +03:00
|
|
|
UINT16 out = in[1] + (in[0] << 8);
|
2018-07-01 13:47:59 +03:00
|
|
|
memcpy(color, &out, sizeof(out));
|
2010-07-31 06:52:47 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
get_pixel_32(Imaging im, int x, int y, void *color) {
|
2018-06-29 23:33:08 +03:00
|
|
|
memcpy(color, &im->image32[y][x], sizeof(INT32));
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
get_pixel_32L(Imaging im, int x, int y, void *color) {
|
|
|
|
UINT8 *in = (UINT8 *)&im->image[y][x * 4];
|
2010-07-31 06:52:47 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
2021-01-03 06:17:51 +03:00
|
|
|
INT32 out = in[0] + (in[1] << 8) + (in[2] << 16) + (in[3] << 24);
|
2018-07-01 13:47:59 +03:00
|
|
|
memcpy(color, &out, sizeof(out));
|
2010-07-31 06:52:47 +04:00
|
|
|
#else
|
2018-06-29 23:33:08 +03:00
|
|
|
memcpy(color, in, sizeof(INT32));
|
2010-07-31 06:52:47 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
get_pixel_32B(Imaging im, int x, int y, void *color) {
|
|
|
|
UINT8 *in = (UINT8 *)&im->image[y][x * 4];
|
2010-07-31 06:52:47 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
2018-06-29 23:33:08 +03:00
|
|
|
memcpy(color, in, sizeof(INT32));
|
2010-07-31 06:52:47 +04:00
|
|
|
#else
|
2021-01-03 06:17:51 +03:00
|
|
|
INT32 out = in[3] + (in[2] << 8) + (in[1] << 16) + (in[0] << 24);
|
2018-07-01 13:47:59 +03:00
|
|
|
memcpy(color, &out, sizeof(out));
|
2010-07-31 06:52:47 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store individual pixel */
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
put_pixel(Imaging im, int x, int y, const void *color) {
|
2020-05-10 12:56:36 +03:00
|
|
|
if (im->image8) {
|
2021-01-03 06:17:51 +03:00
|
|
|
im->image8[y][x] = *((UINT8 *)color);
|
2020-05-10 12:56:36 +03:00
|
|
|
} else {
|
2018-06-29 23:33:08 +03:00
|
|
|
memcpy(&im->image32[y][x], color, sizeof(INT32));
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
put_pixel_8(Imaging im, int x, int y, const void *color) {
|
|
|
|
im->image8[y][x] = *((UINT8 *)color);
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
put_pixel_16L(Imaging im, int x, int y, const void *color) {
|
|
|
|
memcpy(&im->image8[y][x + x], color, 2);
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
put_pixel_16B(Imaging im, int x, int y, const void *color) {
|
|
|
|
const char *in = color;
|
|
|
|
UINT8 *out = (UINT8 *)&im->image8[y][x + x];
|
2010-07-31 06:52:47 +04:00
|
|
|
out[0] = in[1];
|
|
|
|
out[1] = in[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
put_pixel_32L(Imaging im, int x, int y, const void *color) {
|
|
|
|
memcpy(&im->image8[y][x * 4], color, 4);
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
put_pixel_32B(Imaging im, int x, int y, const void *color) {
|
|
|
|
const char *in = color;
|
|
|
|
UINT8 *out = (UINT8 *)&im->image8[y][x * 4];
|
2010-07-31 06:52:47 +04:00
|
|
|
out[0] = in[3];
|
|
|
|
out[1] = in[2];
|
|
|
|
out[2] = in[1];
|
|
|
|
out[3] = in[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-03 06:17:51 +03:00
|
|
|
put_pixel_32(Imaging im, int x, int y, const void *color) {
|
2018-06-29 23:33:08 +03:00
|
|
|
memcpy(&im->image32[y][x], color, sizeof(INT32));
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-03 06:17:51 +03:00
|
|
|
ImagingAccessInit() {
|
|
|
|
#define ADD(mode_, line_, get_pixel_, put_pixel_) \
|
|
|
|
{ \
|
|
|
|
ImagingAccess access = add_item(mode_); \
|
|
|
|
access->line = line_; \
|
|
|
|
access->get_pixel = get_pixel_; \
|
|
|
|
access->put_pixel = put_pixel_; \
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* populate access table */
|
|
|
|
ADD("1", line_8, get_pixel_8, put_pixel_8);
|
|
|
|
ADD("L", line_8, get_pixel_8, put_pixel_8);
|
|
|
|
ADD("LA", line_32, get_pixel, put_pixel);
|
2016-05-10 21:46:40 +03:00
|
|
|
ADD("La", line_32, get_pixel, put_pixel);
|
2010-07-31 06:52:47 +04:00
|
|
|
ADD("I", line_32, get_pixel_32, put_pixel_32);
|
|
|
|
ADD("I;16", line_16, get_pixel_16L, put_pixel_16L);
|
|
|
|
ADD("I;16L", line_16, get_pixel_16L, put_pixel_16L);
|
|
|
|
ADD("I;16B", line_16, get_pixel_16B, put_pixel_16B);
|
|
|
|
ADD("I;32L", line_32, get_pixel_32L, put_pixel_32L);
|
|
|
|
ADD("I;32B", line_32, get_pixel_32B, put_pixel_32B);
|
|
|
|
ADD("F", line_32, get_pixel_32, put_pixel_32);
|
|
|
|
ADD("P", line_8, get_pixel_8, put_pixel_8);
|
|
|
|
ADD("PA", line_32, get_pixel, put_pixel);
|
|
|
|
ADD("RGB", line_32, get_pixel_32, put_pixel_32);
|
|
|
|
ADD("RGBA", line_32, get_pixel_32, put_pixel_32);
|
|
|
|
ADD("RGBa", line_32, get_pixel_32, put_pixel_32);
|
|
|
|
ADD("RGBX", line_32, get_pixel_32, put_pixel_32);
|
|
|
|
ADD("CMYK", line_32, get_pixel_32, put_pixel_32);
|
|
|
|
ADD("YCbCr", line_32, get_pixel_32, put_pixel_32);
|
2013-10-12 09:29:19 +04:00
|
|
|
ADD("LAB", line_32, get_pixel_32, put_pixel_32);
|
2014-07-22 09:31:32 +04:00
|
|
|
ADD("HSV", line_32, get_pixel_32, put_pixel_32);
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
ImagingAccess
|
2021-01-03 06:17:51 +03:00
|
|
|
ImagingAccessNew(Imaging im) {
|
2010-07-31 06:52:47 +04:00
|
|
|
ImagingAccess access = &access_table[hash(im->mode)];
|
2020-05-10 12:56:36 +03:00
|
|
|
if (im->mode[0] != access->mode[0] || strcmp(im->mode, access->mode) != 0) {
|
2010-07-31 06:52:47 +04:00
|
|
|
return NULL;
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
return access;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-03 06:17:51 +03:00
|
|
|
_ImagingAccessDelete(Imaging im, ImagingAccess access) {}
|