/* * 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 */ #define ACCESS_TABLE_SIZE 21 #define ACCESS_TABLE_HASH 30197 static struct ImagingAccessInstance access_table[ACCESS_TABLE_SIZE]; static inline UINT32 hash(const char* mode) { UINT32 i = ACCESS_TABLE_HASH; while (*mode) i = ((i<<5) + i) ^ (UINT8) *mode++; return i % ACCESS_TABLE_SIZE; } static ImagingAccess add_item(const char* mode) { UINT32 i = hash(mode); /* printf("hash %s => %d\n", mode, i); */ if (access_table[i].mode) { 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]; INT16* out = color; #ifdef WORDS_BIGENDIAN out[0] = in[0] + (in[1]<<8); #else out[0] = *(INT16*) in; #endif } static void get_pixel_16B(Imaging im, int x, int y, void* color) { UINT8* in = (UINT8*) &im->image[y][x+x]; INT16* out = color; #ifdef WORDS_BIGENDIAN out[0] = *(INT16*) in; #else out[0] = in[1] + (in[0]<<8); #endif } static void get_pixel_32(Imaging im, int x, int y, void* color) { INT32* out = color; out[0] = im->image32[y][x]; } static void get_pixel_32L(Imaging im, int x, int y, void* color) { UINT8* in = (UINT8*) &im->image[y][x*4]; INT32* out = color; #ifdef WORDS_BIGENDIAN out[0] = in[0] + (in[1]<<8) + (in[2]<<16) + (in[3]<<24); #else out[0] = *(INT32*) in; #endif } static void get_pixel_32B(Imaging im, int x, int y, void* color) { UINT8* in = (UINT8*) &im->image[y][x*4]; INT32* out = color; #ifdef WORDS_BIGENDIAN out[0] = *(INT32*) in; #else out[0] = in[3] + (in[2]<<8) + (in[1]<<16) + (in[0]<<24); #endif } /* store individual pixel */ static void put_pixel(Imaging im, int x, int y, const void* color) { if (im->image8) im->image8[y][x] = *((UINT8*) color); else im->image32[y][x] = *((INT32*) color); } 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) { const char* in = color; UINT8* out = (UINT8*) &im->image8[y][x+x]; out[0] = in[0]; out[1] = in[1]; } 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) { const char* in = color; UINT8* out = (UINT8*) &im->image8[y][x*4]; out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; } 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) { im->image32[y][x] = *((INT32*) color); } 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); 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); } ImagingAccess ImagingAccessNew(Imaging im) { ImagingAccess access = &access_table[hash(im->mode)]; if (im->mode[0] != access->mode[0] || strcmp(im->mode, access->mode) != 0) return NULL; return access; } void _ImagingAccessDelete(Imaging im, ImagingAccess access) { }