diff --git a/nimPNG.nim b/nimPNG.nim index 0976958..1e233a4 100644 --- a/nimPNG.nim +++ b/nimPNG.nim @@ -30,6 +30,8 @@ import nimPNG/[buffer, nimz, filters, results] import strutils +export typetraits, results + const NIM_PNG_VERSION = "0.3.0" @@ -254,7 +256,7 @@ proc `$`*(tag: PNGChunkType): string = result[2] = chr(uint32(t shr 8) and 0xFF) result[3] = chr(uint32(t) and 0xFF) -proc `==`(a, b: PNGChunkType): bool = int(a) == int(b) +proc `==`*(a, b: PNGChunkType): bool = int(a) == int(b) #proc isAncillary(a: PNGChunkType): bool = (int(a) and (32 shl 24)) != 0 #proc isPrivate(a: PNGChunkType): bool = (int(a) and (32 shl 16)) != 0 #proc isSafeToCopy(a: PNGChunkType): bool = (int(a) and 32) != 0 @@ -271,6 +273,18 @@ proc crc32(crc: uint32, buf: string): uint32 = result = not crcu32 +template newStorage[T](size: int): T = + when T is string: + newString(size) + else: + newSeq[uint8](size) + +template newStorageOfCap[T](size: int): T = + when T is string: + newStringOfCap(size) + else: + newSeqOfCap[uint8](size) + const PNGSignature = signatureMaker() IHDR = makeChunkType("IHDR") @@ -381,7 +395,7 @@ proc readByte(s: PNGChunk): int = inc s.pos template readEnum(s: PNGChunk, T: type): untyped = - let typ = s.readByte.int + let typ = readByte(s).int if typ < low(T).int or typ > high(T).int: raise PNGFatal("Wrong " & T.name & " value " & $typ) T(typ) @@ -949,7 +963,8 @@ proc parsePNG[T](s: Stream, settings: PNGDecoder): PNG[T] = if not idat.validateChunk(png): raise PNGFatal("bad IDAT") result = png -proc postProcessScanLines[T](png: PNG; header: PNGHeader, w, h: int; input, output: var openArray[T]) = +proc postProcessScanLines[T, A, B](png: PNG[T]; header: PNGHeader, w, h: int; input: var openArray[A], + output: var openArray[B]) = # This function converts the filtered-padded-interlaced data # into pure 2D image buffer with the PNG's colorType. # Steps: @@ -993,25 +1008,25 @@ proc postProcessScanLines[T](png: PNG; header: PNGHeader, w, h: int; input, outp adam7Deinterlace(output, input, w, h, bpp) -proc postProcessScanLines(png: PNG) = +proc postProcessScanLines[T](png: PNG[T]) = var header = PNGHeader(png.getChunk(IHDR)) let w = header.width let h = header.height var idat = PNGData(png.getChunk(IDAT)) - png.pixels = newString(idatRawSize(header.width, header.height, header)) + png.pixels = newStorage[T](idatRawSize(header.width, header.height, header)) png.postProcessScanLines(header, w, h, idat.idat.toOpenArray(0, idat.idat.len-1), # input png.pixels.toOpenArray(0, png.pixels.len-1) # output ) -proc postProcessScanLines(png: PNG, ctl: APNGFrameControl, data: var string) = +proc postProcessScanLines[T](png: PNG[T], ctl: APNGFrameControl, data: var string) = # we use var string here to avoid realloc # coz we use the input as output too var header = PNGHeader(png.getChunk(IHDR)) let w = ctl.width let h = ctl.height - png.apngPixels.add newString(idatRawSize(ctl.width, ctl.height, header)) + png.apngPixels.add newStorage[T](idatRawSize(ctl.width, ctl.height, header)) png.postProcessScanLines(header, w, h, data.toOpenArray(0, data.len-1), # input @@ -1112,9 +1127,9 @@ proc RGBFromRGB16[T](output: var openArray[T], input: openArray[T], numPixels: i for i in 0..= mode.paletteSize: # This is an error according to the PNG spec, but most PNG decoders make it black instead. # Done here too, slightly faster due to no error handling needed. - output[x] = chr(0) - output[x+1] = chr(0) - output[x+2] = chr(0) + output[x] = T(0) + output[x+1] = T(0) + output[x+2] = T(0) else: - output[x] = mode.palette[index].r - output[x+1] = mode.palette[index].g - output[x+2] = mode.palette[index].b + output[x] = T(mode.palette[index].r) + output[x+1] = T(mode.palette[index].g) + output[x+2] = T(mode.palette[index].b) proc RGBFromPalette124[T](output: var openArray[T], input: openArray[T], numPixels: int, mode: PNGColorMode) = var obp = 0 @@ -1139,13 +1154,13 @@ proc RGBFromPalette124[T](output: var openArray[T], input: openArray[T], numPixe if index >= mode.paletteSize: # This is an error according to the PNG spec, but most PNG decoders make it black instead. # Done here too, slightly faster due to no error handling needed. - output[x] = chr(0) - output[x+1] = chr(0) - output[x+2] = chr(0) + output[x] = T(0) + output[x+1] = T(0) + output[x+2] = T(0) else: - output[x] = mode.palette[index].r - output[x+1] = mode.palette[index].g - output[x+2] = mode.palette[index].b + output[x] = T(mode.palette[index].r) + output[x+1] = T(mode.palette[index].g) + output[x+2] = T(mode.palette[index].b) proc RGBFromGreyAlpha8[T](output: var openArray[T], input: openArray[T], numPixels: int, mode: PNGColorMode) = for i in 0..= mode.paletteSize: # This is an error according to the PNG spec, but most PNG decoders make it black instead. # Done here too, slightly faster due to no error handling needed. - output[x] = chr(0) - output[x+1] = chr(0) - output[x+2] = chr(0) - output[x+3] = chr(0) + output[x] = T(0) + output[x+1] = T(0) + output[x+2] = T(0) + output[x+3] = T(0) else: - output[x] = mode.palette[index].r - output[x+1] = mode.palette[index].g - output[x+2] = mode.palette[index].b - output[x+3] = mode.palette[index].a + output[x] = T(mode.palette[index].r) + output[x+1] = T(mode.palette[index].g) + output[x+2] = T(mode.palette[index].b) + output[x+3] = T(mode.palette[index].a) proc RGBAFromPalette124[T](output: var openArray[T], input: openArray[T], numPixels: int, mode: PNGColorMode) = var obp = 0 @@ -1262,15 +1277,15 @@ proc RGBAFromPalette124[T](output: var openArray[T], input: openArray[T], numPix if index >= mode.paletteSize: # This is an error according to the PNG spec, but most PNG decoders make it black instead. # Done here too, slightly faster due to no error handling needed. - output[x] = chr(0) - output[x+1] = chr(0) - output[x+2] = chr(0) - output[x+3] = chr(0) + output[x] = T(0) + output[x+1] = T(0) + output[x+2] = T(0) + output[x+3] = T(0) else: - output[x] = mode.palette[index].r - output[x+1] = mode.palette[index].g - output[x+2] = mode.palette[index].b - output[x+3] = mode.palette[index].a + output[x] = T(mode.palette[index].r) + output[x+1] = T(mode.palette[index].g) + output[x+2] = T(mode.palette[index].b) + output[x+3] = T(mode.palette[index].a) proc RGBAFromGreyAlpha8[T](output: var openArray[T], input: openArray[T], numPixels: int, mode: PNGColorMode) = for i in 0..