mirror of https://github.com/status-im/nimPNG.git
gc:arc refactor nimPNG encoder/decoder
This commit is contained in:
parent
b755b8811e
commit
a521c46f74
1029
nimPNG.nim
1029
nimPNG.nim
File diff suppressed because it is too large
Load Diff
|
@ -14,10 +14,10 @@ type
|
|||
|
||||
const
|
||||
# shared values used by multiple Adam7 related functions
|
||||
ADAM7_IX = [ 0, 4, 0, 2, 0, 1, 0 ] # x start values
|
||||
ADAM7_IY = [ 0, 0, 4, 0, 2, 0, 1 ] # y start values
|
||||
ADAM7_DX = [ 8, 8, 4, 4, 2, 2, 1 ] # x delta values
|
||||
ADAM7_DY = [ 8, 8, 8, 4, 4, 2, 2 ] # y delta values
|
||||
ADAM7_IX* = [ 0, 4, 0, 2, 0, 1, 0 ] # x start values
|
||||
ADAM7_IY* = [ 0, 0, 4, 0, 2, 0, 1 ] # y start values
|
||||
ADAM7_DX* = [ 8, 8, 4, 4, 2, 2, 1 ] # x delta values
|
||||
ADAM7_DY* = [ 8, 8, 8, 4, 4, 2, 2 ] # y delta values
|
||||
|
||||
# Paeth predicter, used by PNG filter type 4
|
||||
proc paethPredictor(a, b, c: int): uint =
|
||||
|
@ -400,11 +400,11 @@ proc unfilter*[T](output: var openArray[T], input: openArray[T], w, h, bpp: int)
|
|||
TWidth, lineTs, filterType)
|
||||
prevIndex = outIndex
|
||||
|
||||
proc readBitFromReversedStream[T](bitptr: var int, bitstream: openArray[T]): int =
|
||||
proc readBitFromReversedStream*[T](bitptr: var int, bitstream: openArray[T]): int =
|
||||
result = ((int(bitstream[bitptr shr 3]) shr (7 - (bitptr and 0x7))) and 1)
|
||||
inc bitptr
|
||||
|
||||
proc readBitsFromReversedStream[T](bitptr: var int, bitstream: openArray[T], nbits: int): int =
|
||||
proc readBitsFromReversedStream*[T](bitptr: var int, bitstream: openArray[T], nbits: int): int =
|
||||
result = 0
|
||||
var i = nbits - 1
|
||||
while i > -1:
|
||||
|
@ -417,20 +417,20 @@ proc `&=`[T](a: var T, b: T) =
|
|||
proc `|=`[T](a: var T, b: T) =
|
||||
a = T(int(a) or int(b))
|
||||
|
||||
proc setBitOfReversedStream0[T](bitptr: var int, bitstream: var openArray[T], bit: int) =
|
||||
proc setBitOfReversedStream0*[T](bitptr: var int, bitstream: var openArray[T], bit: int) =
|
||||
# the current bit in bitstream must be 0 for this to work
|
||||
if bit != 0:
|
||||
# earlier bit of huffman code is in a lesser significant bit of an earlier T
|
||||
bitstream[bitptr shr 3] |= T(bit shl (7 - (bitptr and 0x7)))
|
||||
bitstream[bitptr shr 3] |= cast[T](bit shl (7 - (bitptr and 0x7)))
|
||||
inc bitptr
|
||||
|
||||
proc setBitOfReversedStream[T](bitptr: var int, bitstream: var openArray[T], bit: int) =
|
||||
proc setBitOfReversedStream*[T](bitptr: var int, bitstream: var openArray[T], bit: int) =
|
||||
# the current bit in bitstream may be 0 or 1 for this to work
|
||||
if bit == 0: bitstream[bitptr shr 3] &= T(not (1 shl (7 - (bitptr and 0x7))))
|
||||
else: bitstream[bitptr shr 3] |= T(1 shl (7 - (bitptr and 0x7)))
|
||||
if bit == 0: bitstream[bitptr shr 3] &= cast[T](not (1 shl (7 - (bitptr and 0x7))))
|
||||
else: bitstream[bitptr shr 3] |= cast[T](1 shl (7 - (bitptr and 0x7)))
|
||||
inc bitptr
|
||||
|
||||
proc removePaddingBits[T](output: var openArray[T], input: openArray[T], olinebits, ilinebits, h: int) =
|
||||
proc removePaddingBits*[T](output: var openArray[T], input: openArray[T], olinebits, ilinebits, h: int) =
|
||||
# After filtering there are still padding bits if scanLines have non multiple of 8 bit amounts. They need
|
||||
# to be removed (except at last scanLine of (Adam7-reduced) image) before working with pure image buffers
|
||||
# for the Adam7 code, the color convert code and the output to the user.
|
||||
|
@ -462,7 +462,7 @@ proc removePaddingBits[T](output: var openArray[T], input: openArray[T], olinebi
|
|||
# bpp: bits per pixel
|
||||
# "padded" is only relevant if bpp is less than 8 and a scanLine or image does not
|
||||
# end at a full T
|
||||
proc adam7PassValues(pass: var PNGPass, w, h, bpp: int) =
|
||||
proc adam7PassValues*(pass: var PNGPass, w, h, bpp: int) =
|
||||
# the passstart values have 8 values:
|
||||
# the 8th one indicates the T after the end of the 7th (= last) pass
|
||||
|
||||
|
@ -554,3 +554,32 @@ proc adam7Interlace*[T](output: var openArray[T], input: openArray[T], w, h, bpp
|
|||
for b in 0..<bpp:
|
||||
let bit = readBitFromReversedStream(ibp, input)
|
||||
setBitOfReversedStream(obp, output, bit)
|
||||
|
||||
# index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to
|
||||
proc addColorBits*[T](output: var openArray[T], index, bits, input: int) =
|
||||
var m = 1
|
||||
if bits == 1: m = 7
|
||||
elif bits == 2: m = 3
|
||||
# p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half
|
||||
let p = index and m
|
||||
|
||||
var val = input and ((1 shl bits) - 1) # filter out any other bits of the input value
|
||||
val = val shl (bits * (m - p))
|
||||
let idx = index * bits div 8
|
||||
if p == 0: output[idx] = T(val)
|
||||
else: output[idx] = T(int(output[idx]) or val)
|
||||
|
||||
proc addPaddingBits*[T](output: var openArray[T], input: openArray[T], olinebits, ilinebits, h: int) =
|
||||
#The opposite of the removePaddingBits function
|
||||
#olinebits must be >= ilinebits
|
||||
|
||||
let diff = olinebits - ilinebits
|
||||
var
|
||||
obp = 0
|
||||
ibp = 0 #bit pointers
|
||||
|
||||
for y in 0..h-1:
|
||||
for x in 0..ilinebits-1:
|
||||
let bit = readBitFromReversedStream(ibp, input)
|
||||
setBitOfReversedStream(obp, output, bit)
|
||||
for x in 0..diff-1: setBitOfReversedStream(obp, output, 0)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import ../nimPNG, streams, math, strutils, tables, base64, os
|
||||
import ../nimPNG/buffer
|
||||
import ../nimPNG/[buffer, filters]
|
||||
|
||||
type
|
||||
Image = ref object
|
||||
|
@ -485,12 +485,12 @@ proc testPredefinedFilters() =
|
|||
var state = makePNGEncoder()
|
||||
state.filterStrategy = LFS_PREDEFINED
|
||||
state.filterPaletteZero = false
|
||||
|
||||
|
||||
# everything to filter type 'FLT_AVERAGE'
|
||||
state.predefinedFilters = newSeq[PNGFilter](h)
|
||||
for i in 0..<h:
|
||||
state.predefinedFilters[i] = FLT_AVERAGE
|
||||
|
||||
|
||||
var png = encodePNG(image.data, w, h, state)
|
||||
var outFilters = png.getFilterTypes()
|
||||
|
||||
|
@ -591,12 +591,15 @@ proc colorConvertTest(bits_in: string, colorType_in: PNGcolorType, bitDepth_in:
|
|||
|
||||
echo "color convert test ", bits_in, " - ", bits_out
|
||||
let expected = bitStringToBytes(bits_out)
|
||||
let image = initBuffer(bitStringToBytes(bits_in))
|
||||
let image = bitStringToBytes(bits_in)
|
||||
let modeIn = newColorMode(colorType_in, bitDepth_in)
|
||||
let modeOut = newColorMode(colorType_out, bitDepth_out)
|
||||
var actual = newString(expected.len)
|
||||
var actualView = initBuffer(actual)
|
||||
convert(actualView, image, modeOut, modeIn, 1)
|
||||
convert(
|
||||
actual.toOpenArray(0, actual.len-1),
|
||||
image.toOpenArray(0, image.len-1),
|
||||
modeOut, modeIn, 1)
|
||||
|
||||
for i in 0..expected.high:
|
||||
assertEquals(expected[i].int, actual[i].int, "byte " & $i)
|
||||
|
||||
|
@ -674,19 +677,19 @@ proc testColorConvert2() =
|
|||
(colorType: LCT_RGBA, bitDepth: 8),
|
||||
(colorType: LCT_RGBA, bitDepth: 16)]
|
||||
|
||||
eight = initBuffer([0,0,0,255, 255,255,255,255,
|
||||
eight = [0,0,0,255, 255,255,255,255,
|
||||
0,0,0,255, 255,255,255,255,
|
||||
255,255,255,255, 0,0,0,255,
|
||||
255,255,255,255, 255,255,255,255,
|
||||
0,0,0,255].toString()) #input in RGBA8
|
||||
0,0,0,255].toString() #input in RGBA8
|
||||
|
||||
var
|
||||
modeIn = newColorMode()
|
||||
modeOut = newColorMode()
|
||||
mode_8 = newColorMode()
|
||||
input = initBuffer(newString(72))
|
||||
output = initBuffer(newString(72))
|
||||
eight2 = initBuffer(newString(36))
|
||||
input = newString(72)
|
||||
output = newString(72)
|
||||
eight2 = newString(36)
|
||||
|
||||
for i in 0..255:
|
||||
let j = if i == 1: 255 else: i
|
||||
|
@ -701,10 +704,10 @@ proc testColorConvert2() =
|
|||
modeOut.colorType = cmb.colorType
|
||||
modeOut.bitDepth = cmb.bitDepth
|
||||
|
||||
convert(input, eight, modeIn, mode_8, 3 * 3)
|
||||
convert(output, input, modeOut, modeIn, 3 * 3) #Test input to output type
|
||||
convert(eight2, output, mode_8, modeOut, 3 * 3)
|
||||
assertEquals(eight.data, eight2.data)
|
||||
convert(input.toOpenArray(0, input.len-1), eight.toOpenArray(0, eight.len-1), modeIn, mode_8, 3 * 3)
|
||||
convert(output.toOpenArray(0, output.len-1), input.toOpenArray(0, input.len-1), modeOut, modeIn, 3 * 3) #Test input to output type
|
||||
convert(eight2.toOpenArray(0, eight2.len-1), output.toOpenArray(0, output.len-1), mode_8, modeOut, 3 * 3)
|
||||
assertEquals(eight, eight2)
|
||||
|
||||
#tests that there are no crashes with auto color chooser in case of palettes with translucency etc...
|
||||
proc testPaletteToPaletteConvert() =
|
||||
|
@ -1198,5 +1201,5 @@ proc doMain() =
|
|||
testNoAutoConvert()
|
||||
testAutoColorModels()
|
||||
testFilter()
|
||||
|
||||
|
||||
doMain()
|
||||
|
|
Loading…
Reference in New Issue