mirror of https://github.com/status-im/nimPNG.git
JS compatibility
This commit is contained in:
parent
7b364c04bb
commit
ba5d8131b3
397
nimPNG.nim
397
nimPNG.nim
File diff suppressed because it is too large
Load Diff
49
nimz.nim
49
nimz.nim
|
@ -199,15 +199,14 @@ proc HuffmanTree_make2DTree(tree: var HuffmanTree) =
|
|||
tree.tree2d[branch] = n #put the current code in it
|
||||
treepos = 0 #start from root again
|
||||
|
||||
for it in mitems(tree.tree2d):
|
||||
if it == 32767: it = 0 #remove possible remaining 32767's
|
||||
tree.tree2d.applyIt(if it == 32767: 0 else: it) #remove possible remaining 32767's
|
||||
|
||||
#Second step for the ...makeFromLengths and ...makeFromFrequencies functions.
|
||||
#numcodes, lengths and maxbitlen must already be filled in correctly.
|
||||
proc HuffmanTree_makeFromLengths2(tree: var HuffmanTree) =
|
||||
tree.tree1d = newSeq[int](tree.numcodes)
|
||||
var blcount = newSeqWith(tree.maxbitlen + 1, 0)
|
||||
var nextcode = newSeqWith(tree.maxbitlen + 1, 0)
|
||||
var blcount = newSeq[int](tree.maxbitlen + 1)
|
||||
var nextcode = newSeq[int](tree.maxbitlen + 1)
|
||||
|
||||
#step 1: count number of instances of each code length
|
||||
for len in tree.lengths: inc blcount[len]
|
||||
|
@ -285,7 +284,7 @@ proc quickSort[T](a: var openArray[T], lo, hi: int) =
|
|||
var pivot = placePivot(a, lo, hi)
|
||||
quickSort(a, lo, pivot-1) #sort bottom half
|
||||
quickSort(a, pivot+1, hi) #sort top half
|
||||
|
||||
|
||||
proc quickSort[T](a: var openArray[T], length = -1) =
|
||||
var lo = 0
|
||||
var hi = if length < 0: a.high else: length-1
|
||||
|
@ -293,13 +292,13 @@ proc quickSort[T](a: var openArray[T], length = -1) =
|
|||
|
||||
proc huffman_code_lengths(frequencies: openarray[int], numcodes, maxbitlen: int): seq[int] =
|
||||
var
|
||||
lengths = newSeqWith(numcodes, 0)
|
||||
lengths = newSeq[int](numcodes)
|
||||
sum = 0
|
||||
numpresent = 0
|
||||
coins: Coins #the coins of the currently calculated row
|
||||
prev_row: Coins #the previous row of coins
|
||||
coinmem, numcoins: int
|
||||
|
||||
|
||||
if numcodes == 0:
|
||||
raise newNZError("a tree of 0 symbols is not supposed to be made")
|
||||
|
||||
|
@ -362,7 +361,7 @@ proc huffman_code_lengths(frequencies: openarray[int], numcodes, maxbitlen: int)
|
|||
if j < maxbitlen:
|
||||
append_symbol_coins(coins, numcoins, frequencies, numcodes, sum)
|
||||
inc(numcoins, numpresent)
|
||||
|
||||
|
||||
coins.quickSort(numcoins)
|
||||
|
||||
#calculate the lengths of each symbol, as the amount of times a coin of each symbol is used
|
||||
|
@ -482,8 +481,8 @@ proc getTreeInflateDynamic(s: var BitStream, tree_ll, tree_d: var HuffmanTree) =
|
|||
|
||||
#see comments in deflateDynamic for explanation
|
||||
#of the context and these variables, it is analogous
|
||||
var bitlen_ll = newSeqWith(NUM_DEFLATE_CODE_SYMBOLS, 0) #lit,len code lengths
|
||||
var bitlen_d = newSeqWith(NUM_DISTANCE_SYMBOLS, 0) #dist code lengths
|
||||
var bitlen_ll = newSeq[int](NUM_DEFLATE_CODE_SYMBOLS) #lit,len code lengths
|
||||
var bitlen_d = newSeq[int](NUM_DISTANCE_SYMBOLS) #dist code lengths
|
||||
|
||||
#code length code lengths ("clcl"),
|
||||
#the bit lengths of the huffman tree
|
||||
|
@ -1034,8 +1033,8 @@ proc deflateDynamic(nz: nzStream, hash: var NZHash, datapos, dataend: int, final
|
|||
lz77 = newSeq[int](datasize)
|
||||
for i in datapos..dataend-1: lz77[i] = ord(nz.data[i])
|
||||
|
||||
var frequencies_ll = newSeqWith(286, 0) #frequency of lit,len codes
|
||||
var frequencies_d = newSeqWith(30, 0) #frequency of dist codes
|
||||
var frequencies_ll = newSeq[int](286) #frequency of lit,len codes
|
||||
var frequencies_d = newSeq[int](30) #frequency of dist codes
|
||||
|
||||
#Count the frequencies of lit, len and dist codes
|
||||
var i = 0
|
||||
|
@ -1099,7 +1098,7 @@ proc deflateDynamic(nz: nzStream, hash: var NZHash, datapos, dataend: int, final
|
|||
inc i
|
||||
|
||||
#generate tree_cl, the huffmantree of huffmantrees
|
||||
frequencies_cl = newSeqWith(NUM_CODE_LENGTH_CODES, 0)
|
||||
frequencies_cl = newSeq[int](NUM_CODE_LENGTH_CODES)
|
||||
i = 0
|
||||
while i < bitlen_lld_e.len:
|
||||
inc frequencies_cl[bitlen_lld_e[i]]
|
||||
|
@ -1178,7 +1177,7 @@ proc nzDeflate(nz: nzStream) =
|
|||
var hash: NZHash
|
||||
var blocksize = 0
|
||||
var insize = nz.data.len
|
||||
|
||||
|
||||
if nz.btype > 2: raise newNZError("invalid block type")
|
||||
elif nz.btype == 0:
|
||||
nz.deflateNoCompression
|
||||
|
@ -1186,16 +1185,16 @@ proc nzDeflate(nz: nzStream) =
|
|||
elif nz.btype == 1: blocksize = insize
|
||||
else: blocksize = max(insize div 8 + 8, 65535) #if(nz.btype == 2)
|
||||
#if blocksize < 65535: blocksize = 65535
|
||||
|
||||
|
||||
var numdeflateblocks = (insize + blocksize - 1) div blocksize
|
||||
if numdeflateblocks == 0: numdeflateblocks = 1
|
||||
nimzHashInit(hash, nz.windowsize)
|
||||
|
||||
|
||||
for i in 0..numdeflateblocks-1:
|
||||
let final = (i == numdeflateblocks - 1)
|
||||
let datapos = i * blocksize
|
||||
let dataend = min(datapos + blocksize, insize)
|
||||
|
||||
|
||||
if nz.btype == 1: nz.deflateFixed(hash, datapos, dataend, final)
|
||||
elif nz.btype == 2: nz.deflateDynamic(hash, datapos, dataend, final)
|
||||
|
||||
|
@ -1217,7 +1216,7 @@ proc nzDeflateInit*(input: string): nzStream =
|
|||
nz.data = input
|
||||
nz.bits.data = ""
|
||||
nz.bits.bitpointer = 0
|
||||
nz.mode = nzsDeflate
|
||||
nz.mode = nzsDeflate
|
||||
result = nz
|
||||
|
||||
proc nzInflateInit*(input: string): nzStream =
|
||||
|
@ -1246,15 +1245,15 @@ proc nzAdler32(adler: uint32, data: string): uint32 =
|
|||
var amount = min(len, 5550)
|
||||
dec(len, amount)
|
||||
while amount > 0:
|
||||
s1 += cast[uint32](ord(data[i]))
|
||||
s1 += cast[uint32](ord(data[i]) or 0)
|
||||
s2 += s1
|
||||
dec(amount)
|
||||
inc(i)
|
||||
|
||||
s1 = s1 mod 65521'u32
|
||||
s2 = s2 mod 65521'u32
|
||||
s1 = s1 mod 65521.uint32
|
||||
s2 = s2 mod 65521.uint32
|
||||
|
||||
result = (s2 shl 16'u32) or s1
|
||||
result = (s2 shl 16.uint32) or s1
|
||||
|
||||
proc add32bitInt(s: var BitStream, val: uint32) =
|
||||
s.data.add chr(cast[int](val shr 24) and 0xff)
|
||||
|
@ -1280,7 +1279,7 @@ proc zlib_compress*(nz: nzStream): string =
|
|||
nz.bits.data.add chr(CMFFLG div 256)
|
||||
nz.bits.data.add chr(CMFFLG mod 256)
|
||||
nz.bits.bitpointer += 16
|
||||
|
||||
|
||||
nz.nzDeflate
|
||||
nz.bits.add32bitInt nzAdler32(1, nz.data)
|
||||
result = nz.nzGetResult
|
||||
|
@ -1293,7 +1292,7 @@ proc readInt32(input: string): uint32 =
|
|||
result += cast[uint32](ord(input[3]))
|
||||
|
||||
proc zlib_decompress*(nz: nzStream): string =
|
||||
var insize = nz.bits.data.len
|
||||
let insize = nz.bits.data.len
|
||||
|
||||
if insize < 2: raise newNZError("size of zlib data too small")
|
||||
|
||||
|
@ -1319,7 +1318,7 @@ proc zlib_decompress*(nz: nzStream): string =
|
|||
#"The additional flags shall not specify a preset dictionary."*/
|
||||
#return 26;
|
||||
|
||||
let checksum = nz.bits.data.substr(insize-4, insize).readInt32
|
||||
let checksum = nz.bits.data.substr(insize-4, insize-1).readInt32
|
||||
nz.bits.data.setLen(insize-4)
|
||||
|
||||
nz.nzInflate
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import sequtils
|
||||
|
||||
type
|
||||
Buffer*[T] = object ## Uses T as internal data buffer
|
||||
data*: T
|
||||
offset*: int
|
||||
SeqBuffer*[T] = Buffer[seq[T]] ## Uses seq[T] as internal data buffer
|
||||
|
||||
template `[]`*[T](b: Buffer[T], i: int): auto = b.data[b.offset + i]
|
||||
template `[]=`*[S, T](b: var Buffer[S], i: int, v: T) = b.data[b.offset + i] = v
|
||||
|
||||
proc init*[T](b: var Buffer[T], d: T) =
|
||||
shallowCopy(b.data, d)
|
||||
b.offset = 0
|
||||
|
||||
proc initBuffer*[T](d: T): Buffer[T] =
|
||||
shallowCopy(result.data, d)
|
||||
|
||||
proc subbuffer*[T](b: Buffer[T], offset: int): Buffer[T] =
|
||||
shallowCopy(result.data, b.data)
|
||||
result.offset = b.offset + offset
|
||||
|
||||
template isNil*[T](b: Buffer[T]): bool = b.data.isNil
|
||||
|
||||
template copyElements*[T](dst: var Buffer[T], src: Buffer[T], count: int) =
|
||||
when defined(js):
|
||||
for i in 0 ..< count: dst[i] = src[i]
|
||||
else:
|
||||
copyMem(addr dst[dst.offset], unsafeAddr src[src.offset], count * sizeof(dst[0]))
|
||||
|
||||
template zeroMem*[T](dst: var Buffer[T]) =
|
||||
when defined(js):
|
||||
applyIt(dst.data, type(dst[0])(0))
|
||||
else:
|
||||
zeroMem(addr dst.data[dst.offset], sizeof(dst[0]) * (dst.data.len - dst.offset))
|
||||
|
||||
when isMainModule:
|
||||
var buf: SeqBuffer[uint8]
|
||||
buf.init(newSeq[uint8](1024))
|
||||
buf[1] = 5
|
||||
buf.offset = 1
|
||||
echo buf[0].int
|
||||
|
||||
var strBuf = initBuffer(newString(20))
|
||||
strBuf[1] = 'A'
|
||||
let subBuf = strBuf.subbuffer(1)
|
||||
echo subBuf[0] # Should print A
|
|
@ -1,4 +1,5 @@
|
|||
import nimPNG, streams, math, strutils, tables, base64, os
|
||||
import private.buffer
|
||||
|
||||
type
|
||||
Image = ref object
|
||||
|
@ -551,12 +552,12 @@ 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 = bitStringToBytes(bits_in)
|
||||
let image = initBuffer(bitStringToBytes(bits_in))
|
||||
let modeIn = newColorMode(colorType_in, bitDepth_in)
|
||||
let modeOut = newColorMode(colorType_out, bitDepth_out)
|
||||
var actual = newString(expected.len)
|
||||
var output = cstring(actual)
|
||||
convert(output, image.cstring, modeOut, modeIn, 1)
|
||||
var actualView = initBuffer(actual)
|
||||
convert(actualView, image, modeOut, modeIn, 1)
|
||||
for i in 0..expected.high:
|
||||
assertEquals(expected[i].int, actual[i].int, "byte " & $i)
|
||||
|
||||
|
@ -634,22 +635,19 @@ proc testColorConvert2() =
|
|||
(colorType: LCT_RGBA, bitDepth: 8),
|
||||
(colorType: LCT_RGBA, bitDepth: 16)]
|
||||
|
||||
eight = [0,0,0,255, 255,255,255,255,
|
||||
eight = initBuffer([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 = newString(72)
|
||||
output = newString(72)
|
||||
inp = input.cstring
|
||||
outp = output.cstring
|
||||
eight2 = newString(36)
|
||||
e2p = eight2.cstring
|
||||
input = initBuffer(newString(72))
|
||||
output = initBuffer(newString(72))
|
||||
eight2 = initBuffer(newString(36))
|
||||
|
||||
for i in 0..255:
|
||||
let j = if i == 1: 255 else: i
|
||||
|
@ -664,10 +662,10 @@ proc testColorConvert2() =
|
|||
modeOut.colorType = cmb.colorType
|
||||
modeOut.bitDepth = cmb.bitDepth
|
||||
|
||||
convert(inp, eight.cstring, modeIn, mode_8, 3 * 3)
|
||||
convert(outp, inp, modeOut, modeIn, 3 * 3) #Test input to output type
|
||||
convert(e2p, outp, mode_8, modeOut, 3 * 3)
|
||||
assertEquals(eight, eight2)
|
||||
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)
|
||||
|
||||
#tests that there are no crashes with auto color chooser in case of palettes with translucency etc...
|
||||
proc testPaletteToPaletteConvert() =
|
||||
|
|
Loading…
Reference in New Issue