diff --git a/nimPNG.nim b/nimPNG.nim index f0bb368..cd6595b 100644 --- a/nimPNG.nim +++ b/nimPNG.nim @@ -28,7 +28,7 @@ import streams, endians, tables, hashes, math, nimz const - NIM_PNG_VERSION = "0.1.3" + NIM_PNG_VERSION = "0.1.5" type PNGChunkType = distinct int32 @@ -63,14 +63,14 @@ type IM_NONE = 0, IM_INTERLACED = 1 PNGChunk = ref object of RootObj - length: range[0..0x7FFFFFFF] + length: int #range[0..0x7FFFFFFF] chunkType: PNGChunkType crc: uint32 data: string pos: int PNGHeader = ref object of PNGChunk - width, height: range[1..0x7FFFFFFF] + width, height: int #range[1..0x7FFFFFFF] bitDepth: int colorType: PNGcolorType compressionMethod: int @@ -92,12 +92,12 @@ type idat: string PNGTime = ref object of PNGChunk - year: range[0..65535] - month: range[1..12] - day: range[1..31] - hour: range[0..23] - minute: range[0..59] - second: range[0..60] #to allow for leap seconds + year: int #range[0..65535] + month: int #range[1..12] + day: int #range[1..31] + hour: int #range[0..23] + minute: int #range[0..59] + second: int #range[0..60] #to allow for leap seconds PNGPhys = ref object of PNGChunk physX, physY: int @@ -175,12 +175,12 @@ type physX*, physY*, physUnit*: int timeDefined*: bool - year*: range[0..65535] - month*: range[1..12] - day*: range[1..31] - hour*: range[0..23] - minute*: range[0..59] - second*: range[0..60] #to allow for leap seconds + year*: int #range[0..65535] + month*: int #range[1..12] + day*: int #range[1..31] + hour*: int #range[0..23] + minute*: int #range[0..59] + second*: int #range[0..60] #to allow for leap seconds PNG* = ref object settings*: PNGSettings @@ -714,8 +714,7 @@ method parseChunk(chunk: PNGSbit, png: PNG): bool = result = true -proc make[T](): T = - result = new(T) +proc make[T](): T = new(result) proc createChunk(png: PNG, chunkType: PNGChunkType, data: string, crc: uint32): PNGChunk = var settings = PNGDecoder(png.settings) @@ -1867,12 +1866,12 @@ type physX*, physY*, physUnit*: int timeDefined*: bool - year*: range[0..65535] - month*: range[1..12] - day*: range[1..31] - hour*: range[0..23] - minute*: range[0..59] - second*: range[0..60] #to allow for leap seconds + year*: int #range[0..65535] + month*: int #range[1..12] + day*: int #range[1..31] + hour*: int #range[0..23] + minute*: int #range[0..59] + second*: int #range[0..60] #to allow for leap seconds unknown*: seq[PNGUnknown] @@ -2073,15 +2072,6 @@ method writeChunk(chunk: PNGStandarRGB, png: PNG): bool = chunk.writeByte(chunk.renderingIntent) result = true -method writeChunk(chunk: PNGICCProfile, png: PNG): bool = - #estimate chunk.profileName.len + 2 - chunk.writeString chunk.profileName - chunk.writeByte 0 #null separator - chunk.writeByte 0 #compression method(0: deflate) - var nz = nzDeflateInit(chunk.profile) - chunk.writeString zlib_compress(nz) - result = true - method writeChunk(chunk: PNGSPalette, png: PNG): bool = #estimate chunk.paletteName.len + 2 #if sampleDepth == 8: estimate += chunk.palette.len * 6 @@ -2106,7 +2096,7 @@ method writeChunk(chunk: PNGSPalette, png: PNG): bool = chunk.writeInt16(p.alpha) chunk.writeInt16(p.frequency) result = true - + method writeChunk(chunk: PNGHist, png: PNG): bool = #estimate chunk.histogram.len * 2 for c in chunk.histogram: @@ -2156,6 +2146,15 @@ method writeChunk(chunk: PNGItxt, png: PNG): bool = chunk.writeByte 0 #null separator chunk.writeString text result = true + +method writeChunk(chunk: PNGICCProfile, png: PNG): bool = + #estimate chunk.profileName.len + 2 + chunk.writeString chunk.profileName + chunk.writeByte 0 #null separator + chunk.writeByte 0 #compression method(0: deflate) + var nz = nzDeflateInit(chunk.profile) + chunk.writeString zlib_compress(nz) + result = true proc isGreyscaleType(mode: PNGColorMode): bool = result = mode.colorType in {LCT_GREY, LCT_GREY_ALPHA} diff --git a/nimPNG.nimble b/nimPNG.nimble index a202428..612b357 100644 --- a/nimPNG.nimble +++ b/nimPNG.nimble @@ -1,6 +1,6 @@ [Package] name = "nimPNG" -version = "0.1.3" +version = "0.1.5" author = "Andri Lim" description = "PNG encoder and decoder" license = "MIT" diff --git a/nimz.nim b/nimz.nim index b4da91b..0daec77 100644 --- a/nimz.nim +++ b/nimz.nim @@ -251,7 +251,7 @@ proc init_coins(c: var Coins, num: int) = proc cleanup_coins(c: var Coins, num: int) = for i in 0..num-1: c[i].symbols = @[] -proc coin_compare(a, b: Coin): int = +proc cmpx(a, b: Coin): int = var wa = a.weight var wb = b.weight if wa > wb: result = 1 @@ -266,42 +266,30 @@ proc append_symbol_coins(coins: Coins, start: int, frequencies: openarray[int], coins[j].symbols.add i inc j -proc placePivot[T](a: var openArray[T], lo, hi: int, cmp: proc(x, y: T): int): int = +proc placePivot[T](a: var openArray[T], lo, hi: int): int = var pivot = lo #set pivot var switch_i = lo + 1 + let x = lo+1 - for i in lo+1..hi: #run on array - if cmp(a[i], a[pivot]) <= 0: #compare pivot and i + for i in x..hi: #run on array + if cmpx(a[i], a[pivot]) <= 0: #compare pivot and i swap(a[i], a[switch_i]) #swap i and i to switch swap(a[pivot], a[switch_i]) #swap pivot and i to switch inc pivot #set current location of pivot inc switch_i #set location for i to switch with pivot result = pivot #return pivot location -proc quickSort[T](a: var openArray[T], lo, hi: int, cmp: proc(x, y: T): int) = +proc quickSort[T](a: var openArray[T], lo, hi: int) = if lo >= hi: return #stop condition #set pivot location - var pivot = placePivot(a, lo, hi, cmp) - quickSort(a, lo, pivot-1, cmp) #sort bottom half - quickSort(a, pivot+1, hi, cmp) #sort top half - -proc quickSort[T](a: var openArray[T], cmp: proc(x, y: T): int, length = -1) = + 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 - quickSort(a, lo, hi, cmp) - -type - c_coin {.pure, final.} = object - w: float - idx: int - -proc c_coin_cmp(a, b: pointer): int {.exportc, procvar, cdecl.} = - var aa = cast[ptr c_coin](a) - var bb = cast[ptr c_coin](b) - - if aa[].w > bb[].w: result = 1 - elif aa[].w < bb[].w: result = -1 - else: result = 0 + quickSort(a, lo, hi) proc huffman_code_lengths(frequencies: openarray[int], numcodes, maxbitlen: int): seq[int] = var @@ -311,7 +299,7 @@ proc huffman_code_lengths(frequencies: openarray[int], numcodes, maxbitlen: int) 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") @@ -349,7 +337,7 @@ proc huffman_code_lengths(frequencies: openarray[int], numcodes, maxbitlen: int) append_symbol_coins(coins, 0, frequencies, numcodes, sum) numcoins = numpresent - coins.quickSort(coin_compare, numcoins) + coins.quickSort(numcoins) var numprev = 0 for j in 1..maxbitlen: #each of the remaining rows @@ -374,8 +362,8 @@ 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(coin_compare, numcoins) + + coins.quickSort(numcoins) #calculate the lengths of each symbol, as the amount of times a coin of each symbol is used var i = 0 @@ -1211,30 +1199,29 @@ proc nzDeflate(nz: nzStream) = if nz.btype == 1: nz.deflateFixed(hash, datapos, dataend, final) elif nz.btype == 2: nz.deflateDynamic(hash, datapos, dataend, final) -proc nzInit(nz: nzStream) = +proc nzInit(): nzStream = const DEFAULT_WINDOWSIZE = 2048 - #compress with dynamic huffman tree - #(not in the mathematical sense, just not the predefined one) - nz.btype = 2 - nz.use_lz77 = true - nz.windowsize = DEFAULT_WINDOWSIZE - nz.minmatch = 3 - nz.nicematch = 128 - nz.lazymatching = true + result = nzStream( + #compress with dynamic huffman tree + #(not in the mathematical sense, just not the predefined one) + btype : 2, + use_lz77: true, + windowsize: DEFAULT_WINDOWSIZE, + minmatch: 3, + nicematch: 128, + lazymatching: true) proc nzDeflateInit*(input: string): nzStream = - var nz = new(nzStream) - nz.nzInit + var nz = nzInit() nz.data = input nz.bits.data = "" nz.bits.bitpointer = 0 - nz.mode = nzsDeflate + nz.mode = nzsDeflate result = nz proc nzInflateInit*(input: string): nzStream = - var nz = new(nzStream) - nz.nzInit + var nz = nzInit() nz.data = "" nz.bits.data = input nz.bits.bitpointer = 0