Skip to content

Commit 0f9f918

Browse files
author
nfnt
committed
Use RGBA, RGBA64 image types as output.
These image types use premultiplied alpha values which are also used during the interpolation. If we'd use NRGBA, NRGBA64 as output, we'd have to reverse the premultiplication.
1 parent 9780a95 commit 0f9f918

File tree

3 files changed

+62
-114
lines changed

3 files changed

+62
-114
lines changed

converter.go

+29-81
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func clampUint16(in int64) uint16 {
4343
return 0
4444
}
4545

46-
func resizeGeneric(in image.Image, out *image.NRGBA64, scale float64, coeffs []int32, offset []int, filterLength int) {
46+
func resizeGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) {
4747
newBounds := out.Bounds()
4848
maxX := in.Bounds().Dx() - 1
4949

@@ -63,7 +63,7 @@ func resizeGeneric(in image.Image, out *image.NRGBA64, scale float64, coeffs []i
6363
case xi >= maxX:
6464
xi = maxX
6565
}
66-
// Forward alpha-premultiplication (if needed)
66+
6767
r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA()
6868

6969
rgba[0] += int64(coeff) * int64(r)
@@ -75,34 +75,24 @@ func resizeGeneric(in image.Image, out *image.NRGBA64, scale float64, coeffs []i
7575
}
7676

7777
offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8
78-
// Reverse alpha-premultiplication
79-
r := rgba[0] / sum
80-
g := rgba[1] / sum
81-
b := rgba[2] / sum
82-
a := rgba[3] / sum
83-
84-
if a != 0 {
85-
r = r * 0xffff / a
86-
g = g * 0xffff / a
87-
b = b * 0xffff / a
88-
}
89-
value := clampUint16(r)
78+
79+
value := clampUint16(rgba[0] / sum)
9080
out.Pix[offset+0] = uint8(value >> 8)
9181
out.Pix[offset+1] = uint8(value)
92-
value = clampUint16(g)
82+
value = clampUint16(rgba[1] / sum)
9383
out.Pix[offset+2] = uint8(value >> 8)
9484
out.Pix[offset+3] = uint8(value)
95-
value = clampUint16(b)
85+
value = clampUint16(rgba[2] / sum)
9686
out.Pix[offset+4] = uint8(value >> 8)
9787
out.Pix[offset+5] = uint8(value)
98-
value = clampUint16(a)
88+
value = clampUint16(rgba[3] / sum)
9989
out.Pix[offset+6] = uint8(value >> 8)
10090
out.Pix[offset+7] = uint8(value)
10191
}
10292
}
10393
}
10494

105-
func resizeRGBA(in *image.RGBA, out *image.NRGBA, scale float64, coeffs []int16, offset []int, filterLength int) {
95+
func resizeRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []int16, offset []int, filterLength int) {
10696
newBounds := out.Bounds()
10797
maxX := in.Bounds().Dx() - 1
10898

@@ -135,27 +125,16 @@ func resizeRGBA(in *image.RGBA, out *image.NRGBA, scale float64, coeffs []int16,
135125
}
136126

137127
xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4
138-
// Reverse alpha-premultiplication
139-
r := rgba[0] / sum
140-
g := rgba[1] / sum
141-
b := rgba[2] / sum
142-
a := rgba[3] / sum
143-
144-
if a != 0 {
145-
r = r * 0xff / a
146-
g = g * 0xff / a
147-
b = b * 0xff / a
148-
}
149128

150-
out.Pix[xo+0] = clampUint8(r)
151-
out.Pix[xo+1] = clampUint8(g)
152-
out.Pix[xo+2] = clampUint8(b)
153-
out.Pix[xo+3] = clampUint8(a)
129+
out.Pix[xo+0] = clampUint8(rgba[0] / sum)
130+
out.Pix[xo+1] = clampUint8(rgba[1] / sum)
131+
out.Pix[xo+2] = clampUint8(rgba[2] / sum)
132+
out.Pix[xo+3] = clampUint8(rgba[3] / sum)
154133
}
155134
}
156135
}
157136

