File: pbmfile.l

package info (click to toggle)
euslisp 9.31%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 55,448 kB
  • sloc: ansic: 41,610; lisp: 3,339; makefile: 286; sh: 238; asm: 138; python: 53
file content (247 lines) | stat: -rw-r--r-- 7,523 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; raw, PBM, PGM and PPM file I/O
;;; (c) 1992, Toshihiro Matsui, Electrotechnical Laboratory
;;; Oct/1992
;;; Dec/1992	accept streams in addition to files
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(unless (find-package "IMAGE")
	(make-package "IMAGE" :nicknames '("IMG" "IP")))
(in-package "IMAGE")

(export '(read-pnm-file read-pnm write-pgm write-ppm write-pnm write-pnm-file))

(defun read-raw-image (file &optional (x 256) (y x))
   "read a file of raw pixel data"
   (let ((image-vector (make-array (* x y) :element-type :byte)))
      (with-open-file (f file)
         (unix:uread (send f :infd) image-vector))
      image-vector))

(defun write-raw-image (file img)
   "write pixel data out to a file"
   (with-open-file (f file)
       (unix:write (send f :outfd) img))
   img)

;; PBM

(defun read-pbm-token (f eof)
   (prog (ch)
      read-again
      (while (member (setq ch (read-char f nil eof))
		'(#\space #\tab #\newline)))
      (unread-char ch f)
      (cond ((eql ch eof) (return eof))
	    ((eql ch #\#) (read-line f) (go read-again))
	    (t (return  (read f))))))

(defun read-ascii-pbm (f img width height)
   (error "undefined read-ascii-pbm"))
(defun read-binary-pbm (f img width height)
   (error "undefined read-binary-pbm"))

;;
;; pgm
(defun write-pgm (f image  &optional (depth 255)
			(width (send image :width))
			(height (send image :height)))
   "write-pgm always uses binary format"
   (format f "P5 ~d ~d ~d~%" width height depth)
   (unix:write (send f :outfd) (array-entity image)))

;;
;;
(defun read-ascii-pgm (f img width height)
     (let* ((eof (cons nil nil))    (token)
	    (maxval (read-pbm-token f eof))
	    (size (* width height))   )
	(if (/= maxval 255)
	    (error "unknown pgm file format maxval=~A" maxval))
	(dotimes (i size)
	   (setq token  (read-pbm-token f eof))
	   (if (eql token eof) (error "unexpected EOF"))
	   (setf (char img i) token))
	(setq img (instance grayscale-image :init width height img))
	(send img :name (send f :fname))
	img   ) )

(defun read-binary-pgm (f img width height)
   (let* ((img1) (offset)
	  (size (* width height)) (read-length)
	  (eof (cons nil nil))
	  (maxval (read-pbm-token f eof))   )
	(if (/= maxval 255)
	    (error "unknown pgm file format maxval=~A" maxval))
	(setq img (make-string size))
	(read-char f)
	(replace img (setq img1 (send (send f :instream) :tail-string)))
	(send (send f :instream) :discard)
	(setq offset (length img1))
	(while (< offset size)
	   (setq read-length
		(unix:uread (send f :infd) img 
			(- size offset)
			offset))
	   (if (<= read-length 0) (error "EOF hit while reading pgm file"))
	   (incf offset read-length)
	   ; (print offset)
	   )
	(setq img (instance grayscale-image :init width height img))
	(send img :name (send f :fname))
	img   
	))

;; ppm 

(defun read-binary-ppm (f rgb width height)
   (let* ((size (* width height))
	  (eof (cons nil nil))
	  (maxval (read-pbm-token f eof))
	  img sbuf
	  offset (buflen (* size 3))  rdlen)
	(if (/= maxval 255)
	    (error "unknown ppm file format maxval=~A" maxval))
	(read-char f)
	(replace rgb (setq sbuf (send (send f :instream) :tail-string)))
	(setq offset (length sbuf))
	(when (> (mod (length sbuf) 3) 0)
	    ;; align to 3byte boundary
	    (setq rdlen (- 3 (mod (length sbuf) 3)))
	    (unix:uread (send f :infd) rgb rdlen offset)
	    (incf offset rdlen)   )
	(while (> (setq rdlen (unix:uread (send f :infd) rgb (- buflen offset) offset)) 0)
	   (incf offset rdlen)  )
	(setq img (instance color-image24 :init	width height rgb))
	(send img :name (send f :fname))
	img   
	))

(defun read-ascii-ppm (f rgb width height)
     (let* (rgbimg (eof (cons nil nil))  (token)
	    (maxval (read-pbm-token f eof))
	    (size (* width height))  (ii) )
	(if (/= maxval 255)
	    (error "unknown ppm file format maxval=~A" maxval))
	(dotimes (i size)
	   (setq ii (* i 3))
	   ;; red
	   (setq token  (read-pbm-token f eof))
	   (if (eql token eof) (error "unexpected EOF"))
	   (setf (char rgb ii) token)
	   ;; green
           (setq token  (read-pbm-token f eof))
	   (if (eql token eof) (error "unexpected EOF"))
	   (setf (char rgb (1+ ii)) token)
	   ;; blue
	   (setq token  (read-pbm-token f eof))
	   (if (eql token eof) (error "unexpected EOF"))
	   (setf (char rgb (+ ii 2)) token))
	(setq rgbimg (instance color-image24 :init
			width height rgb))
	(send rgbimg :name (send f :fname))
	rgbimg   ) )

(defun write-ppm (f rgb-image)
   "write-ppm always uses binary (P6) format"
   (setq rgb-image (send rgb-image :to24))
   (format f "P6 ~d ~d ~d~%" (send rgb-image :width)
			(send rgb-image :height) 255)
   (unix:write (send f :outfd) (send rgb-image :entity))
   )

;; PNM

(defun read-pnm (f &optional buf0)
     (let ((ch (read-char f))
	   (width) (height)
	   (eof (cons nil nil))
	   (size)   )
	(unless (eql (char-upcase ch) #\P)
	   (error "not a p[bgp]m file") )
	(setq ch (read-char f))
	(setq width (read-pbm-token f eof)
	      height  (read-pbm-token f eof))
        (setq size (* width height))
	(if (or (> size (* 4096 4096)) (< size 0))
	    (error "image too big or negative"))
        (unless buf0
	  (case ch
	   ((#\1 #\4) (setq buf0 (make-string (/ (+ size 7) 8))))
	   ((#\2 #\5) (setq buf0 (make-string size)))
	   ((#\3 #\6) (setq buf0 (make-string (* size 3))))) )
	(case ch
	   (#\1 (read-ascii-pbm f buf0 width height))
	   (#\2 (read-ascii-pgm f buf0 width height))
	   (#\3 (read-ascii-ppm f buf0 width height))
	   (#\4 (read-binary-pbm f buf0 width height))
	   (#\5 (read-binary-pgm f buf0 width height))
	   (#\6 (read-binary-ppm f buf0 width height))
	   (t (error "unknown pbm magic number")))))

(defun read-pnm-file (file &optional buf)
   (with-open-file (f file)
       (read-pnm f buf)))


(defun write-pnm (f img)
   (cond((derivedp img color-image) (write-ppm f img)) 
	((derivedp img color-image) (write-ppm f img)) 
	((derivedp img multi-channel-image)  (write-ppm f img))
   	((derivedp img grayscale-image)  (write-pgm f img))
	)
  )

(defun write-pnm-file (file img)
   (with-open-file (f file :direction :output)   (write-pnm f img)))

;;; misc functions

#|
(defun raster32-to-ppm (rasfile ppmfile)
   (let ((header (make-string 32))
	 (width) (height) (length) rgb r g b size (j 0))
      (declare (integer j))
      (with-open-file (ras rasfile)
         (unix:uread (send ras :infd) header)
	 (setq width (sys:peek header 4 :integer)
	       height (sys:peek header 8 :integer)
	       length (sys:peek header 16 :integer)
	       size (* width height))
	 (setq rgb (make-string length))
	 (unix:uread (send ras :infd) rgb)
	 (setq r (make-string size)
	       g (make-string size)
	       b (make-string size))
	 (print size)
	 (dotimes (i size)
	    (setf (char r i) (aref rgb (incf j))
		  (char g i) (aref rgb (incf j))
		  (char b i) (aref rgb (incf j)))
	    (incf j))
	 (print "writing ppm")
         (write-ppm
		ppmfile
		(instance color-pixel-image :init width height
			r g b)))))

(defun swap-red-blue (cimg)
   (instance color-pixel-image :init
	(send cimg :width) (send cimg :height)
	(send cimg :blue) (send cimg :green) (send cimg :red)))

(defun swap-rb (file)
   (let ((img (read-pnm file)))
      (setq img (swap-red-blue img))
      (write-ppm file img)))

(defun read-halve-hls (file)
   (let ((img (read-pnm file)))
      (setq img (send img :halve))
      (send img :hls)
      (send img :display-hls)
      img))
|#

(provide :pbmfile "#(@)$Id$")