gray.scm 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. #!fold-case
  21. ;;;; Graphics with grey scales, from 6.001 picture code by Newts/Hal Abelson
  22. ;;;; Miscellaneous Utilities
  23. (define floating-vector-ref (make-primitive-procedure 'floating-vector-ref))
  24. (define floating-vector-set! (make-primitive-procedure 'floating-vector-set!))
  25. (define floating-vector-cons (make-primitive-procedure 'floating-vector-cons))
  26. (define floating-vector-length (make-primitive-procedure 'floating-vector-length))
  27. (define (make-floating-vector length init)
  28. (let ((result (floating-vector-cons length)))
  29. (if (not (= init 0.))
  30. (do ((i 0 (fix:+ i 1)))
  31. ((fix:= i length))
  32. (floating-vector-set! result i init)))
  33. result))
  34. (define (floating-vector-copy vector)
  35. (let* ((length (floating-vector-length vector))
  36. (result (floating-vector-cons length)))
  37. (do ((i 0 (fix:+ i 1)))
  38. ((fix:= i length))
  39. (floating-vector-set! result i (floating-vector-ref vector i)))
  40. result))
  41. (define (side-effecting-iter n proc)
  42. (define (reverse-order-iter count)
  43. (if (fix:= count n)
  44. 'done
  45. (begin
  46. (proc count)
  47. (reverse-order-iter (fix:+ 1 count)))))
  48. (reverse-order-iter 0))
  49. (define (lo-bound interval-length)
  50. (fix:- 1 (quotient (fix:+ 1 interval-length) 2)))
  51. (define (up-bound interval-length)
  52. (floor->exact (1+ (/ interval-length 2))))
  53. (define (floating-vector->list vector)
  54. (generate-list (floating-vector-length vector)
  55. (lambda (i)
  56. (floating-vector-ref vector i))))
  57. #| If not defined elsewhere
  58. (define (generate-list n proc) ; ==> ( (proc 0) (proc 1) ... (proc n-1) )
  59. (let loop ((i (fix:- n 1)) (list '()))
  60. (if (fix:< i 0)
  61. list
  62. (loop (fix:- i 1) (cons (proc i) list)))))
  63. |#
  64. ;;; Colormaps
  65. (define (n-gray-map window)
  66. (let ((name (graphics-type-name (graphics-type window))))
  67. (case name
  68. ((X) (n-gray-map/X11 window))
  69. ((WIN32) (n-gray-map/win32 window))
  70. ((OS/2) (n-gray-map/os2 window))
  71. (else (error "Unsupported graphics type:" name)))))
  72. (define (n-gray-map/X11 window)
  73. (let ((properties (x-display/properties (x-graphics/display window))))
  74. (or (1d-table/get properties '6001-GRAY-MAP #f)
  75. (let ((gm (allocate-grays window)))
  76. (1d-table/put! properties '6001-GRAY-MAP gm)
  77. gm))))
  78. (define (allocate-grays window)
  79. (let ((w-cm (graphics-operation window 'get-colormap))
  80. (visual-info (graphics-operation win 'visual-info)))
  81. (let ((find-info
  82. (let ((length (vector-length visual-info)))
  83. (if (= length 0)
  84. (error "X-GET-VISUAL-INFO: no results"))
  85. (lambda (class depth-min depth-max)
  86. (let loop ((index 0))
  87. (and (< index length)
  88. (let ((info (vector-ref visual-info index)))
  89. (if (and (= class (vector-ref info 4))
  90. ;; kludge, but X made us do it.
  91. (<= depth-min (vector-ref info 8) depth-max))
  92. info
  93. (loop (+ index 1)))))))))
  94. (make-gray-map
  95. (lambda (n-levels)
  96. (let ((gm (make-string n-levels))
  97. (step (/ 65535 (- n-levels 1))))
  98. (do ((index 0 (+ index 1)))
  99. ((= index n-levels))
  100. (vector-8b-set!
  101. gm
  102. index
  103. (let ((intensity (round->exact (* step index))))
  104. (x-colormap/allocate-color
  105. w-cm
  106. intensity intensity intensity))))
  107. gm))))
  108. (cond ((find-info visual-class:static-gray 256 256)
  109. (make-gray-map 256))
  110. ((or (find-info visual-class:gray-scale 256 256)
  111. (find-info visual-class:pseudo-color 250 256))
  112. (make-gray-map 128))
  113. ((find-info visual-class:static-gray 2 2)
  114. (make-gray-map 2))
  115. (else
  116. (error "ALLOCATE-GRAYS: not known display type" window))))))
  117. (define-integrable visual-class:static-gray 0)
  118. (define-integrable visual-class:gray-scale 1)
  119. (define-integrable visual-class:static-color 2)
  120. (define-integrable visual-class:pseudo-color 3)
  121. (define-integrable visual-class:true-color 4)
  122. (define-integrable visual-class:direct-color 5)
  123. (define n-gray-map/win32
  124. (let ((map (make-string 128)))
  125. (do ((i 0 (fix:+ i 1)))
  126. ((fix:= i 128))
  127. (vector-8b-set! map i i))
  128. (lambda (window) window map)))
  129. (define n-gray-map/os2
  130. (let ((map (make-string 256)))
  131. (do ((i 0 (fix:+ i 1)))
  132. ((fix:= i 256))
  133. (vector-8b-set! map i i))
  134. (lambda (window) window map)))
  135. (define os2-image-colormap:gray-256
  136. (make-initialized-vector 256
  137. (lambda (index)
  138. (+ (* index #x10000)
  139. (* index #x100)
  140. index))))
  141. ;;;; Pictures
  142. (define (procedure->picture width height fn)
  143. (let ((new-pic (make-picture width height)))
  144. (picture-map! new-pic fn)
  145. new-pic))
  146. (define (picture-map f . pic-list)
  147. (if (and (apply = (map (lambda (pic) (picture-width pic)) pic-list))
  148. (apply = (map (lambda (pic) (picture-height pic)) pic-list)))
  149. (let* ((width (picture-width (car pic-list)))
  150. (height (picture-height (car pic-list)))
  151. (new-pic (make-picture width height))
  152. (picdata (picture-data new-pic)))
  153. (cond ((null? pic-list)
  154. (error "no pictures -- PICTURE-MAP"))
  155. ((null? (cdr pic-list))
  156. (let ((p1-data (picture-data (car pic-list))))
  157. (let y-loop ((y 0))
  158. (if (fix:< y height)
  159. (let ((out-yth-row (vector-ref picdata y))
  160. (in-yth-row (vector-ref p1-data y)))
  161. (let x-loop ((x 0))
  162. (if (fix:< x width)
  163. (begin
  164. (floating-vector-set!
  165. out-yth-row x
  166. (exact->inexact
  167. (f (floating-vector-ref in-yth-row x))))
  168. (x-loop (fix:+ 1 x)))
  169. (y-loop (fix:+ 1 y)))))))))
  170. ((null? (cddr pic-list))
  171. (let ((p1-data (picture-data (car pic-list)))
  172. (p2-data (picture-data (cadr pic-list))))
  173. (let y-loop ((y 0))
  174. (if (fix:< y height)
  175. (let ((out-yth-row (vector-ref picdata y))
  176. (in-yth-row1 (vector-ref p1-data y))
  177. (in-yth-row2 (vector-ref p2-data y)))
  178. (let x-loop ((x 0))
  179. (if (fix:< x width)
  180. (begin
  181. (floating-vector-set!
  182. out-yth-row x
  183. (exact->inexact
  184. (f (floating-vector-ref in-yth-row1 x)
  185. (floating-vector-ref in-yth-row2 x))))
  186. (x-loop (fix:+ 1 x)))
  187. (y-loop (fix:+ 1 y)))))))))
  188. (else
  189. (let ((data-list
  190. (map (lambda (pic) (picture-data pic)) pic-list)))
  191. (let y-loop ((y 0))
  192. (if (fix:< y height)
  193. (let ((out-yth-row (vector-ref picdata y))
  194. (in-yth-rows (map (lambda (data)
  195. (vector-ref data y))
  196. data-list)))
  197. (let x-loop ((x 0))
  198. (if (fix:< x width)
  199. (begin
  200. (floating-vector-set!
  201. out-yth-row x
  202. (exact->inexact
  203. (apply f
  204. (map (lambda (row)
  205. (floating-vector-ref row x))
  206. in-yth-rows))))
  207. (x-loop (fix:+ 1 x)))
  208. (y-loop (fix:+ 1 y))))))))))
  209. (picture-set-data! new-pic picdata)
  210. new-pic)
  211. (error "picture sizes do not match -- PICTURE-MAP")))
  212. (define (picture-display window pic #!optional pic-min pic-max)
  213. (define (check-image pic window brick-wid brick-hgt)
  214. (if (image? (picture-image pic))
  215. (let ((image (picture-image pic)))
  216. (and (1d-table/get (graphics-device/properties window) image #f)
  217. (fix:= (fix:* (picture-width pic) brick-wid)
  218. (image/width image))
  219. (fix:= (fix:* (picture-height pic) brick-hgt)
  220. (image/height image))))
  221. #f))
  222. (call-with-values
  223. (lambda ()
  224. (graphics-device-coordinate-limits window))
  225. (lambda (x1 y1 x2 y2)
  226. (set! *last-picture-displayed* pic)
  227. (graphics-set-coordinate-limits window 0 (- y2 y1) (- x2 x1) 0)
  228. (let* ((win-wid (+ 1 (abs (- x2 x1))))
  229. (win-hgt (+ 1 (abs (- y1 y2))))
  230. (len&margin (integer-divide win-wid (picture-width pic)))
  231. (wid&margin (integer-divide win-hgt (picture-height pic)))
  232. (h-margin (integer-divide-remainder len&margin))
  233. (v-margin (integer-divide-remainder wid&margin))
  234. (brick-wid (integer-divide-quotient len&margin))
  235. (brick-hgt (integer-divide-quotient wid&margin))
  236. (pic-min (if (default-object? pic-min)
  237. (picture-min pic)
  238. (exact->inexact pic-min)))
  239. (pic-max (if (default-object? pic-max)
  240. (picture-max pic)
  241. (exact->inexact pic-max)))
  242. (true-min-max? (and (= pic-min (picture-min pic))
  243. (= pic-max (picture-max pic))))
  244. (image-cached? (check-image pic window brick-wid brick-hgt)))
  245. (if (or (fix:< brick-wid 1) (fix:< brick-hgt 1))
  246. (error "Window is too small to display" pic '--PICTURE-DISPLAY)
  247. (let ((image (if (and image-cached? true-min-max?)
  248. (picture-image pic)
  249. (build-image pic window
  250. brick-wid brick-hgt
  251. pic-min pic-max))))
  252. (graphics-clear window)
  253. (image/draw window
  254. (quotient h-margin 2)
  255. (- (quotient v-margin 2))
  256. image)
  257. (if (and true-min-max? (not image-cached?))
  258. (picture-set-image! pic image))))))))
  259. (define *last-picture-displayed*
  260. false)
  261. ;;; Representation of pictures using records
  262. (declare (usual-integrations))
  263. (define picture-type (make-record-type
  264. 'picture
  265. '(width
  266. height
  267. data
  268. min
  269. max
  270. image)))
  271. (define %make-picture (record-constructor picture-type '(width height)))
  272. (define %picture-min (record-accessor picture-type 'min))
  273. (define %picture-max (record-accessor picture-type 'max))
  274. (define %picture-set-data! (record-updater picture-type 'data))
  275. (define %picture-set-image! (record-updater picture-type 'image))
  276. (define %picture-set-min! (record-updater picture-type 'min))
  277. (define %picture-set-max! (record-updater picture-type 'max))
  278. (define (make-picture width height #!optional initial-val)
  279. (let ((pic (%make-picture width height))
  280. (initial-val (if (default-object? initial-val)
  281. 0.
  282. (exact->inexact initial-val))))
  283. (%picture-set-min! pic initial-val)
  284. (%picture-set-max! pic initial-val)
  285. (%picture-set-data! pic
  286. (make-initialized-vector
  287. height
  288. (lambda (n)
  289. n ; ignored
  290. (make-floating-vector width initial-val))))
  291. (%picture-set-image! pic #f)
  292. pic))
  293. (define picture? (record-predicate picture-type))
  294. (define picture-width
  295. (record-accessor picture-type 'width))
  296. (define picture-height
  297. (record-accessor picture-type 'height))
  298. (define picture-data
  299. (record-accessor picture-type 'data))
  300. (define picture-image
  301. (record-accessor picture-type 'image))
  302. (define (picture-set-image! picture image)
  303. (let ((img (picture-image picture)))
  304. (if (image? img)
  305. (image/destroy img))
  306. (%picture-set-image! picture image)))
  307. (define (picture-min picture)
  308. (let ((pic-min (%picture-min picture)))
  309. (if (not pic-min)
  310. (begin (find-min-max picture)
  311. (%picture-min picture))
  312. pic-min)))
  313. (define (picture-max picture)
  314. (let ((pic-max (%picture-max picture)))
  315. (if (not pic-max)
  316. (begin (find-min-max picture)
  317. (%picture-max picture))
  318. pic-max)))
  319. (define (make-picture-referencer bad-type-predicate bad-range-signal)
  320. (lambda (picture x y)
  321. (cond ((bad-type-predicate x)
  322. (error:wrong-type-argument x "picture X coordinate" 'PICTURE-REF))
  323. ((bad-type-predicate y)
  324. (error:wrong-type-argument y "picture Y coordinate" 'PICTURE-REF))
  325. ((not (and (fix:>= x 0)
  326. (fix:< x (picture-width picture))))
  327. (bad-range-signal x 'PICTURE-REF))
  328. ((not (and (fix:>= y 0)
  329. (fix:< y (picture-height picture))))
  330. (bad-range-signal y 'PICTURE-REF))
  331. (else
  332. (floating-vector-ref
  333. (vector-ref (picture-data picture) y) x)))))
  334. (define (make-picture-setter bad-type-predicate bad-range-signal)
  335. (lambda (picture x y value)
  336. (cond ((bad-type-predicate x)
  337. (error:wrong-type-argument x "picture X coordinate" 'PICTURE-SET!))
  338. ((bad-type-predicate y)
  339. (error:wrong-type-argument y "picture Y coordinate" 'PICTURE-SET!))
  340. ((not (and (fix:>= x 0)
  341. (fix:< x (picture-width picture))))
  342. (bad-range-signal x 'PICTURE-SET!))
  343. ((not (and (fix:>= y 0)
  344. (fix:< y (picture-height picture))))
  345. (bad-range-signal y 'PICTURE-SET!))
  346. (else
  347. (floating-vector-set! (vector-ref (picture-data picture) y)
  348. x (exact->inexact value))
  349. (invalidate-cached-values picture)))))
  350. (define picture-ref (make-picture-referencer
  351. (lambda (var)
  352. (declare (integrate var))
  353. (not (fix:fixnum? var)))
  354. error:bad-range-argument))
  355. (define no-error-picture-ref (make-picture-referencer
  356. (lambda (var)
  357. (declare (integrate var))
  358. var ;ignored
  359. false)
  360. (lambda (var proc-name)
  361. var proc-name ;ignored
  362. false)))
  363. (define picture-set! (make-picture-setter
  364. (lambda (var)
  365. (declare (integrate var))
  366. (not (fix:fixnum? var)))
  367. error:bad-range-argument))
  368. (define no-error-picture-set! (make-picture-setter
  369. (lambda (var)
  370. (declare (integrate var))
  371. var ;ignored
  372. false)
  373. (lambda (var proc-name)
  374. var proc-name ;ignored
  375. false)))
  376. (define (picture-map! picture fn)
  377. (let ((picdata (picture-data picture))
  378. (width (picture-width picture))
  379. (height (picture-height picture)))
  380. (let y-loop ((y 0))
  381. (if (< y height)
  382. (let ((yth-row (vector-ref picdata y)))
  383. (let x-loop ((x 0))
  384. (if (< x width)
  385. (begin (floating-vector-set! yth-row x
  386. (exact->inexact
  387. (fn x y)))
  388. (x-loop (1+ x)))
  389. (y-loop (1+ y))))))
  390. (invalidate-cached-values picture))))
  391. (define (picture-set-data! picture data)
  392. (%picture-set-data! picture data)
  393. (invalidate-cached-values picture))
  394. ;;; Note that picture-data and picture-set-data! are both unsafe operations
  395. ;;; in the sense that both of them do not ensure that only floating point
  396. ;;; numbers are ever stored in the picture array.
  397. (define (invalidate-cached-values picture)
  398. (%picture-set-min! picture #f)
  399. (%picture-set-max! picture #f)
  400. (let ((img (picture-image picture)))
  401. (if (image? img)
  402. (image/destroy img))
  403. (%picture-set-image! picture '())))
  404. (define (find-min-max picture)
  405. (let* ((picdata (picture-data picture))
  406. (width (picture-width picture))
  407. (height (picture-height picture))
  408. (current-min (floating-vector-ref (vector-ref picdata 0) 0))
  409. (current-max current-min))
  410. (let y-loop ((y 0))
  411. (if (< y height)
  412. (let ((yth-row (vector-ref picdata y)))
  413. (let x-loop ((x 0))
  414. (if (< x width)
  415. (let ((v (floating-vector-ref yth-row x)))
  416. (set! current-min (min current-min v))
  417. (set! current-max (max current-max v))
  418. (x-loop (1+ x)))
  419. (y-loop (1+ y)))))))
  420. (%picture-set-min! picture current-min)
  421. (%picture-set-max! picture current-max)))
  422. ;;; Procedure to build an image given a picture and the magnification factors
  423. (define (build-image pic window h-sf v-sf pic-min pic-max)
  424. (let* ((gray-map (n-gray-map window))
  425. (pic-height (picture-height pic)) ;py
  426. (pic-width (picture-width pic)) ;x
  427. (pic-data (picture-data pic))
  428. (image-width (fix:* h-sf pic-width)) ;x
  429. (image-height (fix:* v-sf pic-height)) ;iy
  430. (image (image/create window image-width image-height))
  431. (byte-string (make-string (fix:* image-width image-height)))
  432. (py-max (- pic-height 1))
  433. (rect-index-height (fix:* v-sf image-width))
  434. (range (flo:- pic-max pic-min))
  435. (index-range (string-length gray-map))
  436. (mul (if (flo:< range 1e-12)
  437. 0.
  438. (/ index-range
  439. (flo:* (flo:+ 1. 7.142e-8) ; 1+epsilon
  440. range))))
  441. (gray-pixel
  442. (lambda (pixel-value)
  443. (vector-8b-ref
  444. gray-map
  445. (let ((pixel
  446. (flo:floor->exact
  447. (flo:* mul (flo:- pixel-value pic-min)))))
  448. (cond ((fix:< pixel 0) 0)
  449. ((fix:< pixel index-range) pixel)
  450. (else (fix:- index-range 1))))))))
  451. (cond ((and (fix:= 1 h-sf) (fix:= 1 v-sf))
  452. (let y-loop ((py py-max) (iy-index 0))
  453. (if (fix:<= 0 py)
  454. (begin
  455. (let ((pic-row (vector-ref pic-data py)))
  456. (let x-loop ((px 0))
  457. (if (fix:< px pic-width)
  458. (begin
  459. (vector-8b-set!
  460. byte-string
  461. (fix:+ px iy-index)
  462. (gray-pixel (floating-vector-ref pic-row px)))
  463. (x-loop (fix:+ px 1))))))
  464. (y-loop (fix:- py 1) (fix:+ iy-index rect-index-height))))))
  465. ((and (fix:= 2 h-sf) (fix:= 2 v-sf))
  466. (let y-loop ((py py-max) (iy-index 0))
  467. (if (fix:<= 0 py)
  468. (let ((pic-row (vector-ref pic-data py)))
  469. (let x-loop ((px 0) (ix 0))
  470. (if (fix:< px pic-width)
  471. (let* ((n-is-0 (fix:+ ix iy-index))
  472. (n-is-1 (fix:+ n-is-0 image-width))
  473. (v
  474. (gray-pixel
  475. (floating-vector-ref pic-row px))))
  476. (vector-8b-set! byte-string n-is-0 v)
  477. (vector-8b-set! byte-string (fix:+ n-is-0 1) v)
  478. (vector-8b-set! byte-string n-is-1 v)
  479. (vector-8b-set! byte-string (fix:+ n-is-1 1) v)
  480. (x-loop (fix:+ px 1) (fix:+ ix h-sf)))
  481. (y-loop (fix:- py 1)
  482. (fix:+ iy-index rect-index-height))))))))
  483. ((and (fix:= 3 h-sf) (fix:= 3 v-sf))
  484. (let y-loop ((py py-max) (iy-index 0))
  485. (if (fix:<= 0 py)
  486. (let ((pic-row (vector-ref pic-data py)))
  487. (let x-loop ((px 0) (ix 0))
  488. (if (fix:< px pic-width)
  489. (let* ((row0 (fix:+ ix iy-index))
  490. (row1 (fix:+ row0 image-width))
  491. (row2 (fix:+ row1 image-width))
  492. (v
  493. (gray-pixel
  494. (floating-vector-ref pic-row px))))
  495. (vector-8b-set! byte-string row0 v)
  496. (vector-8b-set! byte-string (fix:+ row0 1) v)
  497. (vector-8b-set! byte-string (fix:+ row0 2) v)
  498. (vector-8b-set! byte-string row1 v)
  499. (vector-8b-set! byte-string (fix:+ row1 1) v)
  500. (vector-8b-set! byte-string (fix:+ row1 2) v)
  501. (vector-8b-set! byte-string row2 v)
  502. (vector-8b-set! byte-string (fix:+ row2 1) v)
  503. (vector-8b-set! byte-string (fix:+ row2 2) v)
  504. (x-loop (fix:+ px 1) (fix:+ ix h-sf)))
  505. (y-loop (fix:- py 1)
  506. (fix:+ iy-index rect-index-height))))))))
  507. ((and (fix:= 4 h-sf) (fix:= 4 v-sf))
  508. (let y-loop ((py py-max) (iy-index 0))
  509. (if (fix:<= 0 py)
  510. (let ((pic-row (vector-ref pic-data py)))
  511. (let x-loop ((px 0) (ix 0))
  512. (if (fix:< px pic-width)
  513. (let* ((row0 (fix:+ ix iy-index))
  514. (row1 (fix:+ row0 image-width))
  515. (row2 (fix:+ row1 image-width))
  516. (row3 (fix:+ row2 image-width))
  517. (v
  518. (gray-pixel
  519. (floating-vector-ref pic-row px))))
  520. (vector-8b-set! byte-string row0 v)
  521. (vector-8b-set! byte-string (fix:+ row0 1) v)
  522. (vector-8b-set! byte-string (fix:+ row0 2) v)
  523. (vector-8b-set! byte-string (fix:+ row0 3) v)
  524. (vector-8b-set! byte-string row1 v)
  525. (vector-8b-set! byte-string (fix:+ row1 1) v)
  526. (vector-8b-set! byte-string (fix:+ row1 2) v)
  527. (vector-8b-set! byte-string (fix:+ row1 3) v)
  528. (vector-8b-set! byte-string row2 v)
  529. (vector-8b-set! byte-string (fix:+ row2 1) v)
  530. (vector-8b-set! byte-string (fix:+ row2 2) v)
  531. (vector-8b-set! byte-string (fix:+ row2 3) v)
  532. (vector-8b-set! byte-string row3 v)
  533. (vector-8b-set! byte-string (fix:+ row3 1) v)
  534. (vector-8b-set! byte-string (fix:+ row3 2) v)
  535. (vector-8b-set! byte-string (fix:+ row3 3) v)
  536. (x-loop (fix:+ px 1) (fix:+ ix h-sf)))
  537. (y-loop (fix:- py 1)
  538. (fix:+ iy-index rect-index-height))))))))
  539. (else
  540. (let y-loop ((py py-max) (iy-index 0))
  541. (if (fix:<= 0 py)
  542. (let ((pic-row (vector-ref pic-data py)))
  543. (let x-loop ((px 0) (ix 0))
  544. (if (fix:< px pic-width)
  545. (let* ((v
  546. (gray-pixel (floating-vector-ref pic-row px)))
  547. (n-start (fix:+ ix iy-index))
  548. (n-end (fix:+ n-start rect-index-height)))
  549. (let n-loop ((n n-start))
  550. (if (fix:< n n-end)
  551. (let ((m-end (fix:+ n h-sf)))
  552. (let m-loop ((m n))
  553. (if (fix:< m m-end)
  554. (begin
  555. (vector-8b-set! byte-string m v)
  556. (m-loop (fix:+ m 1)))
  557. (n-loop (fix:+ n image-width)))))
  558. (x-loop (fix:+ px 1) (fix:+ ix h-sf)))))
  559. (y-loop (fix:- py 1)
  560. (fix:+ iy-index rect-index-height)))))))))
  561. ;; Kludge: IMAGE/FILL-FROM-BYTE-VECTOR should take an argument
  562. ;; that specifies what color a given byte in BYTE-STRING maps to.
  563. ;; OS/2 requires this information, so we supply it here.
  564. (if (eq? 'OS/2 microcode-id/operating-system)
  565. (os2-image/set-colormap image os2-image-colormap:gray-256))
  566. (image/fill-from-byte-vector image byte-string)
  567. (1d-table/put! (graphics-device/properties window) image #t)
  568. image))
  569. #|
  570. ;;; For example
  571. (define foo (make-window 1000 100 0 0))
  572. (define bar
  573. (procedure->picture 500 10
  574. (lambda (x y)
  575. (* (sin (/ x 5.)) y))))
  576. (picture-display foo bar)
  577. (graphics-close foo)
  578. |#