158-
func resizeNRGBA(in *image.NRGBA, out *image.NRGBA, scale float64, coeffs []int16, offset []int, filterLength int) {
137+
func resizeNRGBA(in *image.NRGBA, out *image.RGBA, scale float64, coeffs []int16, offset []int, filterLength int) {
159138
newBounds := out.Bounds()
160139
maxX := in.Bounds().Dx() - 1
161140

@@ -190,27 +169,16 @@ func resizeNRGBA(in *image.NRGBA, out *image.NRGBA, scale float64, coeffs []int1
190169
}
191170

192171
xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4
193-
// Reverse alpha-premultiplication
194-
r := rgba[0] / sum
195-
g := rgba[1] / sum
196-
b := rgba[2] / sum
197-
a := rgba[3] / sum
198-
199-
if a != 0 {
200-
r = r * 0xff / a
201-
g = g * 0xff / a
202-
b = b * 0xff / a
203-
}
204172

205-
out.Pix[xo+0] = clampUint8(r)
206-
out.Pix[xo+1] = clampUint8(g)
207-
out.Pix[xo+2] = clampUint8(b)
208-
out.Pix[xo+3] = clampUint8(a)
173+
out.Pix[xo+0] = clampUint8(rgba[0] / sum)
174+
out.Pix[xo+1] = clampUint8(rgba[1] / sum)
175+
out.Pix[xo+2] = clampUint8(rgba[2] / sum)
176+
out.Pix[xo+3] = clampUint8(rgba[3] / sum)
209177
}
210178
}
211179
}
212180

213-
func resizeRGBA64(in *image.RGBA64, out *image.NRGBA64, scale float64, coeffs []int32, offset []int, filterLength int) {
181+
func resizeRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) {
214182
newBounds := out.Bounds()
215183
maxX := in.Bounds().Dx() - 1
216184

@@ -243,34 +211,24 @@ func resizeRGBA64(in *image.RGBA64, out *image.NRGBA64, scale float64, coeffs []
243211
}
244212

245213
xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8
246-
// Reverse alpha-premultiplication
247-
r := rgba[0] / sum
248-
g := rgba[1] / sum
249-
b := rgba[2] / sum
250-
a := rgba[3] / sum
251-
252-
if a != 0 {
253-
r = r * 0xffff / a
254-
g = g * 0xffff / a
255-
b = b * 0xffff / a
256-
}
257-
value := clampUint16(r)
214+
215+
value := clampUint16(rgba[0] / sum)
258216
out.Pix[xo+0] = uint8(value >> 8)
259217
out.Pix[xo+1] = uint8(value)
260-
value = clampUint16(g)
218+
value = clampUint16(rgba[1] / sum)
261219
out.Pix[xo+2] = uint8(value >> 8)
262220
out.Pix[xo+3] = uint8(value)
263-
value = clampUint16(b)
221+
value = clampUint16(rgba[2] / sum)
264222
out.Pix[xo+4] = uint8(value >> 8)
265223
out.Pix[xo+5] = uint8(value)
266-
value = clampUint16(a)
224+
value = clampUint16(rgba[3] / sum)
267225
out.Pix[xo+6] = uint8(value >> 8)
268226
out.Pix[xo+7] = uint8(value)
269227
}
270228
}
271229
}
272230

