;; This is an (almost) direct translation of C source found at: ;; http://dev.w3.org/cvsweb/Amaya/libjpeg/rdjpgcom.c?rev=1.2 ;; The following code assumes that read-char function returns ;; one unsigned byte (not signed byte, not unicode character) (context 'jpeg-dimensions) (define (return x) x) (define (read_1_byte , c) (setq c (read-char handle)) (unless c (throw "read_1_byte: EOF")) (return c)) (define (read_2_bytes , c1 c2) (setq c1 (read-char handle)) (unless c1 (throw "read_2_bytes: EOF")) (setq c2 (read-char handle)) (unless c2 (throw "read_2_bytes: EOF")) (return (+ (<< c1 8) c2))) (define (sof? byte) (and (= (& byte 0xF0) 0xC0) (not (member byte '(0xC4 0xC8 0xCC))))) (define (first_marker) (unless (= (read_2_bytes) 0xFFD8) (throw "first_marker: not a JPEG"))) (define (next_marker , c) (setq c (read_1_byte)) (unless (= c 0xFF) (throw "next_marker: garbage")) (while (= c 0xFF) (setq c (read_1_byte))) (return c)) (define (skip_variable , len) (setq len (read_2_bytes)) (unless (>= len 2) (throw "skip_variable: bad length")) (dotimes (i (- len 2)) (read_1_byte))) (define (process_sof marker , len precision height width components) (setq len (read_2_bytes)) (setq precision (read_1_byte)) (setq height (read_2_bytes)) (setq width (read_2_bytes)) (setq components (read_1_byte)) (unless (= len (+ 8 (* components 3))) (throw "process_sof: bogus length")) (return (list width height))) (define (scan_jpeg_header , marker) (catch (begin (first_marker) (while (setq marker (next_marker)) (if (sof? marker) (throw (process_sof marker)) (skip_variable))) (throw "scan_jpeg_header: no frames")))) (define (jpeg-dimensions:jpeg-dimensions file , handle result) (setq handle (open file "read")) (setq result (scan_jpeg_header)) (close handle) (return result)) (context MAIN) (println (jpeg-dimensions (main-args 2))) (exit)