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 Tests/make_hash.py 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
|
|
|
|
hash(const char* mode)
|
|
|
|
{
|
|
|
|
UINT32 i = ACCESS_TABLE_HASH;
|
2020-05-10 12:56:36 +03:00
|
|
|
while (*mode) {
|
2010-07-31 06:52:47 +04: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
|
|
|
|
add_item(const char* mode)
|
|
|
|
{
|
|
|
|
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) {
|
2010-07-31 06:52:47 +04:00
|
|
|
fprintf(stderr, "AccessInit: hash collision: %d for both %s and %s\n",
|
|
|
|
i, mode, access_table[i].mode);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
access_table[i].mode = mode;
|
|
|
|
return &access_table[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fetch pointer to pixel line */
|
|
|
|
|
|
|
|
static void*
|
|
|
|
line_8(Imaging im, int x, int y)
|
|
|
|
{
|
|
|
|
return &im->image8[y][x];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
line_16(Imaging im, int x, int y)
|
|
|
|
{
|
|
|
|
return &im->image8[y][x+x];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
line_32(Imaging im, int x, int y)
|
|
|
|
{
|
|
|
|
return &im->image32[y][x];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fetch individual pixel */
|
|
|
|
|
|
|
|
static void
|
|
|
|
get_pixel(Imaging im, int x, int y, void* color)
|
|
|
|
{
|
|
|
|
char* out = color;
|
|
|
|
|
|
|
|
/* generic pixel access*/
|
|
|
|
|
|
|
|
if (im->image8) {
|
|
|
|
out[0] = im->image8[y][x];
|
|
|
|
} else {
|
|
|
|
UINT8* p = (UINT8*) &im->image32[y][x];
|
|
|
|
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
|
|
|
|
get_pixel_8(Imaging im, int x, int y, void* color)
|
|
|
|
{
|
|
|
|
char* out = color;
|
|
|
|
out[0] = im->image8[y][x];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
get_pixel_16L(Imaging im, int x, int y, void* color)
|
|
|
|
{
|
|
|
|
UINT8* in = (UINT8*) &im->image[y][x+x];
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
2018-07-01 13:47:59 +03:00
|
|
|
UINT16 out = in[0] + (in[1]<<8);
|
|
|
|
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
|
|
|
|
get_pixel_16B(Imaging im, int x, int y, void* color)
|
|
|
|
{
|
|
|
|
UINT8* in = (UINT8*) &im->image[y][x+x];
|
|
|
|
#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
|
2018-07-01 13:47:59 +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
|
|
|
|
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
|
|
|
|
get_pixel_32L(Imaging im, int x, int y, void* color)
|
|
|
|
{
|
|
|
|
UINT8* in = (UINT8*) &im->image[y][x*4];
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
2018-07-01 13:47:59 +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
|
2018-06-29 23:33:08 +03:00
|
|
|
memcpy(color, in, sizeof(INT32));
|
2010-07-31 06:52:47 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
get_pixel_32B(Imaging im, int x, int y, void* color)
|
|
|
|
{
|
|
|
|
UINT8* in = (UINT8*) &im->image[y][x*4];
|
|
|
|
#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
|
2018-07-01 13:47:59 +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
|
|
|
|
put_pixel(Imaging im, int x, int y, const void* color)
|
|
|
|
{
|
2020-05-10 12:56:36 +03:00
|
|
|
if (im->image8) {
|
2010-07-31 06:52:47 +04: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
|
|
|
|
put_pixel_8(Imaging im, int x, int y, const void* color)
|
|
|
|
{
|
|
|
|
im->image8[y][x] = *((UINT8*) color);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
put_pixel_16L(Imaging im, int x, int y, const void* color)
|
|
|
|
{
|
2018-06-29 23:33:08 +03:00
|
|
|
memcpy(&im->image8[y][x+x], color, 2);
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
put_pixel_16B(Imaging im, int x, int y, const void* color)
|
|
|
|
{
|
|
|
|
const char* in = color;
|
|
|
|
UINT8* out = (UINT8*) &im->image8[y][x+x];
|
|
|
|
out[0] = in[1];
|
|
|
|
out[1] = in[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
put_pixel_32L(Imaging im, int x, int y, const void* color)
|
|
|
|
{
|
2018-06-29 23:33:08 +03:00
|
|
|
memcpy(&im->image8[y][x*4], color, 4);
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
put_pixel_32B(Imaging im, int x, int y, const void* color)
|
|
|
|
{
|
|
|
|
const char* in = color;
|
|
|
|
UINT8* out = (UINT8*) &im->image8[y][x*4];
|
|
|
|
out[0] = in[3];
|
|
|
|
out[1] = in[2];
|
|
|
|
out[2] = in[1];
|
|
|
|
out[3] = in[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
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
|
|
|
|
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_; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
ImagingAccessNew(Imaging im)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
_ImagingAccessDelete(Imaging im, ImagingAccess access)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|