rounding minifyBy2

This commit is contained in:
Ryan Oldenburg 2022-07-29 13:20:14 -05:00
parent c17a27041b
commit 5641e0dc07
4 changed files with 30 additions and 29 deletions

View file

@ -56,18 +56,13 @@ proc copy*(image: Image): Image {.raises: [].} =
template dataIndex*(image: Image, x, y: int): int = template dataIndex*(image: Image, x, y: int): int =
image.width * y + x image.width * y + x
proc mix*(a, b: uint8, t: float32): uint8 {.inline, raises: [].} =
## Linearly interpolate between a and b using t.
let t = round(t * 255).uint32
((a * (255 - t) + b * t) div 255).uint8
proc mix*(a, b: ColorRGBX, t: float32): ColorRGBX {.inline, raises: [].} = proc mix*(a, b: ColorRGBX, t: float32): ColorRGBX {.inline, raises: [].} =
## Linearly interpolate between a and b using t. ## Linearly interpolate between a and b using t.
let x = round(t * 255).uint32 let x = round(t * 255).uint32
result.r = ((a.r.uint32 * (255 - x) + b.r.uint32 * x) div 255).uint8 result.r = ((a.r.uint32 * (255 - x) + b.r.uint32 * x + 127) div 255).uint8
result.g = ((a.g.uint32 * (255 - x) + b.g.uint32 * x) div 255).uint8 result.g = ((a.g.uint32 * (255 - x) + b.g.uint32 * x + 127) div 255).uint8
result.b = ((a.b.uint32 * (255 - x) + b.b.uint32 * x) div 255).uint8 result.b = ((a.b.uint32 * (255 - x) + b.b.uint32 * x + 127) div 255).uint8
result.a = ((a.a.uint32 * (255 - x) + b.a.uint32 * x) div 255).uint8 result.a = ((a.a.uint32 * (255 - x) + b.a.uint32 * x + 127) div 255).uint8
proc `*`*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} = proc `*`*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} =
if opacity == 0: if opacity == 0:
@ -75,10 +70,10 @@ proc `*`*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} =
else: else:
let let
x = round(opacity * 255).uint32 x = round(opacity * 255).uint32
r = ((color.r * x) div 255).uint8 r = ((color.r * x + 127) div 255).uint8
g = ((color.g * x) div 255).uint8 g = ((color.g * x + 127) div 255).uint8
b = ((color.b * x) div 255).uint8 b = ((color.b * x + 127) div 255).uint8
a = ((color.a * x) div 255).uint8 a = ((color.a * x + 127) div 255).uint8
rgbx(r, g, b, a) rgbx(r, g, b, a)
proc snapToPixels*(rect: Rect): Rect {.raises: [].} = proc snapToPixels*(rect: Rect): Rect {.raises: [].} =

View file

@ -192,10 +192,10 @@ proc minifyBy2*(
c = src.data[bottomRowStart + x * 2 + 1] c = src.data[bottomRowStart + x * 2 + 1]
d = src.data[bottomRowStart + x * 2] d = src.data[bottomRowStart + x * 2]
mixed = rgbx( mixed = rgbx(
((a.r.uint32 + b.r + c.r + d.r) div 4).uint8, ((a.r.uint32 + b.r + c.r + d.r + 2) div 4).uint8,
((a.g.uint32 + b.g + c.g + d.g) div 4).uint8, ((a.g.uint32 + b.g + c.g + d.g + 2) div 4).uint8,
((a.b.uint32 + b.b + c.b + d.b) div 4).uint8, ((a.b.uint32 + b.b + c.b + d.b + 2) div 4).uint8,
((a.a.uint32 + b.a + c.a + d.a) div 4).uint8 ((a.a.uint32 + b.a + c.a + d.a + 2) div 4).uint8
) )
result.data[result.dataIndex(x, y)] = mixed result.data[result.dataIndex(x, y)] = mixed

View file

@ -296,6 +296,7 @@ proc minifyBy2Avx2*(image: Image, power = 1): Image {.simd.} =
) )
let let
oddMask = mm256_set1_epi16(0xff00) oddMask = mm256_set1_epi16(0xff00)
vec2 = mm256_set1_epi16(2)
permuteControl = mm256_set_epi32(7, 7, 7, 7, 6, 4, 2, 0) permuteControl = mm256_set_epi32(7, 7, 7, 7, 6, 4, 2, 0)
for y in 0 ..< resultEvenHeight: for y in 0 ..< resultEvenHeight:
let let
@ -323,8 +324,10 @@ proc minifyBy2Avx2*(image: Image, power = 1): Image {.simd.} =
bottomAddedOdd = mm256_add_epi16(bottomOdd, bottomShiftedOdd) bottomAddedOdd = mm256_add_epi16(bottomOdd, bottomShiftedOdd)
addedEven = mm256_add_epi16(topAddedEven, bottomAddedEven) addedEven = mm256_add_epi16(topAddedEven, bottomAddedEven)
addedOdd = mm256_add_epi16(topAddedOdd, bottomAddedOdd) addedOdd = mm256_add_epi16(topAddedOdd, bottomAddedOdd)
addedEvenDiv4 = mm256_srli_epi16(addedEven, 2) addedEvenRounding = mm256_add_epi16(addedEven, vec2)
addedOddDiv4 = mm256_srli_epi16(addedOdd, 2) addedOddRounding = mm256_add_epi16(addedOdd, vec2)
addedEvenDiv4 = mm256_srli_epi16(addedEvenRounding, 2)
addedOddDiv4 = mm256_srli_epi16(addedOddRounding, 2)
merged = mm256_or_si256(addedEvenDiv4, mm256_slli_epi16(addedOddDiv4, 8)) merged = mm256_or_si256(addedEvenDiv4, mm256_slli_epi16(addedOddDiv4, 8))
# Merged has the correct values for the next two pixels at # Merged has the correct values for the next two pixels at
# index 0, 2, 4, 6 so permute into position and store # index 0, 2, 4, 6 so permute into position and store
@ -342,10 +345,10 @@ proc minifyBy2Avx2*(image: Image, power = 1): Image {.simd.} =
c = src.data[bottomRowStart + x * 2 + 1] c = src.data[bottomRowStart + x * 2 + 1]
d = src.data[bottomRowStart + x * 2] d = src.data[bottomRowStart + x * 2]
mixed = rgbx( mixed = rgbx(
((a.r.uint32 + b.r + c.r + d.r) div 4).uint8, ((a.r.uint32 + b.r + c.r + d.r + 2) div 4).uint8,
((a.g.uint32 + b.g + c.g + d.g) div 4).uint8, ((a.g.uint32 + b.g + c.g + d.g + 2) div 4).uint8,
((a.b.uint32 + b.b + c.b + d.b) div 4).uint8, ((a.b.uint32 + b.b + c.b + d.b + 2) div 4).uint8,
((a.a.uint32 + b.a + c.a + d.a) div 4).uint8 ((a.a.uint32 + b.a + c.a + d.a + 2) div 4).uint8
) )
result.data[result.dataIndex(x, y)] = mixed result.data[result.dataIndex(x, y)] = mixed

