more jpg
This commit is contained in:
parent
641b2b79fa
commit
df0756941c
1 changed files with 36 additions and 19 deletions
|
@ -5,6 +5,14 @@ import flatty/binny, pixie/common, pixie/images
|
||||||
const
|
const
|
||||||
jpgStartOfImage* = [0xFF.uint8, 0xD8]
|
jpgStartOfImage* = [0xFF.uint8, 0xD8]
|
||||||
|
|
||||||
|
type
|
||||||
|
Component = object
|
||||||
|
id, samplingFactors, quantizationTable: uint8
|
||||||
|
|
||||||
|
Jpg = object
|
||||||
|
width, height: int
|
||||||
|
components: array[3, Component]
|
||||||
|
|
||||||
template failInvalid() =
|
template failInvalid() =
|
||||||
raise newException(PixieError, "Invalid JPG buffer, unable to load")
|
raise newException(PixieError, "Invalid JPG buffer, unable to load")
|
||||||
|
|
||||||
|
@ -21,7 +29,7 @@ proc readSegmentLen(data: seq[uint8], pos: int): int =
|
||||||
proc skipSegment(data: seq[uint8], pos: var int) {.inline.} =
|
proc skipSegment(data: seq[uint8], pos: var int) {.inline.} =
|
||||||
pos += readSegmentLen(data, pos)
|
pos += readSegmentLen(data, pos)
|
||||||
|
|
||||||
proc decodeSOF(data: seq[uint8], pos: var int) =
|
proc decodeSOF(jpg: var Jpg, data: seq[uint8], pos: var int) =
|
||||||
let segmentLen = readSegmentLen(data, pos)
|
let segmentLen = readSegmentLen(data, pos)
|
||||||
pos += 2
|
pos += 2
|
||||||
|
|
||||||
|
@ -36,21 +44,31 @@ proc decodeSOF(data: seq[uint8], pos: var int) =
|
||||||
|
|
||||||
pos += 6
|
pos += 6
|
||||||
|
|
||||||
|
if width <= 0:
|
||||||
|
raise newException(PixieError, "Invalid JPG width")
|
||||||
|
|
||||||
|
if height <= 0:
|
||||||
|
raise newException(PixieError, "Invalid JPG height")
|
||||||
|
|
||||||
if precision != 8:
|
if precision != 8:
|
||||||
raise newException(PixieError, "Unsupported JPG bit depth")
|
raise newException(PixieError, "Unsupported JPG bit depth")
|
||||||
|
|
||||||
if components != 3:
|
if components != 3:
|
||||||
raise newException(PixieError, "Unsupported JPG channel count")
|
raise newException(PixieError, "Unsupported JPG channel count")
|
||||||
|
|
||||||
debugEcho width, " x ", height
|
jpg.width = width
|
||||||
|
jpg.height = height
|
||||||
|
|
||||||
if 8 + components * 3 != segmentLen:
|
if 8 + components * 3 != segmentLen:
|
||||||
failInvalid()
|
failInvalid()
|
||||||
|
|
||||||
for i in 0 ..< 3:
|
for i in 0 ..< 3:
|
||||||
discard
|
jpg.components[i] = Component(
|
||||||
|
id: data[pos],
|
||||||
pos += components * 3
|
samplingFactors: data[pos + 1],
|
||||||
|
quantizationTable: data[pos + 2]
|
||||||
|
)
|
||||||
|
pos += 3
|
||||||
|
|
||||||
proc decodeDHT(data: seq[uint8], pos: var int) =
|
proc decodeDHT(data: seq[uint8], pos: var int) =
|
||||||
skipSegment(data, pos)
|
skipSegment(data, pos)
|
||||||
|
@ -58,9 +76,6 @@ proc decodeDHT(data: seq[uint8], pos: var int) =
|
||||||
proc decodeDQT(data: seq[uint8], pos: var int) =
|
proc decodeDQT(data: seq[uint8], pos: var int) =
|
||||||
skipSegment(data, pos)
|
skipSegment(data, pos)
|
||||||
|
|
||||||
proc decodeDRI(data: seq[uint8], pos: var int) =
|
|
||||||
skipSegment(data, pos)
|
|
||||||
|
|
||||||
proc decodeSOS(data: seq[uint8], pos: var int) =
|
proc decodeSOS(data: seq[uint8], pos: var int) =
|
||||||
let segmentLen = readSegmentLen(data, pos)
|
let segmentLen = readSegmentLen(data, pos)
|
||||||
pos += 2
|
pos += 2
|
||||||
|
@ -83,16 +98,17 @@ proc decodeSOS(data: seq[uint8], pos: var int) =
|
||||||
failInvalid()
|
failInvalid()
|
||||||
|
|
||||||
if data[pos] == 0xFF:
|
if data[pos] == 0xFF:
|
||||||
inc pos
|
if pos + 1 == data.len:
|
||||||
if pos == data.len:
|
|
||||||
failInvalid()
|
failInvalid()
|
||||||
if data[pos] == 0xD9: # End of Image:
|
if data[pos + 1] == 0xD9: # End of Image:
|
||||||
inc pos
|
pos += 2
|
||||||
break
|
break
|
||||||
elif data[pos] == 0x00:
|
elif data[pos + 1] == 0x00:
|
||||||
discard # Skip this byte
|
discard # Skip the 0x00 byte
|
||||||
else:
|
else:
|
||||||
failInvalid()
|
failInvalid()
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
inc pos
|
inc pos
|
||||||
|
|
||||||
|
@ -105,7 +121,9 @@ proc decodeJpg*(data: seq[uint8]): Image =
|
||||||
if data.readUint16(0) != cast[uint16](jpgStartOfImage):
|
if data.readUint16(0) != cast[uint16](jpgStartOfImage):
|
||||||
failInvalid()
|
failInvalid()
|
||||||
|
|
||||||
var pos: int
|
var
|
||||||
|
jpg: Jpg
|
||||||
|
pos: int
|
||||||
while true:
|
while true:
|
||||||
if pos + 2 > data.len:
|
if pos + 2 > data.len:
|
||||||
failInvalid()
|
failInvalid()
|
||||||
|
@ -120,15 +138,14 @@ proc decodeJpg*(data: seq[uint8]): Image =
|
||||||
of 0xD8: # Start of Image
|
of 0xD8: # Start of Image
|
||||||
discard
|
discard
|
||||||
of 0xC0: # Start of Frame
|
of 0xC0: # Start of Frame
|
||||||
decodeSOF(data, pos)
|
jpg.decodeSOF(data, pos)
|
||||||
of 0xC2: # Start of Frame
|
of 0xC2: # Start of Frame
|
||||||
raise newException(PixieError, "Progressive JPG not supported")
|
raise newException(PixieError, "Progressive JPG not supported")
|
||||||
of 0xC4: # Define Huffman Tables
|
of 0xC4: # Define Huffman Tables
|
||||||
decodeDHT(data, pos)
|
decodeDHT(data, pos)
|
||||||
of 0xDB: # Define Quantanization Table(s)
|
of 0xDB: # Define Quantanization Table(s)
|
||||||
decodeDQT(data, pos)
|
decodeDQT(data, pos)
|
||||||
of 0xDD: # Define Restart Interval
|
# of 0xDD: # Define Restart Interval
|
||||||
decodeDRI(data, pos)
|
|
||||||
of 0xDA: # Start of Scan
|
of 0xDA: # Start of Scan
|
||||||
decodeSOS(data, pos)
|
decodeSOS(data, pos)
|
||||||
break
|
break
|
||||||
|
@ -141,7 +158,7 @@ proc decodeJpg*(data: seq[uint8]): Image =
|
||||||
# Skip APPn segments
|
# Skip APPn segments
|
||||||
skipSegment(data, pos)
|
skipSegment(data, pos)
|
||||||
else:
|
else:
|
||||||
raise newException(PixieError, "Unsupported JPG segemnt")
|
raise newException(PixieError, "Unsupported JPG segment")
|
||||||
|
|
||||||
raise newException(PixieError, "Decoding JPG not supported yet")
|
raise newException(PixieError, "Decoding JPG not supported yet")
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue