safer exif decode
This commit is contained in:
parent
dc69535191
commit
4b7a9d1bb4
|
@ -380,15 +380,16 @@ proc decodeSOF2(state: var DecoderState) =
|
||||||
|
|
||||||
proc decodeExif(state: var DecoderState) =
|
proc decodeExif(state: var DecoderState) =
|
||||||
## Decode Exif header
|
## Decode Exif header
|
||||||
let
|
var len = state.readUint16be().int - 2
|
||||||
len = state.readUint16be().int - 2
|
|
||||||
endOffset = state.pos + len
|
|
||||||
|
|
||||||
let exifHeader = state.readStr(6)
|
let exifHeader = state.readStr(6)
|
||||||
|
|
||||||
|
len -= 6
|
||||||
|
|
||||||
if exifHeader != "Exif\0\0":
|
if exifHeader != "Exif\0\0":
|
||||||
# Happens with progressive images, just ignore instead of error.
|
# Happens with progressive images, just ignore instead of error.
|
||||||
# Skip to the end.
|
# Skip to the end.
|
||||||
state.pos = endOffset
|
state.skipBytes(len)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Read the endianess of the exif header
|
# Read the endianess of the exif header
|
||||||
|
@ -402,22 +403,40 @@ proc decodeExif(state: var DecoderState) =
|
||||||
else:
|
else:
|
||||||
failInvalid("invalid Tiff header")
|
failInvalid("invalid Tiff header")
|
||||||
|
|
||||||
|
len -= 2
|
||||||
|
|
||||||
# Verify we got the endianess right.
|
# Verify we got the endianess right.
|
||||||
if state.readUint16be().maybeSwap(littleEndian) != 0x002A.uint16:
|
if state.readUint16be().maybeSwap(littleEndian) != 0x002A.uint16:
|
||||||
failInvalid("invalid Tiff header endianess")
|
failInvalid("invalid Tiff header endianess")
|
||||||
|
|
||||||
|
len -= 2
|
||||||
|
|
||||||
# Skip any other tiff header data.
|
# Skip any other tiff header data.
|
||||||
let offsetToFirstIFD = state.readUint32be().maybeSwap(littleEndian).int
|
let offsetToFirstIFD = state.readUint32be().maybeSwap(littleEndian).int
|
||||||
|
|
||||||
|
len -= 4
|
||||||
|
|
||||||
|
if offsetToFirstIFD < 8:
|
||||||
|
failInvalid("invalid Tiff offset")
|
||||||
|
|
||||||
state.skipBytes(offsetToFirstIFD - 8)
|
state.skipBytes(offsetToFirstIFD - 8)
|
||||||
|
|
||||||
|
len -= (offsetToFirstIFD - 8)
|
||||||
|
|
||||||
# Read the IFD0 (main image) tags.
|
# Read the IFD0 (main image) tags.
|
||||||
let numTags = state.readUint16be().maybeSwap(littleEndian).int
|
let numTags = state.readUint16be().maybeSwap(littleEndian).int
|
||||||
|
|
||||||
|
len -= 2
|
||||||
|
|
||||||
for i in 0 ..< numTags:
|
for i in 0 ..< numTags:
|
||||||
let
|
let
|
||||||
tagNumber = state.readUint16be().maybeSwap(littleEndian)
|
tagNumber = state.readUint16be().maybeSwap(littleEndian)
|
||||||
dataFormat = state.readUint16be().maybeSwap(littleEndian)
|
dataFormat = state.readUint16be().maybeSwap(littleEndian)
|
||||||
numberComponents = state.readUint32be().maybeSwap(littleEndian)
|
numberComponents = state.readUint32be().maybeSwap(littleEndian)
|
||||||
dataOffset = state.readUint32be().maybeSwap(littleEndian).int
|
dataOffset = state.readUint32be().maybeSwap(littleEndian).int
|
||||||
|
|
||||||
|
len -= 12
|
||||||
|
|
||||||
# For now we only care about orientation tag.
|
# For now we only care about orientation tag.
|
||||||
case tagNumber:
|
case tagNumber:
|
||||||
of 0x0112: # Orientation
|
of 0x0112: # Orientation
|
||||||
|
@ -426,7 +445,7 @@ proc decodeExif(state: var DecoderState) =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
# Skip all of the data we do not want to read, IFD1, thumbnail, etc.
|
# Skip all of the data we do not want to read, IFD1, thumbnail, etc.
|
||||||
state.pos = endOffset
|
state.skipBytes(len) # Skip any remaining len
|
||||||
|
|
||||||
proc reset(state: var DecoderState) =
|
proc reset(state: var DecoderState) =
|
||||||
## Rests the decoder state need for restart markers.
|
## Rests the decoder state need for restart markers.
|
||||||
|
@ -1153,18 +1172,15 @@ proc decodeJpegDimensions*(
|
||||||
of 0xD8:
|
of 0xD8:
|
||||||
# SOI - Start of Image
|
# SOI - Start of Image
|
||||||
discard
|
discard
|
||||||
of 0xC0:
|
of 0xC0, 0xC2:
|
||||||
# Start Of Frame (Baseline DCT)
|
# Start Of Frame (Baseline DCT or Progressive DCT)
|
||||||
state.decodeSOF0()
|
discard state.readUint16be().int # Chunk len
|
||||||
|
discard state.readUint8() # Precision
|
||||||
|
state.imageHeight = state.readUint16be().int
|
||||||
|
state.imageWidth = state.readUint16be().int
|
||||||
break
|
break
|
||||||
of 0xC1:
|
of 0xC1:
|
||||||
# Start Of Frame (Extended sequential DCT)
|
failInvalid("unsupported extended sequential DCT format")
|
||||||
state.decodeSOF1()
|
|
||||||
break
|
|
||||||
of 0xC2:
|
|
||||||
# Start Of Frame (Progressive DCT)
|
|
||||||
state.decodeSOF2()
|
|
||||||
break
|
|
||||||
of 0xDB:
|
of 0xDB:
|
||||||
# Define Quantization Table(s)
|
# Define Quantization Table(s)
|
||||||
state.skipChunk()
|
state.skipChunk()
|
||||||
|
|
Loading…
Reference in a new issue