2013-07-01 02:42:19 +04:00
|
|
|
/*
|
2010-07-31 06:52:47 +04:00
|
|
|
* The Python Imaging Library
|
|
|
|
* $Id$
|
2013-07-01 02:42:19 +04:00
|
|
|
*
|
2010-07-31 06:52:47 +04:00
|
|
|
* stuff to extract and paste back individual bands
|
|
|
|
*
|
|
|
|
* history:
|
|
|
|
* 1996-03-20 fl Created
|
|
|
|
* 1997-08-27 fl Fixed putband for single band targets.
|
|
|
|
* 2003-09-26 fl Fixed getband/putband for 2-band images (LA, PA).
|
|
|
|
*
|
|
|
|
* Copyright (c) 1997-2003 by Secret Labs AB.
|
|
|
|
* Copyright (c) 1996-1997 by Fredrik Lundh.
|
|
|
|
*
|
|
|
|
* See the README file for details on usage and redistribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "Imaging.h"
|
|
|
|
|
|
|
|
|
|
|
|
Imaging
|
|
|
|
ImagingGetBand(Imaging imIn, int band)
|
|
|
|
{
|
|
|
|
Imaging imOut;
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
/* Check arguments */
|
2020-05-10 12:56:36 +03:00
|
|
|
if (!imIn || imIn->type != IMAGING_TYPE_UINT8) {
|
2017-08-09 03:48:24 +03:00
|
|
|
return (Imaging) ImagingError_ModeError();
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2020-05-10 12:56:36 +03:00
|
|
|
if (band < 0 || band >= imIn->bands) {
|
2017-08-09 03:48:24 +03:00
|
|
|
return (Imaging) ImagingError_ValueError("band index out of range");
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
/* Shortcuts */
|
2020-05-10 12:56:36 +03:00
|
|
|
if (imIn->bands == 1) {
|
2017-08-09 03:48:24 +03:00
|
|
|
return ImagingCopy(imIn);
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
/* Special case for LXXA etc */
|
2020-05-10 12:56:36 +03:00
|
|
|
if (imIn->bands == 2 && band == 1) {
|
2010-07-31 06:52:47 +04:00
|
|
|
band = 3;
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2017-08-06 13:32:46 +03:00
|
|
|
imOut = ImagingNewDirty("L", imIn->xsize, imIn->ysize);
|
2020-05-10 12:56:36 +03:00
|
|
|
if (!imOut) {
|
2017-08-09 03:48:24 +03:00
|
|
|
return NULL;
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
/* Extract band from image */
|
|
|
|
for (y = 0; y < imIn->ysize; y++) {
|
2017-08-09 03:48:24 +03:00
|
|
|
UINT8* in = (UINT8*) imIn->image[y] + band;
|
|
|
|
UINT8* out = imOut->image8[y];
|
2017-08-12 13:10:26 +03:00
|
|
|
x = 0;
|
|
|
|
for (; x < imIn->xsize - 3; x += 4) {
|
2018-07-01 13:47:59 +03:00
|
|
|
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
|
|
|
memcpy(out + x, &v, sizeof(v));
|
2017-08-12 13:10:26 +03:00
|
|
|
in += 16;
|
|
|
|
}
|
|
|
|
for (; x < imIn->xsize; x++) {
|
2017-08-09 03:48:24 +03:00
|
|
|
out[x] = *in;
|
|
|
|
in += 4;
|
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return imOut;
|
|
|
|
}
|
|
|
|
|
2017-08-12 03:43:19 +03:00
|
|
|
|
|
|
|
int
|
|
|
|
ImagingSplit(Imaging imIn, Imaging bands[4])
|
|
|
|
{
|
2017-08-12 17:42:49 +03:00
|
|
|
int i, j, x, y;
|
2017-08-12 10:13:23 +03:00
|
|
|
|
|
|
|
/* Check arguments */
|
|
|
|
if (!imIn || imIn->type != IMAGING_TYPE_UINT8) {
|
2017-10-02 00:22:22 +03:00
|
|
|
(void) ImagingError_ModeError();
|
2017-08-12 10:13:23 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Shortcuts */
|
|
|
|
if (imIn->bands == 1) {
|
|
|
|
bands[0] = ImagingCopy(imIn);
|
|
|
|
return imIn->bands;
|
|
|
|
}
|
|
|
|
|
2017-08-12 03:43:19 +03:00
|
|
|
for (i = 0; i < imIn->bands; i++) {
|
2017-08-17 03:23:13 +03:00
|
|
|
bands[i] = ImagingNewDirty("L", imIn->xsize, imIn->ysize);
|
2017-08-12 17:42:49 +03:00
|
|
|
if ( ! bands[i]) {
|
|
|
|
for (j = 0; j < i; ++j) {
|
|
|
|
ImagingDelete(bands[j]);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2017-08-12 03:43:19 +03:00
|
|
|
}
|
|
|
|
|
2017-08-12 10:13:23 +03:00
|
|
|
/* Extract bands from image */
|
|
|
|
if (imIn->bands == 2) {
|
|
|
|
for (y = 0; y < imIn->ysize; y++) {
|
|
|
|
UINT8* in = (UINT8*) imIn->image[y];
|
|
|
|
UINT8* out0 = bands[0]->image8[y];
|
|
|
|
UINT8* out1 = bands[1]->image8[y];
|
2017-08-12 15:49:23 +03:00
|
|
|
x = 0;
|
|
|
|
for (; x < imIn->xsize - 3; x += 4) {
|
2018-07-01 13:47:59 +03:00
|
|
|
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
|
|
|
memcpy(out0 + x, &v, sizeof(v));
|
|
|
|
v = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]);
|
|
|
|
memcpy(out1 + x, &v, sizeof(v));
|
2017-08-12 15:49:23 +03:00
|
|
|
in += 16;
|
|
|
|
}
|
|
|
|
for (; x < imIn->xsize; x++) {
|
2017-08-12 10:13:23 +03:00
|
|
|
out0[x] = in[0];
|
|
|
|
out1[x] = in[3];
|
|
|
|
in += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (imIn->bands == 3) {
|
|
|
|
for (y = 0; y < imIn->ysize; y++) {
|
|
|
|
UINT8* in = (UINT8*) imIn->image[y];
|
|
|
|
UINT8* out0 = bands[0]->image8[y];
|
|
|
|
UINT8* out1 = bands[1]->image8[y];
|
|
|
|
UINT8* out2 = bands[2]->image8[y];
|
2017-08-12 15:49:23 +03:00
|
|
|
x = 0;
|
|
|
|
for (; x < imIn->xsize - 3; x += 4) {
|
2018-07-01 13:47:59 +03:00
|
|
|
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
|
|
|
memcpy(out0 + x, &v, sizeof(v));
|
|
|
|
v = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]);
|
|
|
|
memcpy(out1 + x, &v, sizeof(v));
|
|
|
|
v = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]);
|
|
|
|
memcpy(out2 + x, &v, sizeof(v));
|
2017-08-12 15:49:23 +03:00
|
|
|
in += 16;
|
|
|
|
}
|
|
|
|
for (; x < imIn->xsize; x++) {
|
2017-08-12 10:13:23 +03:00
|
|
|
out0[x] = in[0];
|
|
|
|
out1[x] = in[1];
|
|
|
|
out2[x] = in[2];
|
|
|
|
in += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (y = 0; y < imIn->ysize; y++) {
|
|
|
|
UINT8* in = (UINT8*) imIn->image[y];
|
|
|
|
UINT8* out0 = bands[0]->image8[y];
|
|
|
|
UINT8* out1 = bands[1]->image8[y];
|
|
|
|
UINT8* out2 = bands[2]->image8[y];
|
|
|
|
UINT8* out3 = bands[3]->image8[y];
|
2017-08-12 15:49:23 +03:00
|
|
|
x = 0;
|
|
|
|
for (; x < imIn->xsize - 3; x += 4) {
|
2018-07-01 13:47:59 +03:00
|
|
|
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
|
|
|
memcpy(out0 + x, &v, sizeof(v));
|
|
|
|
v = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]);
|
|
|
|
memcpy(out1 + x, &v, sizeof(v));
|
|
|
|
v = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]);
|
|
|
|
memcpy(out2 + x, &v, sizeof(v));
|
|
|
|
v = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]);
|
|
|
|
memcpy(out3 + x, &v, sizeof(v));
|
2017-08-12 15:49:23 +03:00
|
|
|
in += 16;
|
|
|
|
}
|
|
|
|
for (; x < imIn->xsize; x++) {
|
2017-08-12 10:13:23 +03:00
|
|
|
out0[x] = in[0];
|
|
|
|
out1[x] = in[1];
|
|
|
|
out2[x] = in[2];
|
|
|
|
out3[x] = in[3];
|
|
|
|
in += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-12 03:43:19 +03:00
|
|
|
return imIn->bands;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-31 06:52:47 +04:00
|
|
|
Imaging
|
|
|
|
ImagingPutBand(Imaging imOut, Imaging imIn, int band)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
/* Check arguments */
|
2020-05-10 12:56:36 +03:00
|
|
|
if (!imIn || imIn->bands != 1 || !imOut) {
|
2017-08-09 03:48:24 +03:00
|
|
|
return (Imaging) ImagingError_ModeError();
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2020-05-10 12:56:36 +03:00
|
|
|
if (band < 0 || band >= imOut->bands) {
|
2017-08-09 03:48:24 +03:00
|
|
|
return (Imaging) ImagingError_ValueError("band index out of range");
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
if (imIn->type != imOut->type ||
|
2017-08-09 03:48:24 +03:00
|
|
|
imIn->xsize != imOut->xsize ||
|
2020-05-10 12:56:36 +03:00
|
|
|
imIn->ysize != imOut->ysize) {
|
2017-08-09 03:48:24 +03:00
|
|
|
return (Imaging) ImagingError_Mismatch();
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
/* Shortcuts */
|
2020-05-10 12:56:36 +03:00
|
|
|
if (imOut->bands == 1) {
|
2017-08-09 03:48:24 +03:00
|
|
|
return ImagingCopy2(imOut, imIn);
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
/* Special case for LXXA etc */
|
2020-05-10 12:56:36 +03:00
|
|
|
if (imOut->bands == 2 && band == 1) {
|
2010-07-31 06:52:47 +04:00
|
|
|
band = 3;
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
/* Insert band into image */
|
|
|
|
for (y = 0; y < imIn->ysize; y++) {
|
2017-08-09 03:48:24 +03:00
|
|
|
UINT8* in = imIn->image8[y];
|
|
|
|
UINT8* out = (UINT8*) imOut->image[y] + band;
|
|
|
|
for (x = 0; x < imIn->xsize; x++) {
|
|
|
|
*out = in[x];
|
|
|
|
out += 4;
|
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return imOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
Imaging
|
|
|
|
ImagingFillBand(Imaging imOut, int band, int color)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
/* Check arguments */
|
2020-05-10 12:56:36 +03:00
|
|
|
if (!imOut || imOut->type != IMAGING_TYPE_UINT8) {
|
2017-08-09 03:48:24 +03:00
|
|
|
return (Imaging) ImagingError_ModeError();
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2020-05-10 12:56:36 +03:00
|
|
|
if (band < 0 || band >= imOut->bands) {
|
2017-08-09 03:48:24 +03:00
|
|
|
return (Imaging) ImagingError_ValueError("band index out of range");
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
/* Special case for LXXA etc */
|
2020-05-10 12:56:36 +03:00
|
|
|
if (imOut->bands == 2 && band == 1) {
|
2010-07-31 06:52:47 +04:00
|
|
|
band = 3;
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2018-04-21 11:14:05 +03:00
|
|
|
color = CLIP8(color);
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
/* Insert color into image */
|
|
|
|
for (y = 0; y < imOut->ysize; y++) {
|
2017-08-09 03:48:24 +03:00
|
|
|
UINT8* out = (UINT8*) imOut->image[y] + band;
|
|
|
|
for (x = 0; x < imOut->xsize; x++) {
|
|
|
|
*out = (UINT8) color;
|
|
|
|
out += 4;
|
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return imOut;
|
|
|
|
}
|
2017-08-12 19:08:07 +03:00
|
|
|
|
|
|
|
Imaging
|
|
|
|
ImagingMerge(const char* mode, Imaging bands[4])
|
|
|
|
{
|
2017-08-12 19:17:21 +03:00
|
|
|
int i, x, y;
|
2017-08-12 19:08:07 +03:00
|
|
|
int bandsCount = 0;
|
|
|
|
Imaging imOut;
|
|
|
|
Imaging firstBand;
|
|
|
|
|
|
|
|
firstBand = bands[0];
|
|
|
|
if ( ! firstBand) {
|
2017-08-12 19:17:21 +03:00
|
|
|
return (Imaging) ImagingError_ValueError("wrong number of bands");
|
2017-08-12 19:08:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
|
|
if ( ! bands[i]) {
|
|
|
|
break;
|
|
|
|
}
|
2017-08-12 19:36:56 +03:00
|
|
|
if (bands[i]->bands != 1) {
|
2017-08-12 19:08:07 +03:00
|
|
|
return (Imaging) ImagingError_ModeError();
|
|
|
|
}
|
|
|
|
if (bands[i]->xsize != firstBand->xsize
|
|
|
|
|| bands[i]->ysize != firstBand->ysize) {
|
|
|
|
return (Imaging) ImagingError_Mismatch();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bandsCount = i;
|
|
|
|
|
2017-08-17 12:14:19 +03:00
|
|
|
imOut = ImagingNewDirty(mode, firstBand->xsize, firstBand->ysize);
|
2020-05-10 12:56:36 +03:00
|
|
|
if ( ! imOut) {
|
2017-08-12 19:08:07 +03:00
|
|
|
return NULL;
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2017-08-12 19:08:07 +03:00
|
|
|
|
|
|
|
if (imOut->bands != bandsCount) {
|
|
|
|
ImagingDelete(imOut);
|
|
|
|
return (Imaging) ImagingError_ValueError("wrong number of bands");
|
|
|
|
}
|
|
|
|
|
2020-05-10 12:56:36 +03:00
|
|
|
if (imOut->bands == 1) {
|
2017-08-12 19:17:21 +03:00
|
|
|
return ImagingCopy2(imOut, firstBand);
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2017-08-12 19:17:21 +03:00
|
|
|
|
|
|
|
if (imOut->bands == 2) {
|
|
|
|
for (y = 0; y < imOut->ysize; y++) {
|
|
|
|
UINT8* in0 = bands[0]->image8[y];
|
|
|
|
UINT8* in1 = bands[1]->image8[y];
|
2017-08-12 19:36:56 +03:00
|
|
|
UINT32* out = (UINT32*) imOut->image32[y];
|
2017-08-12 19:17:21 +03:00
|
|
|
for (x = 0; x < imOut->xsize; x++) {
|
2017-08-12 19:41:18 +03:00
|
|
|
out[x] = MAKE_UINT32(in0[x], 0, 0, in1[x]);
|
2017-08-12 19:17:21 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (imOut->bands == 3) {
|
|
|
|
for (y = 0; y < imOut->ysize; y++) {
|
|
|
|
UINT8* in0 = bands[0]->image8[y];
|
|
|
|
UINT8* in1 = bands[1]->image8[y];
|
|
|
|
UINT8* in2 = bands[2]->image8[y];
|
2017-08-12 19:36:56 +03:00
|
|
|
UINT32* out = (UINT32*) imOut->image32[y];
|
2017-08-12 19:17:21 +03:00
|
|
|
for (x = 0; x < imOut->xsize; x++) {
|
2017-08-12 19:41:18 +03:00
|
|
|
out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], 0);
|
2017-08-12 19:17:21 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (imOut->bands == 4) {
|
|
|
|
for (y = 0; y < imOut->ysize; y++) {
|
|
|
|
UINT8* in0 = bands[0]->image8[y];
|
|
|
|
UINT8* in1 = bands[1]->image8[y];
|
|
|
|
UINT8* in2 = bands[2]->image8[y];
|
|
|
|
UINT8* in3 = bands[3]->image8[y];
|
2017-08-12 19:36:56 +03:00
|
|
|
UINT32* out = (UINT32*) imOut->image32[y];
|
2017-08-12 19:17:21 +03:00
|
|
|
for (x = 0; x < imOut->xsize; x++) {
|
2017-08-12 19:36:56 +03:00
|
|
|
out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], in3[x]);
|
2017-08-12 19:17:21 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-12 19:08:07 +03:00
|
|
|
return imOut;
|
|
|
|
}
|