mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-26 01:46:18 +03:00
commit
14859ce506
|
@ -23,6 +23,7 @@ class TestImageConvert(PillowTestCase):
|
||||||
"RGBX",
|
"RGBX",
|
||||||
"CMYK",
|
"CMYK",
|
||||||
"YCbCr",
|
"YCbCr",
|
||||||
|
"HSV",
|
||||||
)
|
)
|
||||||
|
|
||||||
for mode in modes:
|
for mode in modes:
|
||||||
|
|
|
@ -101,6 +101,19 @@ bit2ycbcr(UINT8* out, const UINT8* in, int xsize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bit2hsv(UINT8* out, const UINT8* in, int xsize)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < xsize; x++, out += 4) {
|
||||||
|
UINT8 v = (*in++ != 0) ? 255 : 0;
|
||||||
|
out[0] = 0;
|
||||||
|
out[1] = 0;
|
||||||
|
out[2] = v;
|
||||||
|
out[3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------- */
|
/* ----------------- */
|
||||||
/* RGB/L conversions */
|
/* RGB/L conversions */
|
||||||
/* ----------------- */
|
/* ----------------- */
|
||||||
|
@ -175,6 +188,19 @@ l2rgb(UINT8* out, const UINT8* in, int xsize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
l2hsv(UINT8* out, const UINT8* in, int xsize)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < xsize; x++, out += 4) {
|
||||||
|
UINT8 v = *in++;
|
||||||
|
out[0] = 0;
|
||||||
|
out[1] = 0;
|
||||||
|
out[2] = v;
|
||||||
|
out[3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
la2l(UINT8* out, const UINT8* in, int xsize)
|
la2l(UINT8* out, const UINT8* in, int xsize)
|
||||||
{
|
{
|
||||||
|
@ -196,6 +222,19 @@ la2rgb(UINT8* out, const UINT8* in, int xsize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
la2hsv(UINT8* out, const UINT8* in, int xsize)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < xsize; x++, in += 4, out += 4) {
|
||||||
|
UINT8 v = in[0];
|
||||||
|
out[0] = 0;
|
||||||
|
out[1] = 0;
|
||||||
|
out[2] = v;
|
||||||
|
out[3] = in[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rgb2bit(UINT8* out, const UINT8* in, int xsize)
|
rgb2bit(UINT8* out, const UINT8* in, int xsize)
|
||||||
{
|
{
|
||||||
|
@ -283,54 +322,58 @@ rgb2bgr24(UINT8* out, const UINT8* in, int xsize)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rgb2hsv(UINT8* out, const UINT8* in, int xsize)
|
rgb2hsv_row(UINT8* out, const UINT8* in)
|
||||||
{ // following colorsys.py
|
{ // following colorsys.py
|
||||||
float h,s,rc,gc,bc,cr;
|
float h,s,rc,gc,bc,cr;
|
||||||
UINT8 maxc,minc;
|
UINT8 maxc,minc;
|
||||||
UINT8 r, g, b;
|
UINT8 r, g, b;
|
||||||
UINT8 uh,us,uv;
|
UINT8 uh,us,uv;
|
||||||
int x;
|
|
||||||
|
|
||||||
for (x = 0; x < xsize; x++, in += 4) {
|
r = in[0];
|
||||||
r = in[0];
|
g = in[1];
|
||||||
g = in[1];
|
b = in[2];
|
||||||
b = in[2];
|
maxc = MAX(r,MAX(g,b));
|
||||||
|
minc = MIN(r,MIN(g,b));
|
||||||
maxc = MAX(r,MAX(g,b));
|
uv = maxc;
|
||||||
minc = MIN(r,MIN(g,b));
|
if (minc == maxc){
|
||||||
uv = maxc;
|
uh = 0;
|
||||||
if (minc == maxc){
|
us = 0;
|
||||||
*out++ = 0;
|
} else {
|
||||||
*out++ = 0;
|
cr = (float)(maxc-minc);
|
||||||
*out++ = uv;
|
s = cr/(float)maxc;
|
||||||
|
rc = ((float)(maxc-r))/cr;
|
||||||
|
gc = ((float)(maxc-g))/cr;
|
||||||
|
bc = ((float)(maxc-b))/cr;
|
||||||
|
if (r == maxc) {
|
||||||
|
h = bc-gc;
|
||||||
|
} else if (g == maxc) {
|
||||||
|
h = 2.0 + rc-bc;
|
||||||
} else {
|
} else {
|
||||||
cr = (float)(maxc-minc);
|
h = 4.0 + gc-rc;
|
||||||
s = cr/(float)maxc;
|
|
||||||
rc = ((float)(maxc-r))/cr;
|
|
||||||
gc = ((float)(maxc-g))/cr;
|
|
||||||
bc = ((float)(maxc-b))/cr;
|
|
||||||
if (r == maxc) {
|
|
||||||
h = bc-gc;
|
|
||||||
} else if (g == maxc) {
|
|
||||||
h = 2.0 + rc-bc;
|
|
||||||
} else {
|
|
||||||
h = 4.0 + gc-rc;
|
|
||||||
}
|
|
||||||
// incorrect hue happens if h/6 is negative.
|
|
||||||
h = fmod((h/6.0 + 1.0), 1.0);
|
|
||||||
|
|
||||||
uh = (UINT8)CLIP8((int)(h*255.0));
|
|
||||||
us = (UINT8)CLIP8((int)(s*255.0));
|
|
||||||
|
|
||||||
*out++ = uh;
|
|
||||||
*out++ = us;
|
|
||||||
*out++ = uv;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
*out++ = in[3];
|
// incorrect hue happens if h/6 is negative.
|
||||||
|
h = fmod((h/6.0 + 1.0), 1.0);
|
||||||
|
|
||||||
|
uh = (UINT8)CLIP8((int)(h*255.0));
|
||||||
|
us = (UINT8)CLIP8((int)(s*255.0));
|
||||||
|
}
|
||||||
|
out[0] = uh;
|
||||||
|
out[1] = us;
|
||||||
|
out[2] = uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rgb2hsv(UINT8* out, const UINT8* in, int xsize)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < xsize; x++, in += 4, out += 4) {
|
||||||
|
rgb2hsv_row(out, in);
|
||||||
|
out[3] = in[3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
hsv2rgb(UINT8* out, const UINT8* in, int xsize)
|
hsv2rgb(UINT8* out, const UINT8* in, int xsize)
|
||||||
{ // following colorsys.py
|
{ // following colorsys.py
|
||||||
|
@ -562,6 +605,22 @@ cmyk2rgb(UINT8* out, const UINT8* in, int xsize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmyk2hsv(UINT8* out, const UINT8* in, int xsize)
|
||||||
|
{
|
||||||
|
int x, nk, tmp;
|
||||||
|
for (x = 0; x < xsize; x++) {
|
||||||
|
nk = 255 - in[3];
|
||||||
|
out[0] = CLIP8(nk - MULDIV255(in[0], nk, tmp));
|
||||||
|
out[1] = CLIP8(nk - MULDIV255(in[1], nk, tmp));
|
||||||
|
out[2] = CLIP8(nk - MULDIV255(in[2], nk, tmp));
|
||||||
|
rgb2hsv_row(out, out);
|
||||||
|
out[3] = 255;
|
||||||
|
out += 4;
|
||||||
|
in += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------- */
|
/* ------------- */
|
||||||
/* I conversions */
|
/* I conversions */
|
||||||
/* ------------- */
|
/* ------------- */
|
||||||
|
@ -631,6 +690,25 @@ i2rgb(UINT8* out, const UINT8* in_, int xsize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
i2hsv(UINT8* out, const UINT8* in_, int xsize)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
INT32* in = (INT32*) in_;
|
||||||
|
for (x = 0; x < xsize; x++, in++, out+=4) {
|
||||||
|
out[0] = 0;
|
||||||
|
out[1] = 0;
|
||||||
|
if (*in <= 0) {
|
||||||
|
out[2] = 0;
|
||||||
|
} else if (*in >= 255) {
|
||||||
|
out[2] = 255;
|
||||||
|
} else {
|
||||||
|
out[2] = (UINT8) *in;
|
||||||
|
}
|
||||||
|
out[3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------- */
|
/* ------------- */
|
||||||
/* F conversions */
|
/* F conversions */
|
||||||
/* ------------- */
|
/* ------------- */
|
||||||
|
@ -861,6 +939,7 @@ static struct {
|
||||||
{ "1", "RGBX", bit2rgb },
|
{ "1", "RGBX", bit2rgb },
|
||||||
{ "1", "CMYK", bit2cmyk },
|
{ "1", "CMYK", bit2cmyk },
|
||||||
{ "1", "YCbCr", bit2ycbcr },
|
{ "1", "YCbCr", bit2ycbcr },
|
||||||
|
{ "1", "HSV", bit2hsv },
|
||||||
|
|
||||||
{ "L", "1", l2bit },
|
{ "L", "1", l2bit },
|
||||||
{ "L", "LA", l2la },
|
{ "L", "LA", l2la },
|
||||||
|
@ -871,6 +950,7 @@ static struct {
|
||||||
{ "L", "RGBX", l2rgb },
|
{ "L", "RGBX", l2rgb },
|
||||||
{ "L", "CMYK", l2cmyk },
|
{ "L", "CMYK", l2cmyk },
|
||||||
{ "L", "YCbCr", l2ycbcr },
|
{ "L", "YCbCr", l2ycbcr },
|
||||||
|
{ "L", "HSV", l2hsv },
|
||||||
|
|
||||||
{ "LA", "L", la2l },
|
{ "LA", "L", la2l },
|
||||||
{ "LA", "La", lA2la },
|
{ "LA", "La", lA2la },
|
||||||
|
@ -879,6 +959,7 @@ static struct {
|
||||||
{ "LA", "RGBX", la2rgb },
|
{ "LA", "RGBX", la2rgb },
|
||||||
{ "LA", "CMYK", la2cmyk },
|
{ "LA", "CMYK", la2cmyk },
|
||||||
{ "LA", "YCbCr", la2ycbcr },
|
{ "LA", "YCbCr", la2ycbcr },
|
||||||
|
{ "LA", "HSV", la2hsv },
|
||||||
|
|
||||||
{ "La", "LA", la2lA },
|
{ "La", "LA", la2lA },
|
||||||
|
|
||||||
|
@ -887,6 +968,7 @@ static struct {
|
||||||
{ "I", "RGB", i2rgb },
|
{ "I", "RGB", i2rgb },
|
||||||
{ "I", "RGBA", i2rgb },
|
{ "I", "RGBA", i2rgb },
|
||||||
{ "I", "RGBX", i2rgb },
|
{ "I", "RGBX", i2rgb },
|
||||||
|
{ "I", "HSV", i2hsv },
|
||||||
|
|
||||||
{ "F", "L", f2l },
|
{ "F", "L", f2l },
|
||||||
{ "F", "I", f2i },
|
{ "F", "I", f2i },
|
||||||
|
@ -915,6 +997,7 @@ static struct {
|
||||||
{ "RGBA", "RGBX", rgb2rgba },
|
{ "RGBA", "RGBX", rgb2rgba },
|
||||||
{ "RGBA", "CMYK", rgb2cmyk },
|
{ "RGBA", "CMYK", rgb2cmyk },
|
||||||
{ "RGBA", "YCbCr", ImagingConvertRGB2YCbCr },
|
{ "RGBA", "YCbCr", ImagingConvertRGB2YCbCr },
|
||||||
|
{ "RGBA", "HSV", rgb2hsv },
|
||||||
|
|
||||||
{ "RGBa", "RGBA", rgba2rgbA },
|
{ "RGBa", "RGBA", rgba2rgbA },
|
||||||
|
|
||||||
|
@ -926,10 +1009,12 @@ static struct {
|
||||||
{ "RGBX", "RGB", rgba2rgb },
|
{ "RGBX", "RGB", rgba2rgb },
|
||||||
{ "RGBX", "CMYK", rgb2cmyk },
|
{ "RGBX", "CMYK", rgb2cmyk },
|
||||||
{ "RGBX", "YCbCr", ImagingConvertRGB2YCbCr },
|
{ "RGBX", "YCbCr", ImagingConvertRGB2YCbCr },
|
||||||
|
{ "RGBX", "HSV", rgb2hsv },
|
||||||
|
|
||||||
{ "CMYK", "RGB", cmyk2rgb },
|
{ "CMYK", "RGB", cmyk2rgb },
|
||||||
{ "CMYK", "RGBA", cmyk2rgb },
|
{ "CMYK", "RGBA", cmyk2rgb },
|
||||||
{ "CMYK", "RGBX", cmyk2rgb },
|
{ "CMYK", "RGBX", cmyk2rgb },
|
||||||
|
{ "CMYK", "HSV", cmyk2hsv },
|
||||||
|
|
||||||
{ "YCbCr", "L", ycbcr2l },
|
{ "YCbCr", "L", ycbcr2l },
|
||||||
{ "YCbCr", "LA", ycbcr2la },
|
{ "YCbCr", "LA", ycbcr2la },
|
||||||
|
@ -1101,6 +1186,28 @@ pa2rgb(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
p2hsv(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < xsize; x++, out += 4) {
|
||||||
|
const UINT8* rgb = &palette[*in++ * 4];
|
||||||
|
rgb2hsv_row(out, rgb);
|
||||||
|
out[3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pa2hsv(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < xsize; x++, in += 4, out += 4) {
|
||||||
|
const UINT8* rgb = &palette[in[0] * 4];
|
||||||
|
rgb2hsv_row(out, rgb);
|
||||||
|
out[3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
p2rgba(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
|
p2rgba(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
|
||||||
{
|
{
|
||||||
|
@ -1192,6 +1299,8 @@ frompalette(Imaging imOut, Imaging imIn, const char *mode)
|
||||||
convert = alpha ? pa2cmyk : p2cmyk;
|
convert = alpha ? pa2cmyk : p2cmyk;
|
||||||
else if (strcmp(mode, "YCbCr") == 0)
|
else if (strcmp(mode, "YCbCr") == 0)
|
||||||
convert = alpha ? pa2ycbcr : p2ycbcr;
|
convert = alpha ? pa2ycbcr : p2ycbcr;
|
||||||
|
else if (strcmp(mode, "HSV") == 0)
|
||||||
|
convert = alpha ? pa2hsv : p2hsv;
|
||||||
else
|
else
|
||||||
return (Imaging) ImagingError_ValueError("conversion not supported");
|
return (Imaging) ImagingError_ValueError("conversion not supported");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user