Skip to content

Commit ee7d44c

Browse files
committed
Bands: hoist size vars and add restrict in split/merge/getband/putband
1 parent 00a5426 commit ee7d44c

1 file changed

Lines changed: 67 additions & 51 deletions

File tree

src/libImaging/Bands.c

Lines changed: 67 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,19 @@ ImagingGetBand(Imaging imIn, int band) {
4747
}
4848

4949
/* Extract band from image */
50-
for (y = 0; y < imIn->ysize; y++) {
51-
UINT8 *in = (UINT8 *)imIn->image[y] + band;
52-
UINT8 *out = imOut->image8[y];
50+
// restrict safe: imIn is read-only, imOut is a fresh allocation.
51+
int xsize = imIn->xsize;
52+
int ysize = imIn->ysize;
53+
for (y = 0; y < ysize; y++) {
54+
UINT8 *restrict in = (UINT8 *)imIn->image[y] + band;
55+
UINT8 *restrict out = imOut->image8[y];
5356
x = 0;
54-
for (; x < imIn->xsize - 3; x += 4) {
57+
for (; x < xsize - 3; x += 4) {
5558
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
5659
memcpy(out + x, &v, sizeof(v));
5760
in += 16;
5861
}
59-
for (; x < imIn->xsize; x++) {
62+
for (; x < xsize; x++) {
6063
out[x] = *in;
6164
in += 4;
6265
}
@@ -92,33 +95,37 @@ ImagingSplit(Imaging imIn, Imaging bands[4]) {
9295
}
9396

9497
/* Extract bands from image */
98+
// restrict safe: imIn is read-only and each band is a distinct fresh
99+
// allocation, so none of in/out0..out3 alias each other.
100+
int xsize = imIn->xsize;
101+
int ysize = imIn->ysize;
95102
if (imIn->bands == 2) {
96-
for (y = 0; y < imIn->ysize; y++) {
97-
UINT8 *in = (UINT8 *)imIn->image[y];
98-
UINT8 *out0 = bands[0]->image8[y];
99-
UINT8 *out1 = bands[1]->image8[y];
103+
for (y = 0; y < ysize; y++) {
104+
UINT8 *restrict in = (UINT8 *)imIn->image[y];
105+
UINT8 *restrict out0 = bands[0]->image8[y];
106+
UINT8 *restrict out1 = bands[1]->image8[y];
100107
x = 0;
101-
for (; x < imIn->xsize - 3; x += 4) {
108+
for (; x < xsize - 3; x += 4) {
102109
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
103110
memcpy(out0 + x, &v, sizeof(v));
104111
v = MAKE_UINT32(in[0 + 3], in[4 + 3], in[8 + 3], in[12 + 3]);
105112
memcpy(out1 + x, &v, sizeof(v));
106113
in += 16;
107114
}
108-
for (; x < imIn->xsize; x++) {
115+
for (; x < xsize; x++) {
109116
out0[x] = in[0];
110117
out1[x] = in[3];
111118
in += 4;
112119
}
113120
}
114121
} else if (imIn->bands == 3) {
115-
for (y = 0; y < imIn->ysize; y++) {
116-
UINT8 *in = (UINT8 *)imIn->image[y];
117-
UINT8 *out0 = bands[0]->image8[y];
118-
UINT8 *out1 = bands[1]->image8[y];
119-
UINT8 *out2 = bands[2]->image8[y];
122+
for (y = 0; y < ysize; y++) {
123+
UINT8 *restrict in = (UINT8 *)imIn->image[y];
124+
UINT8 *restrict out0 = bands[0]->image8[y];
125+
UINT8 *restrict out1 = bands[1]->image8[y];
126+
UINT8 *restrict out2 = bands[2]->image8[y];
120127
x = 0;
121-
for (; x < imIn->xsize - 3; x += 4) {
128+
for (; x < xsize - 3; x += 4) {
122129
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
123130
memcpy(out0 + x, &v, sizeof(v));
124131
v = MAKE_UINT32(in[0 + 1], in[4 + 1], in[8 + 1], in[12 + 1]);
@@ -127,22 +134,22 @@ ImagingSplit(Imaging imIn, Imaging bands[4]) {
127134
memcpy(out2 + x, &v, sizeof(v));
128135
in += 16;
129136
}
130-
for (; x < imIn->xsize; x++) {
137+
for (; x < xsize; x++) {
131138
out0[x] = in[0];
132139
out1[x] = in[1];
133140
out2[x] = in[2];
134141
in += 4;
135142
}
136143
}
137144
} else {
138-
for (y = 0; y < imIn->ysize; y++) {
139-
UINT8 *in = (UINT8 *)imIn->image[y];
140-
UINT8 *out0 = bands[0]->image8[y];
141-
UINT8 *out1 = bands[1]->image8[y];
142-
UINT8 *out2 = bands[2]->image8[y];
143-
UINT8 *out3 = bands[3]->image8[y];
145+
for (y = 0; y < ysize; y++) {
146+
UINT8 *restrict in = (UINT8 *)imIn->image[y];
147+
UINT8 *restrict out0 = bands[0]->image8[y];
148+
UINT8 *restrict out1 = bands[1]->image8[y];
149+
UINT8 *restrict out2 = bands[2]->image8[y];
150+
UINT8 *restrict out3 = bands[3]->image8[y];
144151
x = 0;
145-
for (; x < imIn->xsize - 3; x += 4) {
152+
for (; x < xsize - 3; x += 4) {
146153
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
147154
memcpy(out0 + x, &v, sizeof(v));
148155
v = MAKE_UINT32(in[0 + 1], in[4 + 1], in[8 + 1], in[12 + 1]);
@@ -153,7 +160,7 @@ ImagingSplit(Imaging imIn, Imaging bands[4]) {
153160
memcpy(out3 + x, &v, sizeof(v));
154161
in += 16;
155162
}
156-
for (; x < imIn->xsize; x++) {
163+
for (; x < xsize; x++) {
157164
out0[x] = in[0];
158165
out1[x] = in[1];
159166
out2[x] = in[2];
@@ -195,10 +202,13 @@ ImagingPutBand(Imaging imOut, Imaging imIn, int band) {
195202
}
196203

197204
/* Insert band into image */
198-
for (y = 0; y < imIn->ysize; y++) {
199-
UINT8 *in = imIn->image8[y];
200-
UINT8 *out = (UINT8 *)imOut->image[y] + band;
201-
for (x = 0; x < imIn->xsize; x++) {
205+
// restrict safe: imIn and imOut are distinct images (sizes checked above).
206+
int xsize = imIn->xsize;
207+
int ysize = imIn->ysize;
208+
for (y = 0; y < ysize; y++) {
209+
UINT8 *restrict in = imIn->image8[y];
210+
UINT8 *restrict out = (UINT8 *)imOut->image[y] + band;
211+
for (x = 0; x < xsize; x++) {
202212
*out = in[x];
203213
out += 4;
204214
}
@@ -228,9 +238,11 @@ ImagingFillBand(Imaging imOut, int band, int color) {
228238
color = CLIP8(color);
229239

230240
/* Insert color into image */
231-
for (y = 0; y < imOut->ysize; y++) {
232-
UINT8 *out = (UINT8 *)imOut->image[y] + band;
233-
for (x = 0; x < imOut->xsize; x++) {
241+
int xsize = imOut->xsize;
242+
int ysize = imOut->ysize;
243+
for (y = 0; y < ysize; y++) {
244+
UINT8 *restrict out = (UINT8 *)imOut->image[y] + band;
245+
for (x = 0; x < xsize; x++) {
234246
*out = (UINT8)color;
235247
out += 4;
236248
}
@@ -279,33 +291,37 @@ ImagingMerge(const ModeID mode, Imaging bands[4]) {
279291
return ImagingCopy2(imOut, firstBand);
280292
}
281293

294+
// restrict safe: the input bands are read-only and imOut is a fresh
295+
// allocation, so none of in0..in3/out alias each other.
296+
int xsize = imOut->xsize;
297+
int ysize = imOut->ysize;
282298
if (imOut->bands == 2) {
283-
for (y = 0; y < imOut->ysize; y++) {
284-
UINT8 *in0 = bands[0]->image8[y];
285-
UINT8 *in1 = bands[1]->image8[y];
286-
UINT32 *out = (UINT32 *)imOut->image32[y];
287-
for (x = 0; x < imOut->xsize; x++) {
299+
for (y = 0; y < ysize; y++) {
300+
UINT8 *restrict in0 = bands[0]->image8[y];
301+
UINT8 *restrict in1 = bands[1]->image8[y];
302+
UINT32 *restrict out = (UINT32 *)imOut->image32[y];
303+
for (x = 0; x < xsize; x++) {
288304
out[x] = MAKE_UINT32(in0[x], 0, 0, in1[x]);
289305
}
290306
}
291307
} else if (imOut->bands == 3) {
292-
for (y = 0; y < imOut->ysize; y++) {
293-
UINT8 *in0 = bands[0]->image8[y];
294-
UINT8 *in1 = bands[1]->image8[y];
295-
UINT8 *in2 = bands[2]->image8[y];
296-
UINT32 *out = (UINT32 *)imOut->image32[y];
297-
for (x = 0; x < imOut->xsize; x++) {
308+
for (y = 0; y < ysize; y++) {
309+
UINT8 *restrict in0 = bands[0]->image8[y];
310+
UINT8 *restrict in1 = bands[1]->image8[y];
311+
UINT8 *restrict in2 = bands[2]->image8[y];
312+
UINT32 *restrict out = (UINT32 *)imOut->image32[y];
313+
for (x = 0; x < xsize; x++) {
298314
out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], 0);
299315
}
300316
}
301317
} else if (imOut->bands == 4) {
302-
for (y = 0; y < imOut->ysize; y++) {
303-
UINT8 *in0 = bands[0]->image8[y];
304-
UINT8 *in1 = bands[1]->image8[y];
305-
UINT8 *in2 = bands[2]->image8[y];
306-
UINT8 *in3 = bands[3]->image8[y];
307-
UINT32 *out = (UINT32 *)imOut->image32[y];
308-
for (x = 0; x < imOut->xsize; x++) {
318+
for (y = 0; y < ysize; y++) {
319+
UINT8 *restrict in0 = bands[0]->image8[y];
320+
UINT8 *restrict in1 = bands[1]->image8[y];
321+
UINT8 *restrict in2 = bands[2]->image8[y];
322+
UINT8 *restrict in3 = bands[3]->image8[y];
323+
UINT32 *restrict out = (UINT32 *)imOut->image32[y];
324+
for (x = 0; x < xsize; x++) {
309325
out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], in3[x]);
310326
}
311327
}

0 commit comments

Comments
 (0)