JS compatibility

This commit is contained in:
Yuriy Glukhov 2016-01-26 00:01:04 +02:00
parent 7b364c04bb
commit ba5d8131b3
4 changed files with 288 additions and 233 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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

47
private/buffer.nim Normal file
View File

@ -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

View File

@ -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() =