From 104cfb03d6b5af85f8cc42a9e7ff03beed54cfb7 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Tue, 14 Jun 2022 17:44:49 -0500 Subject: [PATCH 1/3] use names --- src/pixie/fileformats/gif.nim | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/pixie/fileformats/gif.nim b/src/pixie/fileformats/gif.nim index 6dd75fb..a061d6e 100644 --- a/src/pixie/fileformats/gif.nim +++ b/src/pixie/fileformats/gif.nim @@ -171,7 +171,7 @@ proc decodeGif*(data: string): Gif {.raises: [PixieError].} = colorIndexes: seq[int] codeSize = minCodeSize + 1 table = newSeq[(int, int)](endCode + 1) - prev: (int, int) + prev: tuple[offset, len: int] while true: 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 < clearCode: colorIndexes.add(code) - if prev[1] > 0: - table.add((prev[0], prev[1] + 1)) + if prev.len > 0: + table.add((prev.offset, prev.len + 1)) prev = (start, 1) else: let (offset, len) = table[code] for i in 0 ..< len: colorIndexes.add(colorIndexes[offset + i]) - table.add((prev[0], prev[1] + 1)) + table.add((prev.offset, prev.len + 1)) prev = (start, len) else: if prev[1] == 0: @@ -209,8 +209,8 @@ proc decodeGif*(data: string): Gif {.raises: [PixieError].} = for i in 0 ..< prev[1]: colorIndexes.add(colorIndexes[prev[0] + i]) colorIndexes.add(colorIndexes[prev[0]]) - table.add((start, prev[1] + 1)) - prev = (start, prev[1] + 1) + table.add((start, prev.len + 1)) + prev = (start, prev.len + 1) if colorIndexes.len != imageWidth * imageHeight: failInvalid() @@ -243,6 +243,8 @@ proc decodeGif*(data: string): Gif {.raises: [PixieError].} = image.data[i] = globalColorTable[colorIndex] 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) var y: int From 1e6070c1508995039ecbef1a11789c1da2f7477f Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Tue, 14 Jun 2022 17:54:02 -0500 Subject: [PATCH 2/3] much faster toStraightAlpha --- src/pixie/internal.nim | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/pixie/internal.nim b/src/pixie/internal.nim index e5cb53e..3f309a6 100644 --- a/src/pixie/internal.nim +++ b/src/pixie/internal.nim @@ -81,16 +81,23 @@ proc fillUnsafe*( for j in i ..< start + len: 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: [].} = ## Converts an image from premultiplied alpha to straight alpha. ## This is expensive for large images. - for c in data.mitems: - if c.a == 0 or c.a == 255: - continue - let multiplier = ((255 / c.a.float32) * 255).uint32 - c.r = ((c.r.uint32 * multiplier) div 255).uint8 - c.g = ((c.g.uint32 * multiplier) div 255).uint8 - c.b = ((c.b.uint32 * multiplier) div 255).uint8 + for i in 0 ..< data.len: + var c = data[i] + c.r = straightAlphaTable[c.a][c.r] + c.g = straightAlphaTable[c.a][c.g] + c.b = straightAlphaTable[c.a][c.b] + data[i] = c proc toPremultipliedAlpha*(data: var seq[ColorRGBA | ColorRGBX]) {.raises: [].} = ## Converts an image to premultiplied alpha from straight alpha. From 48d66fabec674a86f61c90eb9eaff8a2d9c85d11 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Tue, 14 Jun 2022 18:04:08 -0500 Subject: [PATCH 3/3] should have this --- src/pixie/internal.nim | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pixie/internal.nim b/src/pixie/internal.nim index 3f309a6..9fda619 100644 --- a/src/pixie/internal.nim +++ b/src/pixie/internal.nim @@ -10,6 +10,9 @@ template currentExceptionAsPixieError*(): untyped = let e = getCurrentException() newException(PixieError, e.getStackTrace & e.msg, e) +when defined(release): + {.push checks: off.} + proc gaussianKernel*(radius: int): seq[uint16] {.raises: [].} = ## Compute lookup table for 1d Gaussian kernel. ## Values are [0, 255] * 256. @@ -194,3 +197,6 @@ when defined(amd64) and allowSimd: a = mm_unpacklo_epi8(v, mm_setzero_si128()) b = mm_unpacklo_epi8(a, mm_setzero_si128()) result = mm_slli_epi32(b, 24) # Shift the values to uint32 `a` + +when defined(release): + {.pop.}