ctucx.git: nimjpg

parse jpg file header

commit dac334837726ec9e8b7dc7aa666153119bb26989
parent 234c1fc04fef5848a205a7dea96bea29ba5d4e65
Author: Milan Pässler <milan@petabyte.dev>
Date: Sat, 13 Mar 2021 12:27:49 +0100

return sof and exif data
3 files changed, 34 insertions(+), 26 deletions(-)
M
example.nim
|
3
++-
M
exif.nim
|
2
+-
M
jpg.nim
|
55
+++++++++++++++++++++++++++++++------------------------
diff --git a/example.nim b/example.nim
@@ -2,6 +2,7 @@ import os
 import jpg
 import asyncdispatch
 import asyncfile
+import json
 
 var result: cint
 

@@ -15,7 +16,7 @@ init_jpg()
 
 if fileExists(path):
   let file = openAsync(path)
-  echo $(waitFor collect_jpg(file))
+  echo pretty(%* (waitFor collect_jpg(file)))
 else:
   echo "Gimme an existing file pls"
 
diff --git a/exif.nim b/exif.nim
@@ -10,7 +10,7 @@ proc init_exif*() =
 proc deinit_exif*() =
   dealloc(buf)
 
-proc collect_exif*(ed: ptr ExifData): Table[string, string] {.gcsafe.} =
+proc collect_exif_data*(ed: ptr ExifData): Table[string, string] {.gcsafe.} =
   #result = initTable[string, string]()
 
   proc process_entries(entry: ptr ExifEntry , callback_data: pointer) {.cdecl.} =
diff --git a/jpg.nim b/jpg.nim
@@ -6,6 +6,8 @@ import libexif
 import exif
 import tables
 import parseutils
+import options
+import utils
 
 var buf {.threadvar.}: pointer
 

@@ -30,9 +32,15 @@ const
   EXIF  = parseHexStr("E1")
   JFIF  = parseHexStr("E0")
 
+type SofData* = object
+  components*: uint8
+  precision*: uint8
+  height*: uint16
+  width*: uint16
+
 type JpgInfo* = object
-  exifInfo*: Table[string, string]
-  resolution*: tuple[x: int, y: int]
+  exifData*: Option[Table[string, string]]
+  sofData*: Option[SofData]
 
 proc getSectionSize(file: AsyncFile): Future[uint16] {.async.} =
   # FIXME consider endianness

@@ -43,14 +51,19 @@ proc getSectionSize(file: AsyncFile): Future[uint16] {.async.} =
 
 proc skipSection(file: AsyncFile): Future[void] {.async.} =
   let size = int64(file.getSectionSize().await)
-  echo("skipping ", size)
+  debug("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)
+    error("expected ", toHex(expected),", got ", toHex(byte))
+
+proc process_sof*(file: AsyncFile): Future[SofData] {.gcsafe,async.} =
+  discard parseHex(toHex(file.read(1).await), result.precision)
+  discard parseHex(toHex(file.read(2).await), result.height)
+  discard parseHex(toHex(file.read(2).await), result.width)
+  discard parseHex(toHex(file.read(1).await), result.components)
 
 proc collect_jpg*(file: AsyncFile): Future[JpgInfo] {.gcsafe,async.} =
   var done = false

@@ -66,8 +79,7 @@ proc collect_jpg*(file: AsyncFile): Future[JpgInfo] {.gcsafe,async.} =
 
     case marker:
     of "":
-      echo("unexpected end of file")
-      quit(1)
+      error("unexpected end of file")
     of SOS:
       # Beginning of compressed data
       done = true

@@ -75,33 +87,28 @@ proc collect_jpg*(file: AsyncFile): Future[JpgInfo] {.gcsafe,async.} =
       # No compressed data? Okay...
       done = true
     of EXIF:
-      echo "found EXIF"
+      debug "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()
+      let ed_table = ed.collect_exif_data()
+      if result.exifData.isNone:
+        result.exifData = some(ed_table)
+      debug ed_table
     of JFIF:
-      echo "found JFIF"
+      debug "found JFIF"
       file.skipSection().await
     else:
       if toHex(marker).startsWith("C"):
-        echo "found SOF"
+        debug "found SOF"
         let section_start = file.getFilePos() + 2
         let section_end = section_start + int64(file.getSectionSize().await)
-        var precision, components: uint8
-        var height, width: uint16
-        discard parseHex(toHex(file.read(1).await), precision)
-        echo("  precision ", precision)
-        discard parseHex(toHex(file.read(2).await), height)
-        echo("  height ", height)
-        discard parseHex(toHex(file.read(2).await), width)
-        echo("  width ", width)
-        discard parseHex(toHex(file.read(1).await), components)
-        echo("  components ", components)
+        let sd = file.process_sof().await
+        if result.sofData.isNone:
+          result.sofData = some(sd)
+        debug sd
         file.setFilePos(section_end)
         continue
 
-      echo("unknown section: ", toHex(marker))
+      debug("unknown section: ", toHex(marker))
       file.skipSection().await
-
-  return JpgInfo(exifInfo: initTable[string, string](), resolution: (0, 0))