Skip to content

Commit 6dec771

Browse files
authored
Merge pull request #165 from bgilbert/argb
convert: process pixels as `u32`; avoid writing back transparent pixels
2 parents 2d2ee96 + 9461ae6 commit 6dec771

File tree

1 file changed

+35
-27
lines changed

1 file changed

+35
-27
lines changed

openslide/_convert.c

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,37 +21,41 @@
2121

2222
typedef unsigned char u8;
2323

24-
#ifdef WORDS_BIGENDIAN
25-
#define CA 0
26-
#define CR 1
27-
#define CG 2
28-
#define CB 3
29-
#else
30-
#define CB 0
31-
#define CG 1
32-
#define CR 2
33-
#define CA 3
34-
#endif
35-
3624
static void
37-
argb2rgba(u8 *buf, Py_ssize_t len)
25+
argb2rgba(PY_UINT32_T *buf, Py_ssize_t len)
3826
{
3927
Py_ssize_t cur;
4028

41-
for (cur = 0; cur < len; cur += 4) {
42-
u8 a = buf[cur + CA];
43-
u8 r = buf[cur + CR];
44-
u8 g = buf[cur + CG];
45-
u8 b = buf[cur + CB];
46-
if (a != 0 && a != 255) {
47-
r = r * 255 / a;
48-
g = g * 255 / a;
49-
b = b * 255 / a;
29+
for (cur = 0; cur < len; cur++) {
30+
PY_UINT32_T val = buf[cur];
31+
u8 a = val >> 24;
32+
switch (a) {
33+
case 0:
34+
break;
35+
case 255:
36+
val = (val << 8) | a;
37+
#ifndef WORDS_BIGENDIAN
38+
// compiler should optimize this to bswap
39+
val = (((val & 0x000000ff) << 24) |
40+
((val & 0x0000ff00) << 8) |
41+
((val & 0x00ff0000) >> 8) |
42+
((val & 0xff000000) >> 24));
43+
#endif
44+
buf[cur] = val;
45+
break;
46+
default:
47+
; // label cannot point to a variable declaration
48+
u8 r = 255 * ((val >> 16) & 0xff) / a;
49+
u8 g = 255 * ((val >> 8) & 0xff) / a;
50+
u8 b = 255 * ((val >> 0) & 0xff) / a;
51+
#ifdef WORDS_BIGENDIAN
52+
val = r << 24 | g << 16 | b << 8 | a;
53+
#else
54+
val = a << 24 | b << 16 | g << 8 | r;
55+
#endif
56+
buf[cur] = val;
57+
break;
5058
}
51-
buf[cur + 0] = r;
52-
buf[cur + 1] = g;
53-
buf[cur + 2] = b;
54-
buf[cur + 3] = a;
5559
}
5660
}
5761

@@ -76,9 +80,13 @@ _convert_argb2rgba(PyObject *self, PyObject *args)
7680
PyErr_SetString(PyExc_ValueError, "Argument has invalid size");
7781
goto DONE;
7882
}
83+
if (view.itemsize != 4) {
84+
PyErr_SetString(PyExc_ValueError, "Argument has invalid item size");
85+
goto DONE;
86+
}
7987

8088
Py_BEGIN_ALLOW_THREADS
81-
argb2rgba(view.buf, view.len);
89+
argb2rgba(view.buf, view.len / 4);
8290
Py_END_ALLOW_THREADS
8391

8492
Py_INCREF(Py_None);

0 commit comments

Comments
 (0)