diff --git a/src/pixie.nim b/src/pixie.nim index f4a1004..a3e4fe3 100644 --- a/src/pixie.nim +++ b/src/pixie.nim @@ -18,24 +18,36 @@ converter autoPremultipliedAlpha*(c: ColorRGBA): ColorRGBX {.inline, raises: []. ## Convert a straight alpha RGBA to a premultiplied alpha RGBA. c.rgbx() +proc decodeImageDimensions*( + data: pointer, len: int +): ImageDimensions {.raises: [PixieError].} = + ## Decodes an image's dimensions from memory. + if len > 8 and equalMem(data, pngSignature[0].unsafeAddr, 8): + decodePngDimensions(data, len) + elif len > 2 and equalMem(data, jpegStartOfImage[0].unsafeAddr, 2): + decodeJpegDimensions(data, len) + elif len > 2 and equalMem(data, bmpSignature.cstring, 2): + decodeBmpDimensions(data, len) + elif len > 6 and ( + equalMem(data, gifSignatures[0].cstring, 6) or + equalMem(data, gifSignatures[1].cstring, 6) + ): + decodeGifDimensions(data, len) + elif len > (14 + 8) and equalMem(data, qoiSignature.cstring, 4): + decodeQoiDimensions(data, len) + elif len > 9 and ( + equalMem(data, ppmSignatures[0].cstring, 2) or + equalMem(data, ppmSignatures[1].cstring, 2) + ): + decodePpmDimensions(data, len) + else: + raise newException(PixieError, "Unsupported image file format") + proc decodeImageDimensions*( data: string ): ImageDimensions {.raises: [PixieError].} = ## Decodes an image's dimensions from memory. - if data.len > 8 and data.readUint64(0) == cast[uint64](pngSignature): - decodePngDimensions(data) - elif data.len > 2 and data.readUint16(0) == cast[uint16](jpegStartOfImage): - decodeJpegDimensions(data) - elif data.len > 2 and data.readStr(0, 2) == bmpSignature: - decodeBmpDimensions(data) - elif data.len > 6 and data.readStr(0, 6) in gifSignatures: - decodeGifDimensions(data) - elif data.len > (14+8) and data.readStr(0, 4) == qoiSignature: - decodeQoiDimensions(data) - elif data.len > 9 and data.readStr(0, 2) in ppmSignatures: - decodePpmDimensions(data) - else: - raise newException(PixieError, "Unsupported image file format") + decodeImageDimensions(data.cstring, data.len) proc decodeImage*(data: string): Image {.raises: [PixieError].} = ## Loads an image from memory. diff --git a/src/pixie/fileformats/jpeg.nim b/src/pixie/fileformats/jpeg.nim index 60e7380..50c3301 100644 --- a/src/pixie/fileformats/jpeg.nim +++ b/src/pixie/fileformats/jpeg.nim @@ -24,7 +24,6 @@ import chroma, flatty/binny, ../common, ../images, ../internal, const fastBits = 9 - jpegStartOfImage* = [0xFF.uint8, 0xD8] deZigZag = [ uint8 00, 01, 08, 16, 09, 02, 03, 10, uint8 17, 24, 32, 25, 18, 11, 04, 05, @@ -40,6 +39,9 @@ const 1023, 2047, 4095, 8191, 16383, 32767, 65535 ] +let + jpegStartOfImage* = [0xFF.uint8, 0xD8] + type Huffman = object codes: array[256, uint16] @@ -1155,13 +1157,13 @@ proc decodeJpeg*(data: string): Image {.raises: [PixieError].} = state.buildImage() proc decodeJpegDimensions*( - data: string + data: pointer, len: int ): ImageDimensions {.raises: [PixieError].} = ## Decodes the JPEG dimensions. var state = DecoderState() - state.buffer = cast[ptr UncheckedArray[uint8]](data.cstring) - state.len = data.len + state.buffer = cast[ptr UncheckedArray[uint8]](data) + state.len = len while true: if state.readUint8() != 0xFF: @@ -1209,5 +1211,11 @@ proc decodeJpegDimensions*( else: failInvalid("invalid orientation") +proc decodeJpegDimensions*( + data: string +): ImageDimensions {.raises: [PixieError].} = + ## Decodes the JPEG dimensions. + decodeJpegDimensions(data.cstring, data.len) + when defined(release): {.pop.} diff --git a/src/pixie/fileformats/png.nim b/src/pixie/fileformats/png.nim index 228351b..a8ff15e 100644 --- a/src/pixie/fileformats/png.nim +++ b/src/pixie/fileformats/png.nim @@ -3,7 +3,7 @@ import chroma, flatty/binny, math, ../common, ../images, ../internal, # See http://www.libpng.org/pub/png/spec/1.2/PNG-Contents.html -const +let pngSignature* = [137.uint8, 80, 78, 71, 13, 10, 26, 10] type