273-
func resizeNRGBA64(in *image.NRGBA64, out *image.NRGBA64, scale float64, coeffs []int32, offset []int, filterLength int) {
231+
func resizeNRGBA64(in *image.NRGBA64, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) {
274232
newBounds := out.Bounds()
275233
maxX := in.Bounds().Dx() - 1
276234

@@ -305,27 +263,17 @@ func resizeNRGBA64(in *image.NRGBA64, out *image.NRGBA64, scale float64, coeffs
305263
}
306264

307265
xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8
308-
// Reverse alpha-premultiplication
309-
r := rgba[0] / sum
310-
g := rgba[1] / sum
311-
b := rgba[2] / sum
312-
a := rgba[3] / sum
313-
314-
if a != 0 {
315-
r = r * 0xffff / a
316-
g = g * 0xffff / a
317-
b = b * 0xffff / a
318-
}
319-
value := clampUint16(r)
266+
267+
value := clampUint16(rgba[0] / sum)
320268
out.Pix[xo+0] = uint8(value >> 8)
321269
out.Pix[xo+1] = uint8(value)
322-
value = clampUint16(g)
270+
value = clampUint16(rgba[1] / sum)
323271
out.Pix[xo+2] = uint8(value >> 8)
324272
out.Pix[xo+3] = uint8(value)
325-
value = clampUint16(b)
273+
value = clampUint16(rgba[2] / sum)
326274
out.Pix[xo+4] = uint8(value >> 8)
327275
out.Pix[xo+5] = uint8(value)
328-
value = clampUint16(a)
276+
value = clampUint16(rgba[3] / sum)
329277
out.Pix[xo+6] = uint8(value >> 8)
330278
out.Pix[xo+7] = uint8(value)
331279
}

resize.go

+25-25
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,14 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
105105
switch input := img.(type) {
106106
case *image.RGBA:
107107
// 8-bit precision
108-
temp := image.NewNRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width)))
109-
result := image.NewNRGBA(image.Rect(0, 0, int(width), int(height)))
108+
temp := image.NewRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width)))
109+
result := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
110110

111111
// horizontal filter, results in transposed temporary image
112112
coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
113113
wg.Add(cpus)
114114
for i := 0; i < cpus; i++ {
115-
slice := makeSlice(temp, i, cpus).(*image.NRGBA)
115+
slice := makeSlice(temp, i, cpus).(*image.RGBA)
116116
go func() {
117117
defer wg.Done()
118118
resizeRGBA(input, slice, scaleX, coeffs, offset, filterLength)
@@ -124,24 +124,24 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
124124
coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel)
125125
wg.Add(cpus)
126126
for i := 0; i < cpus; i++ {
127-
slice := makeSlice(result, i, cpus).(*image.NRGBA)
127+
slice := makeSlice(result, i, cpus).(*image.RGBA)
128128
go func() {
129129
defer wg.Done()
130-
resizeNRGBA(temp, slice, scaleY, coeffs, offset, filterLength)
130+
resizeRGBA(temp, slice, scaleY, coeffs, offset, filterLength)
131131
}()
132132
}
133133
wg.Wait()
134134
return result
135135
case *image.NRGBA:
136136
// 8-bit precision
137-
temp := image.NewNRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width)))
138-
result := image.NewNRGBA(image.Rect(0, 0, int(width), int(height)))
137+
temp := image.NewRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width)))
138+
result := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
139139

140140
// horizontal filter, results in transposed temporary image
141141
coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
142142
wg.Add(cpus)
143143
for i := 0; i < cpus; i++ {
144-
slice := makeSlice(temp, i, cpus).(*image.NRGBA)
144+
slice := makeSlice(temp, i, cpus).(*image.RGBA)
145145
go func() {
146146
defer wg.Done()
147147
resizeNRGBA(input, slice, scaleX, coeffs, offset, filterLength)
@@ -153,10 +153,10 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
153153
coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel)
154154
wg.Add(cpus)
155155
for i := 0; i < cpus; i++ {
156-
slice := makeSlice(result, i, cpus).(*image.NRGBA)
156+
slice := makeSlice(result, i, cpus).(*image.RGBA)
157157
go func() {
158158
defer wg.Done()
159-
resizeNRGBA(temp, slice, scaleY, coeffs, offset, filterLength)
159+
resizeRGBA(temp, slice, scaleY, coeffs, offset, filterLength)
160160
}()
161161
}
162162
wg.Wait()
@@ -194,14 +194,14 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
194194
return result.YCbCr()
195195
case *image.RGBA64:
196196
// 16-bit precision
197-
temp := image.NewNRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width)))
198-
result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height)))
197+
temp := image.NewRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width)))
198+
result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
199199