View file

@ -354,6 +354,7 @@ proc minifyBy2Sse2*(image: Image, power = 1): Image {.simd.} =
oddMask = mm_set1_epi16(0xff00) oddMask = mm_set1_epi16(0xff00)
loMask = mm_set_epi32(0, 0, uint32.high, uint32.high) loMask = mm_set_epi32(0, 0, uint32.high, uint32.high)
hiMask = mm_set_epi32(uint32.high, uint32.high, 0, 0) hiMask = mm_set_epi32(uint32.high, uint32.high, 0, 0)
vec2 = mm_set1_epi16(2)
for y in 0 ..< resultEvenHeight: for y in 0 ..< resultEvenHeight:
let let
topRowStart = src.dataIndex(0, y * 2) topRowStart = src.dataIndex(0, y * 2)
@ -390,8 +391,10 @@ proc minifyBy2Sse2*(image: Image, power = 1): Image {.simd.} =
bottomAddedOdd = mm_add_epi16(bottomOdd, bottomShiftedOdd) bottomAddedOdd = mm_add_epi16(bottomOdd, bottomShiftedOdd)
addedEven = mm_add_epi16(topAddedEven, bottomAddedEven) addedEven = mm_add_epi16(topAddedEven, bottomAddedEven)
addedOdd = mm_add_epi16(topAddedOdd, bottomAddedOdd) addedOdd = mm_add_epi16(topAddedOdd, bottomAddedOdd)
addedEvenDiv4 = mm_srli_epi16(addedEven, 2) addedEvenRounding = mm_add_epi16(addedEven, vec2)
addedOddDiv4 = mm_srli_epi16(addedOdd, 2) addedOddRounding = mm_add_epi16(addedOdd, vec2)
addedEvenDiv4 = mm_srli_epi16(addedEvenRounding, 2)
addedOddDiv4 = mm_srli_epi16(addedOddRounding, 2)
merged = mm_or_si128(addedEvenDiv4, mm_slli_epi16(addedOddDiv4, 8)) merged = mm_or_si128(addedEvenDiv4, mm_slli_epi16(addedOddDiv4, 8))
mm_storeu_si128(result.data[result.dataIndex(x, y)].addr, merged) mm_storeu_si128(result.data[result.dataIndex(x, y)].addr, merged)
x += 4 x += 4
@ -403,10 +406,10 @@ proc minifyBy2Sse2*(image: Image, power = 1): Image {.simd.} =
c = src.data[bottomRowStart + x * 2 + 1] c = src.data[bottomRowStart + x * 2 + 1]
d = src.data[bottomRowStart + x * 2] d = src.data[bottomRowStart + x * 2]
mixed = rgbx( mixed = rgbx(
((a.r.uint32 + b.r + c.r + d.r) div 4).uint8, ((a.r.uint32 + b.r + c.r + d.r + 2) div 4).uint8,
((a.g.uint32 + b.g + c.g + d.g) div 4).uint8, ((a.g.uint32 + b.g + c.g + d.g + 2) div 4).uint8,
((a.b.uint32 + b.b + c.b + d.b) div 4).uint8, ((a.b.uint32 + b.b + c.b + d.b + 2) div 4).uint8,
((a.a.uint32 + b.a + c.a + d.a) div 4).uint8 ((a.a.uint32 + b.a + c.a + d.a + 2) div 4).uint8
) )
result.data[result.dataIndex(x, y)] = mixed result.data[result.dataIndex(x, y)] = mixed