summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Pässler <milan@petabyte.dev>2021-03-13 11:35:46 +0100
committerMilan Pässler <milan@petabyte.dev>2021-03-13 11:35:46 +0100
commit5637b7d5aaccda626b7b274bfb72a69324bb4720 (patch)
treeeff90fad11d79a0b7dec73316dd94e18dec62640
parent0d87f77c176d9b73346c865972704a1addfe74ed (diff)
downloadnimjpg-5637b7d5aaccda626b7b274bfb72a69324bb4720.tar.gz
nimjpg-5637b7d5aaccda626b7b274bfb72a69324bb4720.tar.bz2
nimjpg-5637b7d5aaccda626b7b274bfb72a69324bb4720.zip
jpg: pass exif data to libexif
-rw-r--r--exif.nim11
-rw-r--r--jpg.nim95
2 files changed, 97 insertions, 9 deletions
diff --git a/exif.nim b/exif.nim
index cbc4eaf..09bba88 100644
--- a/exif.nim
+++ b/exif.nim
@@ -2,7 +2,6 @@ import asyncdispatch
import libexif
import tables
-var ed {.threadvar.}: ptr ExifData
var buf {.threadvar.}: cstring
# MUST be called once per thread
@@ -12,14 +11,8 @@ proc init_exif*() =
proc deinit_exif*() =
dealloc(buf)
-proc collect_exif*(path: string): Future[Table[string, string]] {.gcsafe,async.} =
- result = initTable[string, string]()
-
- ed = exif_data_new_from_file(path)
-
- if ed == nil:
- # ERROR
- quit(0)
+proc collect_exif*(ed: ptr ExifData): Table[string, string] {.gcsafe.} =
+ #result = initTable[string, string]()
proc process_entries(entry: ptr ExifEntry , callback_data: pointer) {.cdecl.} =
let name = exif_tag_get_name(entry.tag)
diff --git a/jpg.nim b/jpg.nim
new file mode 100644
index 0000000..81be222
--- /dev/null
+++ b/jpg.nim
@@ -0,0 +1,95 @@
+import os
+import strutils
+import asyncfile
+import asyncdispatch
+import libexif
+import exif
+import tables
+import parseutils
+
+var buf {.threadvar.}: pointer
+
+# MUST be called once per thread
+proc init_jpg*() =
+ init_exif()
+ buf = alloc(65536)
+
+proc deinit_jpg*() =
+ deinit_exif()
+ dealloc(buf)
+
+const
+ MARKER_START = parseHexStr("FF")
+
+ # 0xCn SOFn
+
+ SOS = parseHexStr("DA") # Start Of Scan (begins compressed data)
+ SOI = parseHexStr("D8") # Start Of Image (beginning of datastream)
+ EOI = parseHexStr("D9") # End Of Image (end of datastream)
+
+ EXIF = parseHexStr("E1")
+ JFIF = parseHexStr("E0")
+
+type JpgInfo* = object
+ exifInfo*: Table[string, string]
+ resolution*: tuple[x: int, y: int]
+
+proc getSectionSize(file: AsyncFile): Future[uint16] {.async.} =
+ # FIXME consider endianness
+ var size: uint16
+ let val = toHex(file.read(2).await)
+ discard parseHex(val, size)
+ return size - uint16(2)
+
+proc skipSection(file: AsyncFile): Future[void] {.async.} =
+ let size = int64(file.getSectionSize().await)
+ echo("skipping ", size)
+ file.setFilePos(file.getFilePos() + size)
+
+proc expect(file: AsyncFile, expected: string): Future[void] {.async.} =
+ let byte = file.read(1).await
+ if byte != expected:
+ echo("expected ", toHex(expected),", got ", toHex(byte))
+ quit(1)
+
+proc collect_jpg*(file: AsyncFile): Future[JpgInfo] {.gcsafe,async.} =
+ var done = false
+ var byte: string
+
+ file.expect(MARKER_START).await
+ file.expect(SOI).await
+
+ while not done:
+ file.expect(MARKER_START).await
+
+ let marker = file.read(1).await
+
+ case marker:
+ of "":
+ echo("unexpected end of file")
+ quit(1)
+ of SOS:
+ # Beginning of compressed data
+ done = true
+ of EOI:
+ # No compressed data? Okay...
+ done = true
+ of EXIF:
+ echo "found EXIF"
+ let size = int(file.getSectionSize().await)
+ discard file.readBuffer(buf, size).await
+ let ed = exif_data_new_from_data(cast[ptr[cuchar]](buf), cuint(size))
+ echo ed.collect_exif()
+ of JFIF:
+ echo "found JFIF"
+ file.skipSection().await
+ else:
+ if toHex(marker).startsWith("C"):
+ echo "found SOF"
+ file.skipSection().await
+ continue
+
+ echo("unknown section: ", toHex(marker))
+ file.skipSection().await
+
+ return JpgInfo(exifInfo: initTable[string, string](), resolution: (0, 0))