Merge pull request #440 from guzba/master
much faster toStraightAlpha + other stuff
This commit is contained in:
commit
0af140b047
2 changed files with 28 additions and 13 deletions
|
@ -171,7 +171,7 @@ proc decodeGif*(data: string): Gif {.raises: [PixieError].} =
|
||||||
colorIndexes: seq[int]
|
colorIndexes: seq[int]
|
||||||
codeSize = minCodeSize + 1
|
codeSize = minCodeSize + 1
|
||||||
table = newSeq[(int, int)](endCode + 1)
|
table = newSeq[(int, int)](endCode + 1)
|
||||||
prev: (int, int)
|
prev: tuple[offset, len: int]
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
let code = b.readBits(codeSize).int
|
let code = b.readBits(codeSize).int
|
||||||
|
@ -194,14 +194,14 @@ proc decodeGif*(data: string): Gif {.raises: [PixieError].} =
|
||||||
if code < table.len: # If we have seen the code before
|
if code < table.len: # If we have seen the code before
|
||||||
if code < clearCode:
|
if code < clearCode:
|
||||||
colorIndexes.add(code)
|
colorIndexes.add(code)
|
||||||
if prev[1] > 0:
|
if prev.len > 0:
|
||||||
table.add((prev[0], prev[1] + 1))
|
table.add((prev.offset, prev.len + 1))
|
||||||
prev = (start, 1)
|
prev = (start, 1)
|
||||||
else:
|
else:
|
||||||
let (offset, len) = table[code]
|
let (offset, len) = table[code]
|
||||||
for i in 0 ..< len:
|
for i in 0 ..< len:
|
||||||
colorIndexes.add(colorIndexes[offset + i])
|
colorIndexes.add(colorIndexes[offset + i])
|
||||||
table.add((prev[0], prev[1] + 1))
|
table.add((prev.offset, prev.len + 1))
|
||||||
prev = (start, len)
|
prev = (start, len)
|
||||||
else:
|
else:
|
||||||
if prev[1] == 0:
|
if prev[1] == 0:
|
||||||
|
@ -209,8 +209,8 @@ proc decodeGif*(data: string): Gif {.raises: [PixieError].} =
|
||||||
for i in 0 ..< prev[1]:
|
for i in 0 ..< prev[1]:
|
||||||
colorIndexes.add(colorIndexes[prev[0] + i])
|
colorIndexes.add(colorIndexes[prev[0] + i])
|
||||||
colorIndexes.add(colorIndexes[prev[0]])
|
colorIndexes.add(colorIndexes[prev[0]])
|
||||||
table.add((start, prev[1] + 1))
|
table.add((start, prev.len + 1))
|
||||||
prev = (start, prev[1] + 1)
|
prev = (start, prev.len + 1)
|
||||||
|
|
||||||
if colorIndexes.len != imageWidth * imageHeight:
|
if colorIndexes.len != imageWidth * imageHeight:
|
||||||
failInvalid()
|
failInvalid()
|
||||||
|
@ -243,6 +243,8 @@ proc decodeGif*(data: string): Gif {.raises: [PixieError].} =
|
||||||
image.data[i] = globalColorTable[colorIndex]
|
image.data[i] = globalColorTable[colorIndex]
|
||||||
|
|
||||||
if interlaced:
|
if interlaced:
|
||||||
|
# Just copyMem the rows into the right place. I've only ever seen
|
||||||
|
# interlaced for the first frame so this is unlikely to be a hot path.
|
||||||
let deinterlaced = newImage(image.width, image.height)
|
let deinterlaced = newImage(image.width, image.height)
|
||||||
var
|
var
|
||||||
y: int
|
y: int
|
||||||
|
|
|
@ -10,6 +10,9 @@ template currentExceptionAsPixieError*(): untyped =
|
||||||
let e = getCurrentException()
|
let e = getCurrentException()
|
||||||
newException(PixieError, e.getStackTrace & e.msg, e)
|
newException(PixieError, e.getStackTrace & e.msg, e)
|
||||||
|
|
||||||
|
when defined(release):
|
||||||
|
{.push checks: off.}
|
||||||
|
|
||||||
proc gaussianKernel*(radius: int): seq[uint16] {.raises: [].} =
|
proc gaussianKernel*(radius: int): seq[uint16] {.raises: [].} =
|
||||||
## Compute lookup table for 1d Gaussian kernel.
|
## Compute lookup table for 1d Gaussian kernel.
|
||||||
## Values are [0, 255] * 256.
|
## Values are [0, 255] * 256.
|
||||||
|
@ -81,16 +84,23 @@ proc fillUnsafe*(
|
||||||
for j in i ..< start + len:
|
for j in i ..< start + len:
|
||||||
data[j] = rgbx
|
data[j] = rgbx
|
||||||
|
|
||||||
|
const straightAlphaTable = block:
|
||||||
|
var table: array[256, array[256, uint8]]
|
||||||
|
for a in 0 ..< 256:
|
||||||
|
let multiplier = if a > 0: (255 / a.float32) else: 0
|
||||||
|
for c in 0 ..< 256:
|
||||||
|
table[a][c] = min(round((c.float32 * multiplier)), 255).uint8
|
||||||
|
table
|
||||||
|
|
||||||
proc toStraightAlpha*(data: var seq[ColorRGBA | ColorRGBX]) {.raises: [].} =
|
proc toStraightAlpha*(data: var seq[ColorRGBA | ColorRGBX]) {.raises: [].} =
|
||||||
## Converts an image from premultiplied alpha to straight alpha.
|
## Converts an image from premultiplied alpha to straight alpha.
|
||||||
## This is expensive for large images.
|
## This is expensive for large images.
|
||||||
for c in data.mitems:
|
for i in 0 ..< data.len:
|
||||||
if c.a == 0 or c.a == 255:
|
var c = data[i]
|
||||||
continue
|
c.r = straightAlphaTable[c.a][c.r]
|
||||||
let multiplier = ((255 / c.a.float32) * 255).uint32
|
c.g = straightAlphaTable[c.a][c.g]
|
||||||
c.r = ((c.r.uint32 * multiplier) div 255).uint8
|
c.b = straightAlphaTable[c.a][c.b]
|
||||||
c.g = ((c.g.uint32 * multiplier) div 255).uint8
|
data[i] = c
|
||||||
c.b = ((c.b.uint32 * multiplier) div 255).uint8
|
|
||||||
|
|
||||||
proc toPremultipliedAlpha*(data: var seq[ColorRGBA | ColorRGBX]) {.raises: [].} =
|
proc toPremultipliedAlpha*(data: var seq[ColorRGBA | ColorRGBX]) {.raises: [].} =
|
||||||
## Converts an image to premultiplied alpha from straight alpha.
|
## Converts an image to premultiplied alpha from straight alpha.
|
||||||
|
@ -187,3 +197,6 @@ when defined(amd64) and allowSimd:
|
||||||
a = mm_unpacklo_epi8(v, mm_setzero_si128())
|
a = mm_unpacklo_epi8(v, mm_setzero_si128())
|
||||||
b = mm_unpacklo_epi8(a, mm_setzero_si128())
|
b = mm_unpacklo_epi8(a, mm_setzero_si128())
|
||||||
result = mm_slli_epi32(b, 24) # Shift the values to uint32 `a`
|
result = mm_slli_epi32(b, 24) # Shift the values to uint32 `a`
|
||||||
|
|
||||||
|
when defined(release):
|
||||||
|
{.pop.}
|
||||||
|
|
Loading…
Reference in a new issue