X-Git-Url: https://thelambdalab.xyz/gitweb/index.cgi?a=blobdiff_plain;f=sixel.el;h=f2532e56ba5796b28935e8b9f120c5ed4ff06f1f;hb=6b9058e99e890e33246c6e4e3cad2d4dc81dd951;hp=cd7fd316d81203339e5c0d9ed5f8b6ebab428e37;hpb=c4291595d24b1ca19db14a675268cd87d168983b;p=sixel.git diff --git a/sixel.el b/sixel.el index cd7fd31..f2532e5 100644 --- a/sixel.el +++ b/sixel.el @@ -1,3 +1,18 @@ +;;; sixel.el --- minor mode for processing sixel graphics + +;; Copyright (C) 2019 Tim Vaughan + +;; Author: Tim Vaughan +;; Created: 19 May 2019 +;; Version: 1.0.0 +;; Keywords: +;; Homepage: https://github.com/tgvaughan/sixel +;; Package-Requires: ((emacs "25")) + +;;; Commentary: + +;;; Code: + (defvar test-string (concat "q" "#0;2;0;0;0#1;2;100;100;0#2;2;0;100;0" @@ -5,7 +20,6 @@ "#2??GG????-" "#1!14@")) - (defun sixel-get-params (string) "Retrieve the sixel parameters." (car (split-string string "q"))) @@ -14,22 +28,6 @@ "Retrieve data string." (substring string (1+ (string-match "q" string)))) -(defvar sixel-colour-map nil - "Map of two-character names to RGB colour triples.") - -(defvar sixel-current-colour nil - "Current colour.") - -(defun sixel-compute-row-length (string) - (apply 'max - (mapcar - (lambda (substr) - (apply 'max (mapcar - (lambda (subsubstr) - (length (subsubstr))) - (split-string substr "$")))) - (split-string string -)))) - (defun sixel-tag-bits (sixel n tag) "Set bits of SIXEL corresponding to N with to the value TAG." (dotimes (i 6) @@ -37,54 +35,122 @@ (aset sixel i tag)) (setq n (/ n 2)))) -(defun sixel-tag-sixel-in-row (row-variable index char tag) +(defun sixel-tag-sixel-in-row (row index char tag) "Tag the bits of the sixel at INDEX in the list identified by the variable ROW-VARIABLE corresponding to input character CHAR with TAG." - (while (not (< index (length (symbol-value row-variable)))) - (add-to-list row-variable (make-vector 6 nil))) - (let ((sixel (elt (symbol-value row-variable) index))) - (sixel-tag-bits sixel (- char 63) tag))) - -(defun sixel-process-row (string) - (let ((idx-in 0) - (idx-out 0) - result) - (while (< idx-in (length string)) - (let (trunc-string (substring string index-in)) + (while (not (< index (length row))) + (push (make-vector 6 nil) row)) + (let ((sixel (elt row (- (length row) 1 index)))) + (sixel-tag-bits sixel (- char 63) tag)) + row) + +(defun sixel-process-data (string) + "Convert STRING into a list of lists representing individual sixels. +Returns a sixel image object." + (with-temp-buffer + (insert string) + (goto-char (point-min)) + (let ((idx-out 0) + this-row rows + current-colour colour-map + finished) + (while (not finished) (cond - ((string-match "^#\\([0-9]+\\);\\([0-9]+\\);\\([0-9]+\\);\\([0-9]+\\);\\([0-9]+\\)" - trunc-string) - (let ((tag (intern (string-to (match-string 1 trunc-string)))) - (mode (match-string 2 trunc-string)) - (r (string-to-number (match-string 3 trunc-string))) - (g (string-to-number (match-string 4 trunc-string))) - (b (string-to-number (match-string 5 trunc-string)))) - (add-to-list 'sixel-colour-map (list (tag r g b))) - (setq idx-in (match-end 0)))) - ((string-match "^#\\([0-9]+\\)" trunc-string) - (let ((tag (intern (match-string 1 trunc-string)))) - (setq sixel-current-colour tag) - (setq idx-in (match-end 0)))) - ((string-match "^$" trunc-string) - (setq idx-out 0) - (setq idx-in (match-end 0 trunc-string))) - ((string-match "^!\\([0-9]+\\)\\([?-~]\\)" trunc-string) - (let ((repeat-count (string-to-number (match-string 1 trunc-string))) - (char (elt (match-string 2 trunc-string) 0))) + ((looking-at "#\\([0-9]+\\);\\([0-9]+\\);\\([0-9]+\\);\\([0-9]+\\);\\([0-9]+\\)") + (let ((tag (format "%02x" (string-to-number (match-string 1)))) + (mode (match-string 2)) + (r (string-to-number (match-string 3))) + (g (string-to-number (match-string 4))) + (b (string-to-number (match-string 5)))) + (push (list tag r g b) colour-map))) + + ((looking-at "#\\([0-9]+\\)") + (let ((tag (format "%02x" (string-to-number (match-string 1))))) + (setq current-colour tag))) + + ((looking-at "\\$") + (setq idx-out 0)) + + ((looking-at "-") + (push (reverse this-row) rows) + (setq this-row nil) + (setq idx-out 0)) + + ((looking-at "!\\([0-9]+\\)\\([?-~]\\)") + (let ((repeat-count (string-to-number (match-string 1))) + (char (elt (match-string 2) 0))) (dotimes (i repeat-count) - (sixel-tag-sixel-in-row 'result idx-out char sixel-current-colour) - (setq idx-out (+1 idx-out))))) - ((string-match "^\\([?-~]\\)" trunc-string) - (let ((char (elt (match-string 1 trunc-string) 0))) - (sixel-tag-sixel-in-row 'result idx-out char sixel-current-colour)) - (setq idx-out (+1 idx-out)))))))) - -(sixel-get-rows test-string) + (setq this-row + (sixel-tag-sixel-in-row this-row idx-out char current-colour)) + (setq idx-out (1+ idx-out))))) + + ((looking-at "\\([?-~]\\)") + (let ((char (elt (match-string 1) 0))) + (setq this-row + (sixel-tag-sixel-in-row this-row idx-out char current-colour)) + (setq idx-out (1+ idx-out)))) + + (t (setq finished t))) + + (goto-char (match-end 0))) + (push (reverse this-row) rows) + (cons colour-map + (reverse rows))))) + +(defun sixel-image-colour-map (sixel-image) + "Extract colour map from SIXEL-DATA." + (car sixel-image)) + +(defun sixel-image-sixels (sixel-image) + "Extract sixels from SIXEL-DATA." + (cdr sixel-image)) + +(defun sixel-image-dims (sixel-image) + "Computes image width from SIXEL-DATA. Returns pair (width . height)." + (let ((sixels (sixel-image-sixels sixel-image))) + (cons + (apply #'max (mapcar (lambda (row) (length row)) sixels)) + (length sixels)))) + +(defun sixel-image-to-xpm-values (sixel-image) + (let* ((dims (sixel-image-dims sixel-image)) + (colour-map (sixel-image-colour-map sixel-image)) + (n-colours (length colour-map))) + (concat "\"" + (number-to-string (car dims)) " " + (number-to-string (cdr dims)) " " + (number-to-string n-colours) " 2\""))) + +(defun sixel-image-to-xpm-colours (sixel-image) + (let ((colour-map (sixel-image-colour-map sixel-image))) + (string-join + (mapcar (lambda (colour) + (concat + "\"" + (elt colour 0) " " + "c #" + (format "%02x%02x%02x" + (elt colour 1) + (elt colour 2) + (elt colour 3)) + "\"")) + colour-map) + ","))) (defun sixel-to-xpm (string) - "Converts the given sixel string into an XPM image." + "Returns an XPM image representation of the SIXEL graphic encoded in STRING." + (let* ((param-string (sixel-get-params string)) + (data-string (sixel-get-data string)) + (sixel-image (sixel-process-data data-string))) + (concat + "/* XPM */" + "static char * pixmap = {" + (sixel-image-to-xpm-values sixel-image) ",\n" + (sixel-image-to-xpm-colours sixel-image) + ;; (sixel-data-to-XPM-pixels data) + "};"))) + + - (let* ((sp (split-string string "q")) - (control-string (car sp)) - ()))) +;; sixel.el ends here