mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-27 18:36:17 +03:00
264 lines
7.1 KiB
C
264 lines
7.1 KiB
C
|
/*
|
||
|
* The Python Imaging Library
|
||
|
* $Id$
|
||
|
*
|
||
|
* point (pixel) translation
|
||
|
*
|
||
|
* history:
|
||
|
* 1995-11-27 fl Created
|
||
|
* 1996-03-31 fl Fixed colour support
|
||
|
* 1996-08-13 fl Support 8-bit to "1" thresholding
|
||
|
* 1997-05-31 fl Added floating point transform
|
||
|
* 1998-07-02 fl Added integer point transform
|
||
|
* 1998-07-17 fl Support L to anything lookup
|
||
|
* 2004-12-18 fl Refactored; added I to L lookup
|
||
|
*
|
||
|
* Copyright (c) 1997-2004 by Secret Labs AB.
|
||
|
* Copyright (c) 1995-2004 by Fredrik Lundh.
|
||
|
*
|
||
|
* See the README file for information on usage and redistribution.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include "Imaging.h"
|
||
|
|
||
|
typedef struct {
|
||
|
const void* table;
|
||
|
} im_point_context;
|
||
|
|
||
|
static void
|
||
|
im_point_8_8(Imaging imOut, Imaging imIn, im_point_context* context)
|
||
|
{
|
||
|
int x, y;
|
||
|
/* 8-bit source, 8-bit destination */
|
||
|
UINT8* table = (UINT8*) context->table;
|
||
|
for (y = 0; y < imIn->ysize; y++) {
|
||
|
UINT8* in = imIn->image8[y];
|
||
|
UINT8* out = imOut->image8[y];
|
||
|
for (x = 0; x < imIn->xsize; x++)
|
||
|
out[x] = table[in[x]];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
im_point_2x8_2x8(Imaging imOut, Imaging imIn, im_point_context* context)
|
||
|
{
|
||
|
int x, y;
|
||
|
/* 2x8-bit source, 2x8-bit destination */
|
||
|
UINT8* table = (UINT8*) context->table;
|
||
|
for (y = 0; y < imIn->ysize; y++) {
|
||
|
UINT8* in = (UINT8*) imIn->image[y];
|
||
|
UINT8* out = (UINT8*) imOut->image[y];
|
||
|
for (x = 0; x < imIn->xsize; x++) {
|
||
|
out[0] = table[in[0]];
|
||
|
out[3] = table[in[3]+256];
|
||
|
in += 4; out += 4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
im_point_3x8_3x8(Imaging imOut, Imaging imIn, im_point_context* context)
|
||
|
{
|
||
|
int x, y;
|
||
|
/* 3x8-bit source, 3x8-bit destination */
|
||
|
UINT8* table = (UINT8*) context->table;
|
||
|
for (y = 0; y < imIn->ysize; y++) {
|
||
|
UINT8* in = (UINT8*) imIn->image[y];
|
||
|
UINT8* out = (UINT8*) imOut->image[y];
|
||
|
for (x = 0; x < imIn->xsize; x++) {
|
||
|
out[0] = table[in[0]];
|
||
|
out[1] = table[in[1]+256];
|
||
|
out[2] = table[in[2]+512];
|
||
|
in += 4; out += 4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
im_point_4x8_4x8(Imaging imOut, Imaging imIn, im_point_context* context)
|
||
|
{
|
||
|
int x, y;
|
||
|
/* 4x8-bit source, 4x8-bit destination */
|
||
|
UINT8* table = (UINT8*) context->table;
|
||
|
for (y = 0; y < imIn->ysize; y++) {
|
||
|
UINT8* in = (UINT8*) imIn->image[y];
|
||
|
UINT8* out = (UINT8*) imOut->image[y];
|
||
|
for (x = 0; x < imIn->xsize; x++) {
|
||
|
out[0] = table[in[0]];
|
||
|
out[1] = table[in[1]+256];
|
||
|
out[2] = table[in[2]+512];
|
||
|
out[3] = table[in[3]+768];
|
||
|
in += 4; out += 4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
im_point_8_32(Imaging imOut, Imaging imIn, im_point_context* context)
|
||
|
{
|
||
|
int x, y;
|
||
|
/* 8-bit source, 32-bit destination */
|
||
|
INT32* table = (INT32*) context->table;
|
||
|
for (y = 0; y < imIn->ysize; y++) {
|
||
|
UINT8* in = imIn->image8[y];
|
||
|
INT32* out = imOut->image32[y];
|
||
|
for (x = 0; x < imIn->xsize; x++)
|
||
|
out[x] = table[in[x]];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
im_point_32_8(Imaging imOut, Imaging imIn, im_point_context* context)
|
||
|
{
|
||
|
int x, y;
|
||
|
/* 32-bit source, 8-bit destination */
|
||
|
UINT8* table = (UINT8*) context->table;
|
||
|
for (y = 0; y < imIn->ysize; y++) {
|
||
|
INT32* in = imIn->image32[y];
|
||
|
UINT8* out = imOut->image8[y];
|
||
|
for (x = 0; x < imIn->xsize; x++) {
|
||
|
int v = in[x];
|
||
|
if (v < 0)
|
||
|
v = 0;
|
||
|
else if (v > 65535)
|
||
|
v = 65535;
|
||
|
out[x] = table[v];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Imaging
|
||
|
ImagingPoint(Imaging imIn, const char* mode, const void* table)
|
||
|
{
|
||
|
/* lookup table transform */
|
||
|
|
||
|
ImagingSectionCookie cookie;
|
||
|
Imaging imOut;
|
||
|
im_point_context context;
|
||
|
void (*point)(Imaging imIn, Imaging imOut, im_point_context* context);
|
||
|
|
||
|
if (!imIn)
|
||
|
return (Imaging) ImagingError_ModeError();
|
||
|
|
||
|
if (!mode)
|
||
|
mode = imIn->mode;
|
||
|
|
||
|
if (imIn->type != IMAGING_TYPE_UINT8) {
|
||
|
if (imIn->type != IMAGING_TYPE_INT32 || strcmp(mode, "L") != 0)
|
||
|
goto mode_mismatch;
|
||
|
} else if (!imIn->image8 && strcmp(imIn->mode, mode) != 0)
|
||
|
goto mode_mismatch;
|
||
|
|
||
|
imOut = ImagingNew(mode, imIn->xsize, imIn->ysize);
|
||
|
if (!imOut)
|
||
|
return NULL;
|
||
|
|
||
|
/* find appropriate handler */
|
||
|
if (imIn->type == IMAGING_TYPE_UINT8) {
|
||
|
if (imIn->bands == imOut->bands && imIn->type == imOut->type) {
|
||
|
switch (imIn->bands) {
|
||
|
case 1:
|
||
|
point = im_point_8_8;
|
||
|
break;
|
||
|
case 2:
|
||
|
point = im_point_2x8_2x8;
|
||
|
break;
|
||
|
case 3:
|
||
|
point = im_point_3x8_3x8;
|
||
|
break;
|
||
|
case 4:
|
||
|
point = im_point_4x8_4x8;
|
||
|
break;
|
||
|
default:
|
||
|
/* this cannot really happen */
|
||
|
point = im_point_8_8;
|
||
|
break;
|
||
|
}
|
||
|
} else
|
||
|
point = im_point_8_32;
|
||
|
} else
|
||
|
point = im_point_32_8;
|
||
|
|
||
|
ImagingCopyInfo(imOut, imIn);
|
||
|
|
||
|
ImagingSectionEnter(&cookie);
|
||
|
|
||
|
context.table = table;
|
||
|
point(imOut, imIn, &context);
|
||
|
|
||
|
ImagingSectionLeave(&cookie);
|
||
|
|
||
|
return imOut;
|
||
|
|
||
|
mode_mismatch:
|
||
|
return (Imaging) ImagingError_ValueError(
|
||
|
"point operation not supported for this mode"
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
Imaging
|
||
|
ImagingPointTransform(Imaging imIn, double scale, double offset)
|
||
|
{
|
||
|
/* scale/offset transform */
|
||
|
|
||
|
ImagingSectionCookie cookie;
|
||
|
Imaging imOut;
|
||
|
int x, y;
|
||
|
|
||
|
if (!imIn || (strcmp(imIn->mode, "I") != 0 &&
|
||
|
strcmp(imIn->mode, "I;16") != 0 &&
|
||
|
strcmp(imIn->mode, "F") != 0))
|
||
|
return (Imaging) ImagingError_ModeError();
|
||
|
|
||
|
imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
|
||
|
if (!imOut)
|
||
|
return NULL;
|
||
|
|
||
|
ImagingCopyInfo(imOut, imIn);
|
||
|
|
||
|
switch (imIn->type) {
|
||
|
case IMAGING_TYPE_INT32:
|
||
|
ImagingSectionEnter(&cookie);
|
||
|
for (y = 0; y < imIn->ysize; y++) {
|
||
|
INT32* in = imIn->image32[y];
|
||
|
INT32* out = imOut->image32[y];
|
||
|
/* FIXME: add clipping? */
|
||
|
for (x = 0; x < imIn->xsize; x++)
|
||
|
out[x] = in[x] * scale + offset;
|
||
|
}
|
||
|
ImagingSectionLeave(&cookie);
|
||
|
break;
|
||
|
case IMAGING_TYPE_FLOAT32:
|
||
|
ImagingSectionEnter(&cookie);
|
||
|
for (y = 0; y < imIn->ysize; y++) {
|
||
|
FLOAT32* in = (FLOAT32*) imIn->image32[y];
|
||
|
FLOAT32* out = (FLOAT32*) imOut->image32[y];
|
||
|
for (x = 0; x < imIn->xsize; x++)
|
||
|
out[x] = in[x] * scale + offset;
|
||
|
}
|
||
|
ImagingSectionLeave(&cookie);
|
||
|
break;
|
||
|
case IMAGING_TYPE_SPECIAL:
|
||
|
if (strcmp(imIn->mode,"I;16") == 0) {
|
||
|
ImagingSectionEnter(&cookie);
|
||
|
for (y = 0; y < imIn->ysize; y++) {
|
||
|
UINT16* in = (UINT16 *)imIn->image[y];
|
||
|
UINT16* out = (UINT16 *)imOut->image[y];
|
||
|
/* FIXME: add clipping? */
|
||
|
for (x = 0; x < imIn->xsize; x++)
|
||
|
out[x] = in[x] * scale + offset;
|
||
|
}
|
||
|
ImagingSectionLeave(&cookie);
|
||
|
break;
|
||
|
}
|
||
|
/* FALL THROUGH */
|
||
|
default:
|
||
|
ImagingDelete(imOut);
|
||
|
return (Imaging) ImagingError_ValueError("internal error");
|
||
|
}
|
||
|
|
||
|
return imOut;
|
||
|
}
|