From 6f50064fa0690ec591da9b91d156d0a4d377c172 Mon Sep 17 00:00:00 2001 From: Masaya Tojo Date: Sun, 4 Aug 2024 02:11:09 +0900 Subject: Support writing plain PNM formats --- pnm/write.scm | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 93 insertions(+), 15 deletions(-) (limited to 'pnm/write.scm') diff --git a/pnm/write.scm b/pnm/write.scm index 75cd433..849e3de 100644 --- a/pnm/write.scm +++ b/pnm/write.scm @@ -19,27 +19,105 @@ (define-library (pnm write) (export image-write) (import (scheme base) + (scheme case-lambda) (pnm image)) (begin - (define (image-write image out) - (define (write-string-u8 str) - (string-for-each (lambda (c) (write-u8 (char->integer c) out)) - str)) + (define image-write + (case-lambda + ((image out) + (case (image-type image) + ((ppm) + (write-string-u8 "P6\n" out)) + ((pgm) + (write-string-u8 "P5\n" out)) + ((pbm) + (write-string-u8 "P4\n" out)) + (else + (error "(pnm write) image-write: Not supported type" (image-type image)))) + (write-string-u8 (number->string (image-width image)) out) + (write-string-u8 " " out) + (write-string-u8 (number->string (image-height image)) out) + (write-string-u8 "\n" out) + (case (image-type image) + ((pgm ppm) + (write-string-u8 (number->string (image-maxval image)) out) + (write-string-u8 "\n" out))) + (write-bytevector (image-data image) out)) + ((image out plain?) + (if plain? + (image-write/plan image out) + (image-write image out))))) + + (define (image-write/plan image out) (case (image-type image) ((ppm) - (write-string-u8 "P6\n")) + (write-string-u8 "P3\n" out)) ((pgm) - (write-string-u8 "P5\n")) + (write-string-u8 "P2\n" out)) ((pbm) - (write-string-u8 "P4\n")) + (write-string-u8 "P1\n" out)) (else - (error "(pnm write) pnm-write: Not supported type" (image-type image)))) - (write-string-u8 (number->string (image-width image))) - (write-string-u8 "\n") - (write-string-u8 (number->string (image-height image))) - (write-string-u8 "\n") + (error "(pnm write) image-write: Not supported type" (image-type image)))) + (write-string-u8 (number->string (image-width image)) out) + (write-string-u8 " " out) + (write-string-u8 (number->string (image-height image)) out) + (write-string-u8 "\n" out) (case (image-type image) ((pgm ppm) - (write-string-u8 (number->string (image-maxval image))) - (write-string-u8 "\n"))) - (write-bytevector (image-data image) out)))) + (write-string-u8 (number->string (image-maxval image)) out) + (write-string-u8 "\n" out))) + (let-values (((write-token write-newline) + (limit-line-length-writer 70 out))) + (let ((width (image-width image)) + (height (image-height image))) + (define (write-raster write-pixel) + (do ((y 0 (+ y 1))) + ((= y height)) + (write-pixel 0 y) + (do ((x 1 (+ x 1))) + ((= x width)) + (write-pixel x y)) + (write-newline))) + (case (image-type image) + ((ppm) + (write-raster + (lambda (x y) + (let-values (((r g b) (image-ref image x y))) + (write-token (number->string r)) + (write-token (number->string g)) + (write-token (number->string b)))))) + ((pgm) + (write-raster + (lambda (x y) + (let ((v (image-ref image x y))) + (write-token (number->string v)))))) + ((pbm) + (write-raster + (lambda (x y) + (let ((b (image-ref image x y))) + (write-token (if b "1" "0")))))))))) + + (define (write-string-u8 str out) + (string-for-each (lambda (c) (write-u8 (char->integer c) out)) + str)) + + (define (limit-line-length-writer limit out) + (let ((current-length 0)) + (define (write-token str) + (let ((str-len (string-length str))) + (cond ((zero? current-length) + (write-string-u8 str out) + (set! current-length str-len)) + ((<= (+ current-length str-len 1) limit) + (write-string-u8 " " out) + (write-string-u8 str out) + (set! current-length (+ current-length 1 str-len))) + (else + (write-string-u8 "\n" out) + (write-string-u8 str out) + (set! current-length str-len))))) + (define (write-newline) + (write-string-u8 "\n" out) + (set! current-length 0)) + (values write-token + write-newline))))) -- cgit v1.2.3