Merge pull request #514 from treeform/guzba

produce smaller pngs
This commit is contained in:
Andre von Houck 2022-12-10 08:38:58 -08:00 committed by GitHub
commit a911e9d498
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 10 deletions

View file

@ -1,4 +1,4 @@
version = "5.0.1" version = "5.0.2"
author = "Andre von Houck and Ryan Oldenburg" author = "Andre von Houck and Ryan Oldenburg"
description = "Full-featured 2d graphics library for Nim." description = "Full-featured 2d graphics library for Nim."
license = "MIT" license = "MIT"

View file

@ -1,7 +1,7 @@
import bumpy, chroma, vmath import bumpy, chroma, vmath
type type
PixieError* = object of ValueError ## Raised if an operation fails. PixieError* = object of CatchableError ## Raised if an operation fails.
BlendMode* = enum BlendMode* = enum
NormalBlend NormalBlend

View file

@ -575,22 +575,59 @@ proc encodePng*(
# Add IDAT # Add IDAT
# Add room for 1 byte before each row for the filter type. # Add room for 1 byte before each row for the filter type.
var filtered = newString(width * height * channels + height) var
filtered = newString(width * height * channels + height)
upRow = newSeq[uint8](width * channels)
subRow = newSeq[uint8](width * channels)
avgRow = newSeq[uint8](width * channels)
for y in 0 ..< height: for y in 0 ..< height:
filtered[y * width * channels + y] = 2.char # Up filter type let rowStart = y * width * channels
for x in 0 ..< width * channels: for x in 0 ..< width * channels:
# Move through the image data byte-by-byte # Move through the image data byte-by-byte
let let dataPos = rowStart + x
dataPos = y * width * channels + x var left, up: uint8
filteredPos = y * width * channels + y + 1 + x if x - channels >= 0:
var up: uint8 left = data[dataPos - channels]
if y - 1 >= 0: if y - 1 >= 0:
up = data[(y - 1) * width * channels + x] up = data[(y - 1) * width * channels + x]
filtered[filteredPos] = (data[dataPos] - up).char upRow[x] = data[dataPos] - up.uint8
subRow[x] = data[dataPos] - left.uint8
let avg = ((left.int + up.int) div 2).uint8
avgRow[x] = data[dataPos] - avg
var upRowSum, subRowSum, avgRowSum: uint64
for i in 0 ..< upRow.len:
upRowSum += upRow[i]
subRowSum += subRow[i]
avgRowSum += avgRow[i]
let minRowSum = min(min(upRowSum, subRowSum), avgRowSum)
if upRowSum == minRowSum:
filtered[rowStart + y] = 2.char # Up filter type
copyMem(
filtered[rowStart + y + 1].addr,
upRow[0].addr,
upRow.len
)
elif subRowSum == minRowSum:
filtered[rowStart + y] = 1.char # Sub filter type
copyMem(
filtered[rowStart + y + 1].addr,
subRow[0].addr,
subRow.len
)
else:
filtered[rowStart + y] = 3.char # Average filter type
copyMem(
filtered[rowStart + y + 1].addr,
avgRow[0].addr,
avgRow.len
)
let compressed = let compressed =
try: try:
compress(filtered, BestSpeed, dfZlib) compress(filtered, DefaultCompression, dfZlib)
except ZippyError: except ZippyError:
raise newException( raise newException(
PixieError, "Unexpected error compressing PNG image data" PixieError, "Unexpected error compressing PNG image data"