200200
// horizontal filter, results in transposed temporary image
201201
coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
202202
wg.Add(cpus)
203203
for i := 0; i < cpus; i++ {
204-
slice := makeSlice(temp, i, cpus).(*image.NRGBA64)
204+
slice := makeSlice(temp, i, cpus).(*image.RGBA64)
205205
go func() {
206206
defer wg.Done()
207207
resizeRGBA64(input, slice, scaleX, coeffs, offset, filterLength)
@@ -213,24 +213,24 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
213213
coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel)
214214
wg.Add(cpus)
215215
for i := 0; i < cpus; i++ {
216-
slice := makeSlice(result, i, cpus).(*image.NRGBA64)
216+
slice := makeSlice(result, i, cpus).(*image.RGBA64)
217217
go func() {
218218
defer wg.Done()
219-
resizeNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength)
219+
resizeRGBA64(temp, slice, scaleY, coeffs, offset, filterLength)
220220
}()
221221
}
222222
wg.Wait()
223223
return result
224224
case *image.NRGBA64:
225225
// 16-bit precision
226-
temp := image.NewNRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width)))
227-
result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height)))
226+
temp := image.NewRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width)))
227+
result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
228228

229229
// horizontal filter, results in transposed temporary image
230230
coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
231231
wg.Add(cpus)
232232
for i := 0; i < cpus; i++ {
233-
slice := makeSlice(temp, i, cpus).(*image.NRGBA64)
233+
slice := makeSlice(temp, i, cpus).(*image.RGBA64)
234234
go func() {
235235
defer wg.Done()
236236
resizeNRGBA64(input, slice, scaleX, coeffs, offset, filterLength)
@@ -242,10 +242,10 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
242242
coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel)
243243
wg.Add(cpus)
244244
for i := 0; i < cpus; i++ {
245-
slice := makeSlice(result, i, cpus).(*image.NRGBA64)
245+
slice := makeSlice(result, i, cpus).(*image.RGBA64)
246246
go func() {
247247
defer wg.Done()
248-
resizeNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength)
248+
resizeRGBA64(temp, slice, scaleY, coeffs, offset, filterLength)
249249
}()
250250
}
251251
wg.Wait()
@@ -310,14 +310,14 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
310310
return result
311311
default:
312312
// 16-bit precision
313-
temp := image.NewNRGBA64(image.Rect(0, 0, img.Bounds().Dy(), int(width)))
314-
result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height)))
313+
temp := image.NewRGBA64(image.Rect(0, 0, img.Bounds().Dy(), int(width)))
314+
result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
315315

316316
// horizontal filter, results in transposed temporary image
317317
coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
318318
wg.Add(cpus)
319319
for i := 0; i < cpus; i++ {
320-
slice := makeSlice(temp, i, cpus).(*image.NRGBA64)
320+
slice := makeSlice(temp, i, cpus).(*image.RGBA64)
321321
go func() {
322322
defer wg.Done()
323323
resizeGeneric(img, slice, scaleX, coeffs, offset, filterLength)
@@ -329,10 +329,10 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
329329
coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel)
330330
wg.Add(cpus)
331331
for i := 0; i < cpus; i++ {
332-
slice := makeSlice(result, i, cpus).(*image.NRGBA64)
332+
slice := makeSlice(result, i, cpus).(*image.RGBA64)
333333
go func() {
334334
defer wg.Done()
335-
resizeNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength)
335+
resizeRGBA64(temp, slice, scaleY, coeffs, offset, filterLength)
336336
}()
337337
}
338338
wg.Wait()

0 commit comments

Comments
 (0)