Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@stathissideris
Created February 4, 2014 10:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stathissideris/8801295 to your computer and use it in GitHub Desktop.
Save stathissideris/8801295 to your computer and use it in GitHub Desktop.
(ns binary.core
(:require [org.clojars.smee.binary.core :as b]
[clojure.java.io :as io]
[clojure.core.match :as m])
(:import org.clojars.smee.binary.core.BinaryIO
java.io.DataInput))
(defn fixed-string [len]
(b/string "ISO-8859-1" :length len))
(defn bytes [len]
(b/repeated :byte :length len))
(defn skip [len]
(reify org.clojars.smee.binary.core.BinaryIO
(read-data [_ big-in little-in]
(.skipBytes ^DataInput big-in len) :skipped)
(write-data [_ big-out little-out script])))
(defn select-codec [decision-codec selector-fn]
(reify org.clojars.smee.binary.core.BinaryIO
(read-data [_ big-in little-in]
(let [decision-value (b/read-data decision-codec big-in little-in)
codec (selector-fn decision-value)]
(merge decision-value
(b/read-data codec big-in little-in))))
(write-data [_ big-out little-out script])))
;;;;;
(def header
(b/ordered-map
:magic-number (bytes 8)))
(def chunk-header
(b/ordered-map
:length :int-be
:type (fixed-string 4)))
(defn chunk-codec [& main]
(apply b/ordered-map (concat main [:crc (bytes 4)])))
(defn generic-chunk [len]
(b/ordered-map
:data (bytes len)
:crc (bytes 4)))
(def select-chunk-codec
(select-codec
chunk-header
(fn [{:keys [length] :as header}]
(m/match header
{:type "IHDR"}
(chunk-codec
:width :int-be
:height :int-be
:bit-depth :byte
:color-type :byte
:compression-method :byte
:filter-method :byte
:interlace-method :byte)
{:type "pHYs"}
(chunk-codec
:x-pixels-per-unit :int-be
:y-pixels-per-unit :int-be
:unit :byte)
{:type "bKGD" :length 1}
(chunk-codec :index :byte)
{:type "bKGD" :length 2}
(chunk-codec :gray :short-be)
{:type "bKGD" :length 6}
(chunk-codec :red :short-be
:green :short-be
:blue :short-be)
{:type "gAMA"}
(chunk-codec :gamma :int-be)
{:type "IDAT"}
(chunk-codec
:data (skip length))
{:type "tEXt"}
(chunk-codec
:data (fixed-string length))
:else (generic-chunk length)))))
(def png-file
(b/ordered-map
:header header
:chunks (b/repeated select-chunk-codec)))
(defn decode-png [filename]
(let [in (io/input-stream filename)]
(b/decode png-file in)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment