Pillow/src/libImaging/Access.c

215 lines
5.5 KiB
C
Raw Normal View History

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"
/* use make_hash.py from the pillow-scripts repository to calculate these values */
#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];
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); */
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 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);
memcpy(color, &out, sizeof(out));
2010-07-31 06:52:47 +04:00
#else
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
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);
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) {
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);
memcpy(color, &out, sizeof(out));
2010-07-31 06:52:47 +04:00
#else
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
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);
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 {
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) {
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_, get_pixel_, put_pixel_) \
2021-01-03 06:17:51 +03:00
{ \
ImagingAccess access = add_item(mode_); \
access->get_pixel = get_pixel_; \
access->put_pixel = put_pixel_; \
2010-07-31 06:52:47 +04:00
}
/* populate access table */
ADD("1", get_pixel_8, put_pixel_8);
ADD("L", get_pixel_8, put_pixel_8);
ADD("LA", get_pixel, put_pixel);
ADD("La", get_pixel, put_pixel);
ADD("I", get_pixel_32, put_pixel_32);
ADD("I;16", get_pixel_16L, put_pixel_16L);
ADD("I;16L", get_pixel_16L, put_pixel_16L);
ADD("I;16B", get_pixel_16B, put_pixel_16B);
ADD("I;32L", get_pixel_32L, put_pixel_32L);
ADD("I;32B", get_pixel_32B, put_pixel_32B);
ADD("F", get_pixel_32, put_pixel_32);
ADD("P", get_pixel_8, put_pixel_8);
ADD("PA", get_pixel, put_pixel);
ADD("RGB", get_pixel_32, put_pixel_32);
ADD("RGBA", get_pixel_32, put_pixel_32);
ADD("RGBa", get_pixel_32, put_pixel_32);
ADD("RGBX", get_pixel_32, put_pixel_32);
ADD("CMYK", get_pixel_32, put_pixel_32);
ADD("YCbCr", get_pixel_32, put_pixel_32);
ADD("LAB", get_pixel_32, put_pixel_32);
ADD("HSV", 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) {}