Merge pull request #2693 from uploadcare/fast-unpacking

Fast unpacking and partially packing
This commit is contained in:
wiredfool 2017-08-31 15:23:11 +01:00 committed by GitHub
commit 367ce3c1bc
10 changed files with 178 additions and 229 deletions

View File

@ -77,9 +77,6 @@ ImagingAlphaComposite(Imaging imDst, Imaging imSrc)
UINT16 coef1 = src->a * 255 * 255 * 128 / outa255; UINT16 coef1 = src->a * 255 * 255 * 128 / outa255;
UINT16 coef2 = 255 * 128 - coef1; UINT16 coef2 = 255 * 128 - coef1;
#define SHIFTFORDIV255(a)\
((((a) >> 8) + a) >> 8)
tmpr = src->r * coef1 + dst->r * coef2 + (0x80 << 7); tmpr = src->r * coef1 + dst->r * coef2 + (0x80 << 7);
out->r = SHIFTFORDIV255(tmpr) >> 7; out->r = SHIFTFORDIV255(tmpr) >> 7;
tmpg = src->g * coef1 + dst->g * coef2 + (0x80 << 7); tmpg = src->g * coef1 + dst->g * coef2 + (0x80 << 7);

View File

@ -22,13 +22,6 @@
#define CLIP(x) ((x) <= 0 ? 0 : (x) < 256 ? (x) : 255) #define CLIP(x) ((x) <= 0 ? 0 : (x) < 256 ? (x) : 255)
#ifdef WORDS_BIGENDIAN
#define MAKE_UINT32(u0, u1, u2, u3) (u3 | (u2<<8) | (u1<<16) | (u0<<24))
#else
#define MAKE_UINT32(u0, u1, u2, u3) (u0 | (u1<<8) | (u2<<16) | (u3<<24))
#endif
Imaging Imaging
ImagingGetBand(Imaging imIn, int band) ImagingGetBand(Imaging imIn, int band)
{ {

View File

@ -41,10 +41,6 @@
#define CLIP(v) ((v) <= 0 ? 0 : (v) >= 255 ? 255 : (v)) #define CLIP(v) ((v) <= 0 ? 0 : (v) >= 255 ? 255 : (v))
#define CLIP16(v) ((v) <= -32768 ? -32768 : (v) >= 32767 ? 32767 : (v)) #define CLIP16(v) ((v) <= -32768 ? -32768 : (v) >= 32767 ? 32767 : (v))
/* like (a * b + 127) / 255), but much faster on most platforms */
#define MULDIV255(a, b, tmp)\
(tmp = (a) * (b) + 128, ((((tmp) >> 8) + (tmp)) >> 8))
/* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */ /* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */
#define L(rgb)\ #define L(rgb)\
((INT32) (rgb)[0]*299 + (INT32) (rgb)[1]*587 + (INT32) (rgb)[2]*114) ((INT32) (rgb)[0]*299 + (INT32) (rgb)[1]*587 + (INT32) (rgb)[2]*114)

View File

@ -42,13 +42,6 @@
#define INK8(ink) (*(UINT8*)ink) #define INK8(ink) (*(UINT8*)ink)
#define INK32(ink) (*(INT32*)ink) #define INK32(ink) (*(INT32*)ink)
/* like (a * b + 127) / 255), but much faster on most platforms */
#define MULDIV255(a, b, tmp)\
(tmp = (a) * (b) + 128, ((((tmp) >> 8) + (tmp)) >> 8))
#define BLEND(mask, in1, in2, tmp1, tmp2)\
(MULDIV255(in1, 255 - mask, tmp1) + MULDIV255(in2, mask, tmp2))
/* /*
* Rounds around zero (up=away from zero, down=torwards zero) * Rounds around zero (up=away from zero, down=torwards zero)
* This guarantees that ROUND_UP|DOWN(f) == -ROUND_UP|DOWN(-f) * This guarantees that ROUND_UP|DOWN(f) == -ROUND_UP|DOWN(-f)
@ -88,14 +81,14 @@ point32(Imaging im, int x, int y, int ink)
static inline void static inline void
point32rgba(Imaging im, int x, int y, int ink) point32rgba(Imaging im, int x, int y, int ink)
{ {
unsigned int tmp1, tmp2; unsigned int tmp1;
if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize) { if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize) {
UINT8* out = (UINT8*) im->image[y]+x*4; UINT8* out = (UINT8*) im->image[y]+x*4;
UINT8* in = (UINT8*) &ink; UINT8* in = (UINT8*) &ink;
out[0] = BLEND(in[3], out[0], in[0], tmp1, tmp2); out[0] = BLEND(in[3], out[0], in[0], tmp1);
out[1] = BLEND(in[3], out[1], in[1], tmp1, tmp2); out[1] = BLEND(in[3], out[1], in[1], tmp1);
out[2] = BLEND(in[3], out[2], in[2], tmp1, tmp2); out[2] = BLEND(in[3], out[2], in[2], tmp1);
} }
} }
@ -147,7 +140,7 @@ static inline void
hline32rgba(Imaging im, int x0, int y0, int x1, int ink) hline32rgba(Imaging im, int x0, int y0, int x1, int ink)
{ {
int tmp; int tmp;
unsigned int tmp1, tmp2; unsigned int tmp1;
if (y0 >= 0 && y0 < im->ysize) { if (y0 >= 0 && y0 < im->ysize) {
if (x0 > x1) if (x0 > x1)
@ -164,9 +157,9 @@ hline32rgba(Imaging im, int x0, int y0, int x1, int ink)
UINT8* out = (UINT8*) im->image[y0]+x0*4; UINT8* out = (UINT8*) im->image[y0]+x0*4;
UINT8* in = (UINT8*) &ink; UINT8* in = (UINT8*) &ink;
while (x0 <= x1) { while (x0 <= x1) {
out[0] = BLEND(in[3], out[0], in[0], tmp1, tmp2); out[0] = BLEND(in[3], out[0], in[0], tmp1);
out[1] = BLEND(in[3], out[1], in[1], tmp1, tmp2); out[1] = BLEND(in[3], out[1], in[1], tmp1);
out[2] = BLEND(in[3], out[2], in[2], tmp1, tmp2); out[2] = BLEND(in[3], out[2], in[2], tmp1);
x0++; out += 4; x0++; out += 4;
} }
} }

View File

@ -466,13 +466,9 @@ extern int ImagingZipEncodeCleanup(ImagingCodecState state);
typedef void (*ImagingShuffler)(UINT8* out, const UINT8* in, int pixels); typedef void (*ImagingShuffler)(UINT8* out, const UINT8* in, int pixels);
/* Public shufflers */ /* Public shufflers */
extern void ImagingPackRGB(UINT8* out, const UINT8* in, int pixels);
extern void ImagingPackBGR(UINT8* out, const UINT8* in, int pixels); extern void ImagingPackBGR(UINT8* out, const UINT8* in, int pixels);
extern void ImagingUnpackRGB(UINT8* out, const UINT8* in, int pixels);
extern void ImagingUnpackBGR(UINT8* out, const UINT8* in, int pixels);
extern void ImagingUnpackYCC(UINT8* out, const UINT8* in, int pixels); extern void ImagingUnpackYCC(UINT8* out, const UINT8* in, int pixels);
extern void ImagingUnpackYCCA(UINT8* out, const UINT8* in, int pixels); extern void ImagingUnpackYCCA(UINT8* out, const UINT8* in, int pixels);
extern void ImagingUnpackYCbCr(UINT8* out, const UINT8* in, int pixels);
extern void ImagingConvertRGB2YCbCr(UINT8* out, const UINT8* in, int pixels); extern void ImagingConvertRGB2YCbCr(UINT8* out, const UINT8* in, int pixels);
extern void ImagingConvertYCbCr2RGB(UINT8* out, const UINT8* in, int pixels); extern void ImagingConvertYCbCr2RGB(UINT8* out, const UINT8* in, int pixels);
@ -514,6 +510,10 @@ extern Py_ssize_t _imaging_tell_pyFd(PyObject *fd);
#define IMAGING_CODEC_CONFIG -8 #define IMAGING_CODEC_CONFIG -8
#define IMAGING_CODEC_MEMORY -9 #define IMAGING_CODEC_MEMORY -9
#include "ImagingUtils.h"
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif

30
libImaging/ImagingUtils.h Normal file
View File

@ -0,0 +1,30 @@
#ifdef WORDS_BIGENDIAN
#define MAKE_UINT32(u0, u1, u2, u3) (u3 | (u2<<8) | (u1<<16) | (u0<<24))
#define MASK_UINT32_CHANNEL_0 0xff000000
#define MASK_UINT32_CHANNEL_1 0x00ff0000
#define MASK_UINT32_CHANNEL_2 0x0000ff00
#define MASK_UINT32_CHANNEL_3 0x000000ff
#else
#define MAKE_UINT32(u0, u1, u2, u3) (u0 | (u1<<8) | (u2<<16) | (u3<<24))
#define MASK_UINT32_CHANNEL_0 0x000000ff
#define MASK_UINT32_CHANNEL_1 0x0000ff00
#define MASK_UINT32_CHANNEL_2 0x00ff0000
#define MASK_UINT32_CHANNEL_3 0xff000000
#endif
#define SHIFTFORDIV255(a)\
((((a) >> 8) + a) >> 8)
/* like (a * b + 127) / 255), but much faster on most platforms */
#define MULDIV255(a, b, tmp)\
(tmp = (a) * (b) + 128, SHIFTFORDIV255(tmp))
#define DIV255(a, tmp)\
(tmp = (a) + 128, SHIFTFORDIV255(tmp))
#define BLEND(mask, in1, in2, tmp1)\
DIV255(in1 * (255 - mask) + in2 * mask, tmp1)
#define PREBLEND(mask, in1, in2, tmp1)\
(MULDIV255(in1, (255 - mask), tmp1) + in2)

View File

@ -72,9 +72,6 @@
#define C64L C64N #define C64L C64N
#endif #endif
/* like (a * b + 127) / 255), but much faster on most platforms */
#define MULDIV255(a, b, tmp)\
(tmp = (a) * (b) + 128, ((((tmp) >> 8) + (tmp)) >> 8))
static void static void
pack1(UINT8* out, const UINT8* in, int pixels) pack1(UINT8* out, const UINT8* in, int pixels)
@ -227,13 +224,17 @@ packLAL(UINT8* out, const UINT8* in, int pixels)
void void
ImagingPackRGB(UINT8* out, const UINT8* in, int pixels) ImagingPackRGB(UINT8* out, const UINT8* in, int pixels)
{ {
int i; int i = 0;
/* RGB triplets */ /* RGB triplets */
for (i = 0; i < pixels; i++) { for (; i < pixels-1; i++) {
out[0] = in[R]; ((UINT32*)out)[0] = ((UINT32*)in)[i];
out[1] = in[G]; out += 3;
out[2] = in[B]; }
out += 3; in += 4; for (; i < pixels; i++) {
out[0] = in[i*4+R];
out[1] = in[i*4+G];
out[2] = in[i*4+B];
out += 3;
} }
} }

View File

@ -23,20 +23,6 @@
#include "Imaging.h" #include "Imaging.h"
/* like (a * b + 127) / 255), but much faster on most platforms */
#define MULDIV255NEW(a, tmp)\
(tmp = (a) + 128, ((((tmp) >> 8) + (tmp)) >> 8))
#define MULDIV255OLD(a, tmp)\
(((a) + 127) / 255)
#define MULDIV255 MULDIV255NEW
#define BLEND(mask, in1, in2, tmp1)\
MULDIV255(in1 * (255 - mask) + in2 * mask, tmp1)
#define PREBLEND(mask, in1, in2, tmp1)\
(MULDIV255(in1 * (255 - mask), tmp1) + in2)
static inline void static inline void
paste(Imaging imOut, Imaging imIn, int dx, int dy, int sx, int sy, paste(Imaging imOut, Imaging imIn, int dx, int dy, int sx, int sy,

View File

@ -5,12 +5,6 @@
#define ROUND_UP(f) ((int) ((f) >= 0.0 ? (f) + 0.5F : (f) - 0.5F)) #define ROUND_UP(f) ((int) ((f) >= 0.0 ? (f) + 0.5F : (f) - 0.5F))
#ifdef WORDS_BIGENDIAN
#define MAKE_UINT32(u0, u1, u2, u3) (u3 | (u2<<8) | (u1<<16) | (u0<<24))
#else
#define MAKE_UINT32(u0, u1, u2, u3) (u0 | (u1<<8) | (u2<<16) | (u3<<24))
#endif
struct filter { struct filter {
double (*filter)(double x); double (*filter)(double x);

View File

@ -326,26 +326,25 @@ unpackL4IR(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
unpackLA(UINT8* out, const UINT8* in, int pixels) unpackLA(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* LA, pixel interleaved */ /* LA, pixel interleaved */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = out[G] = out[B] = in[0]; out[i] = MAKE_UINT32(in[0], in[0], in[0], in[1]);
out[A] = in[1]; in += 2;
in += 2; out += 4;
} }
} }
static void static void
unpackLAL(UINT8* out, const UINT8* in, int pixels) unpackLAL(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* LA, line interleaved */ /* LA, line interleaved */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = out[G] = out[B] = in[i]; out[i] = MAKE_UINT32(in[i], in[i], in[i], in[i+pixels]);
out[A] = in[i+pixels];
out += 4;
} }
} }
@ -476,89 +475,82 @@ unpackP4L(UINT8* out, const UINT8* in, int pixels)
} }
} }
/* Unpack to "RGB" image */ /* Unpack to "RGB" image */
void void
ImagingUnpackRGB(UINT8* out, const UINT8* in, int pixels) ImagingUnpackRGB(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i = 0;
UINT32* out = (UINT32*) _out;
/* RGB triplets */ /* RGB triplets */
for (i = 0; i < pixels; i++) { for (; i < pixels-1; i++) {
out[R] = in[0]; out[i] = MASK_UINT32_CHANNEL_3 | *(UINT32*)&in[0];
out[G] = in[1]; in += 3;
out[B] = in[2]; }
out[A] = 255; for (; i < pixels; i++) {
out += 4; in += 3; out[i] = MAKE_UINT32(in[0], in[1], in[2], 255);
in += 3;
} }
} }
void void
unpackRGB16L(UINT8* out, const UINT8* in, int pixels) unpackRGB16L(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* 16-bit RGB triplets, little-endian order */ /* 16-bit RGB triplets, little-endian order */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[1]; out[i] = MAKE_UINT32(in[1], in[3], in[5], 255);
out[G] = in[3]; in += 6;
out[B] = in[5];
out[A] = 255;
out += 4; in += 6;
} }
} }
void void
unpackRGB16B(UINT8* out, const UINT8* in, int pixels) unpackRGB16B(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* 16-bit RGB triplets, big-endian order */ /* 16-bit RGB triplets, big-endian order */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[0]; out[i] = MAKE_UINT32(in[0], in[2], in[4], 255);
out[G] = in[2]; in += 6;
out[B] = in[4];
out[A] = 255;
out += 4; in += 6;
} }
} }
static void static void
unpackRGBL(UINT8* out, const UINT8* in, int pixels) unpackRGBL(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* RGB, line interleaved */ /* RGB, line interleaved */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[i]; out[i] = MAKE_UINT32(in[i], in[i+pixels], in[i+pixels+pixels], 255);
out[G] = in[i+pixels];
out[B] = in[i+pixels+pixels];
out[A] = 255;
out += 4;
} }
} }
static void static void
unpackRGBR(UINT8* out, const UINT8* in, int pixels) unpackRGBR(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* RGB, bit reversed */ /* RGB, bit reversed */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = BITFLIP[in[0]]; out[i] = MAKE_UINT32(BITFLIP[in[0]], BITFLIP[in[1]],
out[G] = BITFLIP[in[1]]; BITFLIP[in[2]], 255);
out[B] = BITFLIP[in[2]]; in += 3;
out[A] = 255;
out += 4; in += 3;
} }
} }
void void
ImagingUnpackBGR(UINT8* out, const UINT8* in, int pixels) ImagingUnpackBGR(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* RGB, reversed bytes */ /* RGB, reversed bytes */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[2]; out[i] = MAKE_UINT32(in[2], in[1], in[0], 255);
out[G] = in[1]; in += 3;
out[B] = in[0];
out[A] = 255;
out += 4; in += 3;
} }
} }
@ -683,166 +675,148 @@ ImagingUnpackRGBA4B(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
ImagingUnpackBGRX(UINT8* out, const UINT8* in, int pixels) ImagingUnpackBGRX(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* RGB, reversed bytes with padding */ /* RGB, reversed bytes with padding */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[2]; out[i] = MAKE_UINT32(in[2], in[1], in[0], 255);
out[G] = in[1]; in += 4;
out[B] = in[0];
out[A] = 255;
out += 4; in += 4;
} }
} }
static void static void
ImagingUnpackXRGB(UINT8* out, const UINT8* in, int pixels) ImagingUnpackXRGB(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* RGB, leading pad */ /* RGB, leading pad */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[1]; out[i] = MAKE_UINT32(in[1], in[2], in[3], 255);
out[G] = in[2]; in += 4;
out[B] = in[3];
out[A] = 255;
out += 4; in += 4;
} }
} }
static void static void
ImagingUnpackXBGR(UINT8* out, const UINT8* in, int pixels) ImagingUnpackXBGR(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* RGB, reversed bytes, leading pad */ /* RGB, reversed bytes, leading pad */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[3]; out[i] = MAKE_UINT32(in[3], in[2], in[1], 255);
out[G] = in[2]; in += 4;
out[B] = in[1];
out[A] = 255;
out += 4; in += 4;
} }
} }
/* Unpack to "RGBA" image */ /* Unpack to "RGBA" image */
static void static void
unpackRGBALA(UINT8* out, const UINT8* in, int pixels) unpackRGBALA(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* greyscale with alpha */ /* greyscale with alpha */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = out[G] = out[B] = in[0]; out[i] = MAKE_UINT32(in[0], in[0], in[0], in[1]);
out[A] = in[1]; in += 2;
out += 4; in += 2;
} }
} }
static void static void
unpackRGBALA16B(UINT8* out, const UINT8* in, int pixels) unpackRGBALA16B(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* 16-bit greyscale with alpha, big-endian */ /* 16-bit greyscale with alpha, big-endian */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = out[G] = out[B] = in[0]; out[i] = MAKE_UINT32(in[0], in[0], in[0], in[2]);
out[A] = in[2]; in += 4;
out += 4; in += 4;
} }
} }
static void static void
unpackRGBa16L(UINT8* out, const UINT8* in, int pixels) unpackRGBa16L(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* premultiplied 16-bit RGBA, little-endian */ /* premultiplied 16-bit RGBA, little-endian */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
int a = in[7]; int a = in[7];
if (!a) if ( ! a) {
out[R] = out[G] = out[B] = out[A] = 0; out[i] = 0;
else if (a == 255) { } else if (a == 255) {
out[R] = in[1]; out[i] = MAKE_UINT32(in[1], in[3], in[5], a);
out[G] = in[3];
out[B] = in[5];
out[A] = a;
} else { } else {
out[R] = CLIP(in[1] * 255 / a); out[i] = MAKE_UINT32(CLIP(in[1] * 255 / a),
out[G] = CLIP(in[3] * 255 / a); CLIP(in[3] * 255 / a),
out[B] = CLIP(in[5] * 255 / a); CLIP(in[5] * 255 / a), a);
out[A] = a;
} }
out += 4; in += 8; in += 8;
} }
} }
static void static void
unpackRGBa16B(UINT8* out, const UINT8* in, int pixels) unpackRGBa16B(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* premultiplied 16-bit RGBA, big-endian */ /* premultiplied 16-bit RGBA, big-endian */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
int a = in[6]; int a = in[6];
if (!a) if ( ! a) {
out[R] = out[G] = out[B] = out[A] = 0; out[i] = 0;
else if (a == 255) { } else if (a == 255) {
out[R] = in[0]; out[i] = MAKE_UINT32(in[0], in[2], in[4], a);
out[G] = in[2];
out[B] = in[4];
out[A] = a;
} else { } else {
out[R] = CLIP(in[0] * 255 / a); out[i] = MAKE_UINT32(CLIP(in[0] * 255 / a),
out[G] = CLIP(in[2] * 255 / a); CLIP(in[2] * 255 / a),
out[B] = CLIP(in[4] * 255 / a); CLIP(in[4] * 255 / a), a);
out[A] = a;
} }
out += 4; in += 8; in += 8;
} }
} }
static void static void
unpackRGBa(UINT8* out, const UINT8* in, int pixels) unpackRGBa(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* premultiplied RGBA */ /* premultiplied RGBA */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
int a = in[3]; int a = in[3];
if (!a) if ( ! a) {
out[R] = out[G] = out[B] = out[A] = 0; out[i] = 0;
else if (a == 255) { } else if (a == 255) {
out[R] = in[0]; out[i] = MAKE_UINT32(in[0], in[1], in[2], a);
out[G] = in[1];
out[B] = in[2];
out[A] = a;
} else { } else {
out[R] = CLIP(in[0] * 255 / a); out[i] = MAKE_UINT32(CLIP(in[0] * 255 / a),
out[G] = CLIP(in[1] * 255 / a); CLIP(in[1] * 255 / a),
out[B] = CLIP(in[2] * 255 / a); CLIP(in[2] * 255 / a), a);
out[A] = a;
} }
out += 4; in += 4; in += 4;
} }
} }
static void static void
unpackBGRa(UINT8* out, const UINT8* in, int pixels) unpackBGRa(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* premultiplied BGRA */ /* premultiplied BGRA */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
int a = in[3]; int a = in[3];
if (!a) if ( ! a) {
out[R] = out[G] = out[B] = out[A] = 0; out[i] = 0;
else if (a == 255) { } else if (a == 255) {
out[R] = in[2]; out[i] = MAKE_UINT32(in[2], in[1], in[0], a);
out[G] = in[1];
out[B] = in[0];
out[A] = a;
} else { } else {
out[R] = CLIP(in[2] * 255 / a); out[i] = MAKE_UINT32(CLIP(in[2] * 255 / a),
out[G] = CLIP(in[1] * 255 / a); CLIP(in[1] * 255 / a),
out[B] = CLIP(in[0] * 255 / a); CLIP(in[0] * 255 / a), a);
out[A] = a;
} }
out += 4; in += 4; in += 4;
} }
} }
@ -861,87 +835,74 @@ unpackRGBAI(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
unpackRGBAL(UINT8* out, const UINT8* in, int pixels) unpackRGBAL(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* RGBA, line interleaved */ /* RGBA, line interleaved */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[i]; out[i] = MAKE_UINT32(in[i], in[i+pixels], in[i+pixels+pixels],
out[G] = in[i+pixels]; in[i+pixels+pixels+pixels]);
out[B] = in[i+pixels+pixels];
out[A] = in[i+pixels+pixels+pixels];
out += 4;
} }
} }
void void
unpackRGBA16L(UINT8* out, const UINT8* in, int pixels) unpackRGBA16L(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* 16-bit RGBA, little-endian order */ /* 16-bit RGBA, little-endian order */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[1]; out[i] = MAKE_UINT32(in[1], in[3], in[5], in[7]);
out[G] = in[3]; in += 8;
out[B] = in[5];
out[A] = in[7];
out += 4; in += 8;
} }
} }
void void
unpackRGBA16B(UINT8* out, const UINT8* in, int pixels) unpackRGBA16B(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* 16-bit RGBA, big-endian order */ /* 16-bit RGBA, big-endian order */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[0]; out[i] = MAKE_UINT32(in[0], in[2], in[4], in[6]);
out[G] = in[2]; in += 8;
out[B] = in[4];
out[A] = in[6];
out += 4; in += 8;
} }
} }
static void static void
unpackARGB(UINT8* out, const UINT8* in, int pixels) unpackARGB(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* RGBA, leading pad */ /* RGBA, leading pad */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[1]; out[i] = MAKE_UINT32(in[1], in[2], in[3], in[0]);
out[G] = in[2]; in += 4;
out[B] = in[3];
out[A] = in[0];
out += 4; in += 4;
} }
} }
static void static void
unpackABGR(UINT8* out, const UINT8* in, int pixels) unpackABGR(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* RGBA, reversed bytes */ /* RGBA, reversed bytes */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[3]; out[i] = MAKE_UINT32(in[3], in[2], in[1], in[0]);
out[G] = in[2]; in += 4;
out[B] = in[1];
out[A] = in[0];
out += 4; in += 4;
} }
} }
static void static void
unpackBGRA(UINT8* out, const UINT8* in, int pixels) unpackBGRA(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* RGBA, reversed bytes */ /* RGBA, reversed bytes */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[R] = in[2]; out[i] = MAKE_UINT32(in[2], in[1], in[0], in[3]);
out[G] = in[1]; in += 4;
out[B] = in[0];
out[A] = in[3];
out += 4; in += 4;
} }
} }
@ -949,16 +910,14 @@ unpackBGRA(UINT8* out, const UINT8* in, int pixels)
/* Unpack to "CMYK" image */ /* Unpack to "CMYK" image */
static void static void
unpackCMYKI(UINT8* out, const UINT8* in, int pixels) unpackCMYKI(UINT8* _out, const UINT8* in, int pixels)
{ {
int i; int i;
UINT32* out = (UINT32*) _out;
/* CMYK, inverted bytes (Photoshop 2.5) */ /* CMYK, inverted bytes (Photoshop 2.5) */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[C] = ~in[0]; out[i] = ~MAKE_UINT32(in[0], in[1], in[2], in[3]);
out[M] = ~in[1]; in += 4;
out[Y] = ~in[2];
out[K] = ~in[3];
out += 4; in += 4;
} }
} }