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 =
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: [].} =
## Linearly interpolate between a and b using t.
let x = round(t * 255).uint32
result.r = ((a.r.uint32 * (255 - x) + b.r.uint32 * x) div 255).uint8
result.g = ((a.g.uint32 * (255 - x) + b.g.uint32 * x) div 255).uint8
result.b = ((a.b.uint32 * (255 - x) + b.b.uint32 * x) div 255).uint8
result.a = ((a.a.uint32 * (255 - x) + b.a.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 + 127) 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 + 127) div 255).uint8
proc `*`*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} =
if opacity == 0:
@ -75,10 +70,10 @@ proc `*`*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} =
else:
let
x = round(opacity * 255).uint32
r = ((color.r * x) div 255).uint8
g = ((color.g * x) div 255).uint8
b = ((color.b * x) div 255).uint8
a = ((color.a * x) div 255).uint8
r = ((color.r * x + 127) div 255).uint8
g = ((color.g * x + 127) div 255).uint8
b = ((color.b * x + 127) div 255).uint8
a = ((color.a * x + 127) div 255).uint8
rgbx(r, g, b, a)
proc snapToPixels*(rect: Rect): Rect {.raises: [].} =

View file

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

View file

@ -296,6 +296,7 @@ proc minifyBy2Avx2*(image: Image, power = 1): Image {.simd.} =
)
let
oddMask = mm256_set1_epi16(0xff00)
vec2 = mm256_set1_epi16(2)
permuteControl = mm256_set_epi32(7, 7, 7, 7, 6, 4, 2, 0)
for y in 0 ..< resultEvenHeight:
let
@ -323,8 +324,10 @@ proc minifyBy2Avx2*(image: Image, power = 1): Image {.simd.} =
bottomAddedOdd = mm256_add_epi16(bottomOdd, bottomShiftedOdd)
addedEven = mm256_add_epi16(topAddedEven, bottomAddedEven)
addedOdd = mm256_add_epi16(topAddedOdd, bottomAddedOdd)
addedEvenDiv4 = mm256_srli_epi16(addedEven, 2)
addedOddDiv4 = mm256_srli_epi16(addedOdd, 2)
addedEvenRounding = mm256_add_epi16(addedEven, vec2)
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 has the correct values for the next two pixels at
# 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]
d = src.data[bottomRowStart + x * 2]
mixed = rgbx(
((a.r.uint32 + b.r + c.r + d.r) div 4).uint8,
((a.g.uint32 + b.g + c.g + d.g) div 4).uint8,
((a.b.uint32 + b.b + c.b + d.b) div 4).uint8,
((a.a.uint32 + b.a + c.a + d.a) 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 + 2) 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 + 2) div 4).uint8
)
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)
loMask = mm_set_epi32(0, 0, uint32.high, uint32.high)
hiMask = mm_set_epi32(uint32.high, uint32.high, 0, 0)
vec2 = mm_set1_epi16(2)
for y in 0 ..< resultEvenHeight:
let
topRowStart = src.dataIndex(0, y * 2)
@ -390,8 +391,10 @@ proc minifyBy2Sse2*(image: Image, power = 1): Image {.simd.} =
bottomAddedOdd = mm_add_epi16(bottomOdd, bottomShiftedOdd)
addedEven = mm_add_epi16(topAddedEven, bottomAddedEven)
addedOdd = mm_add_epi16(topAddedOdd, bottomAddedOdd)
addedEvenDiv4 = mm_srli_epi16(addedEven, 2)
addedOddDiv4 = mm_srli_epi16(addedOdd, 2)
addedEvenRounding = mm_add_epi16(addedEven, vec2)
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))
mm_storeu_si128(result.data[result.dataIndex(x, y)].addr, merged)
x += 4
@ -403,10 +406,10 @@ proc minifyBy2Sse2*(image: Image, power = 1): Image {.simd.} =
c = src.data[bottomRowStart + x * 2 + 1]
d = src.data[bottomRowStart + x * 2]
mixed = rgbx(
((a.r.uint32 + b.r + c.r + d.r) div 4).uint8,
((a.g.uint32 + b.g + c.g + d.g) div 4).uint8,
((a.b.uint32 + b.b + c.b + d.b) div 4).uint8,
((a.a.uint32 + b.a + c.a + d.a) 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 + 2) 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 + 2) div 4).uint8
)
result.data[result.dataIndex(x, y)] = mixed