From 81abe5c60a48650ffe7ce646f983007418f81a19 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Wed, 24 May 2023 07:29:59 -0400 Subject: Move pixbuf module to (chickadee graphics ...) namespace. --- Makefile.am | 2 +- chickadee/graphics/framebuffer.scm | 2 +- chickadee/graphics/pixbuf.scm | 191 +++++++++++++++++++++++++++++++++++++ chickadee/graphics/skybox.scm | 2 +- chickadee/graphics/text.scm | 2 +- chickadee/graphics/texture.scm | 2 +- chickadee/image.scm | 2 +- chickadee/pixbuf.scm | 191 ------------------------------------- 8 files changed, 197 insertions(+), 197 deletions(-) create mode 100644 chickadee/graphics/pixbuf.scm delete mode 100644 chickadee/pixbuf.scm diff --git a/Makefile.am b/Makefile.am index 4b3593d..00162a3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,6 @@ SOURCES = \ chickadee/audio/vorbis.scm \ chickadee/audio/wav.scm \ chickadee/audio.scm \ - chickadee/pixbuf.scm \ chickadee/image.scm \ chickadee/image/jpeg.scm \ chickadee/image/png.scm \ @@ -76,6 +75,7 @@ SOURCES = \ chickadee/graphics/stencil.scm \ chickadee/graphics/multisample.scm \ chickadee/graphics/buffer.scm \ + chickadee/graphics/pixbuf.scm \ chickadee/graphics/texture.scm \ chickadee/graphics/shader.scm \ chickadee/graphics/viewport.scm \ diff --git a/chickadee/graphics/framebuffer.scm b/chickadee/graphics/framebuffer.scm index a05d6ef..bee4b7d 100644 --- a/chickadee/graphics/framebuffer.scm +++ b/chickadee/graphics/framebuffer.scm @@ -29,9 +29,9 @@ #:use-module (chickadee graphics color) #:use-module (chickadee graphics engine) #:use-module (chickadee graphics gl) + #:use-module (chickadee graphics pixbuf) #:use-module ((chickadee graphics texture) #:select (make-texture null-texture)) #:use-module (chickadee graphics viewport) - #:use-module (chickadee pixbuf) #:export (make-framebuffer framebuffer? framebuffer-texture diff --git a/chickadee/graphics/pixbuf.scm b/chickadee/graphics/pixbuf.scm new file mode 100644 index 0000000..c6a9e13 --- /dev/null +++ b/chickadee/graphics/pixbuf.scm @@ -0,0 +1,191 @@ +;;; Chickadee Game Toolkit +;;; Copyright © 2023 David Thompson +;;; +;;; Licensed under the Apache License, Version 2.0 (the "License"); +;;; you may not use this file except in compliance with the License. +;;; You may obtain a copy of the License at +;;; +;;; http://www.apache.org/licenses/LICENSE-2.0 +;;; +;;; Unless required by applicable law or agreed to in writing, software +;;; distributed under the License is distributed on an "AS IS" BASIS, +;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;;; See the License for the specific language governing permissions and +;;; limitations under the License. + +;;; Commentary: +;; +;; CPU-side pixel data buffers. +;; +;;; Code: + +(define-module (chickadee graphics pixbuf) + #:use-module (chickadee graphics color) + #:use-module (chickadee utils) + #:use-module (ice-9 exceptions) + #:use-module (rnrs bytevectors) + #:use-module (srfi srfi-9) + #:use-module (srfi srfi-9 gnu) + #:export (make-pixbuf + bytevector->pixbuf + pixbuf? + pixbuf-alpha? + pixbuf-pixels + pixbuf-width + pixbuf-height + pixbuf-format + pixbuf-bit-depth + pixbuf-copy-raw! + pixbuf-flip-vertically! + pixbuf-color-key!)) + +(define &pixbuf-error + (make-exception-type '&pixbuf-error &error '())) + +(define make-pixbuf-error (record-constructor &pixbuf-error)) + +(define (pixbuf-error message irritants) + (raise-exception + (make-exception + (make-pixbuf-error) + (make-exception-with-message message) + (make-exception-with-irritants irritants)))) + +;; A pixbuf is raw pixel data stored in memory that can be saved to +;; disk or loaded into a GPU texture. +(define-record-type + (%make-pixbuf pixels width height format bit-depth) + pixbuf? + (pixels pixbuf-pixels) + (width pixbuf-width) + (height pixbuf-height) + (format pixbuf-format) + (bit-depth pixbuf-bit-depth)) + +(define (print-pixbuf pixbuf port) + (format port "#" + (pixbuf-width pixbuf) + (pixbuf-height pixbuf) + (pixbuf-format pixbuf) + (pixbuf-bit-depth pixbuf))) + +(set-record-type-printer! print-pixbuf) + +(define (channel-count format) + (case format + ((rgba) 4))) + +(define (byte-depth bit-depth) + (/ bit-depth 8)) + +(define (buffer-length width height format bit-depth) + (* width height + (byte-depth bit-depth) + (channel-count format))) + +(define* (make-pixbuf width height #:key (format 'rgba) (bit-depth 8)) + "Return a new pixbuf object of WIDTH x HEIGHT pixels using color +channel FORMAT and BIT-DEPTH bits per channel. Initially, all color +channel values are 0. Currently, the only supported format is 'rgba' +and the only supported bit depth is 8." + (unless (= bit-depth 8) + (pixbuf-error "unsupported bit depth" (list bit-depth))) + (unless (eq? format 'rgba) + (pixbuf-error "unsupported format" (list format))) + (let* ((n (buffer-length width height format bit-depth)) + (buffer (make-bytevector n 0))) + (%make-pixbuf buffer width height format bit-depth))) + +(define* (bytevector->pixbuf bv width height #:key (format 'rgba) (bit-depth 8)) + (let ((pixbuf (make-pixbuf width height + #:format format + #:bit-depth bit-depth))) + (pixbuf-copy-raw! pixbuf bv) + pixbuf)) + +(define (pixbuf-alpha? pixbuf) + "Return #t if PIXBUF has an alpha channel." + (case (pixbuf-format pixbuf) + ((rgba) #t) + (else #f))) + +(define (pixbuf-byte-depth pixbuf) + (byte-depth (pixbuf-bit-depth pixbuf))) + +(define (pixbuf-red-channel-index pixbuf) + (case (pixbuf-format pixbuf) + ((rgba) 0))) + +(define (pixbuf-green-channel-index pixbuf) + (case (pixbuf-format pixbuf) + ((rgba) 1))) + +(define (pixbuf-blue-channel-index pixbuf) + (case (pixbuf-format pixbuf) + ((rgba) 2))) + +(define (pixbuf-alpha-channel-index pixbuf) + (case (pixbuf-format pixbuf) + ((rgba) 3))) + +(define (pixbuf-channel-count pixbuf) + "Return the number of channels per pixel in PIXBUF." + (channel-count (pixbuf-format pixbuf))) + +(define (pixbuf-copy-raw! pixbuf bv) + "Copy the contents of the bytevector BV into PIXBUF. BV must be +exactly the same size as the underlying buffer of PIXBUF." + (let* ((pixels (pixbuf-pixels pixbuf)) + (n (bytevector-length pixels))) + (if (= (bytevector-length bv) n) + (bytevector-copy! bv 0 pixels 0 n) + (pixbuf-error "improperly sized bytevector" (list bv))))) + +(define (pixbuf-flip-vertically! pixbuf) + "Flip the pixel data in PIXBUF upside-down." + (let* ((w (pixbuf-width pixbuf)) + (h (pixbuf-height pixbuf)) + (n (pixbuf-channel-count pixbuf)) + (d (pixbuf-byte-depth pixbuf)) + (row-length (* w n d)) + (temp-row (make-bytevector row-length 0)) + (pixels (pixbuf-pixels pixbuf))) + (for-range ((y (floor (/ h 2)))) + (let* ((y* (- h y 1)) + (source-start (* y row-length)) + (target-start (* y* row-length))) + ;; Copy the target row into the temp row. + (bytevector-copy! pixels target-start temp-row 0 row-length) + ;; Overwrite the target row with the source row. + (bytevector-copy! pixels source-start pixels target-start row-length) + ;; Overwrite the source row with the temp row. + (bytevector-copy! temp-row 0 pixels source-start row-length))))) + +(define (pixbuf-color-key! pixbuf color) + "Overwrite the alpha channel for pixels in PIXBUF that match COLOR +with full transparency." + (when (pixbuf-alpha? pixbuf) + (let* ((w (pixbuf-width pixbuf)) + (h (pixbuf-height pixbuf)) + (n (pixbuf-channel-count pixbuf)) + (d (pixbuf-byte-depth pixbuf)) + (ri (pixbuf-red-channel-index pixbuf)) + (gi (pixbuf-green-channel-index pixbuf)) + (bi (pixbuf-blue-channel-index pixbuf)) + (ai (pixbuf-alpha-channel-index pixbuf)) + (high (- (expt 256 d) 1)) + (r (inexact->exact (* (color-r color) high))) + (g (inexact->exact (* (color-g color) high))) + (b (inexact->exact (* (color-b color) high))) + (pixels (pixbuf-pixels pixbuf))) + (define (channel-ref i offset) + (bytevector-uint-ref pixels (+ i offset) (native-endianness) d)) + (define (channel-set! i offset x) + (bytevector-uint-set! pixels (+ i offset) x (native-endianness) d)) + (for-range ((i (bytevector-length pixels) 0 (* n d))) + ;; Zero the alpha channel of pixels that match the transparent + ;; color key. + (when (and (= r (channel-ref i ri)) + (= g (channel-ref i gi)) + (= b (channel-ref i bi))) + (channel-set! i ai 0)))))) diff --git a/chickadee/graphics/skybox.scm b/chickadee/graphics/skybox.scm index 57e2f81..31fcd76 100644 --- a/chickadee/graphics/skybox.scm +++ b/chickadee/graphics/skybox.scm @@ -26,10 +26,10 @@ #:use-module (chickadee graphics color) #:use-module (chickadee graphics depth) #:use-module (chickadee graphics engine) + #:use-module (chickadee graphics pixbuf) #:use-module (chickadee graphics polygon) #:use-module (chickadee graphics shader) #:use-module (chickadee graphics texture) - #:use-module (chickadee pixbuf) #:use-module (srfi srfi-9) #:export (make-skybox skybox? diff --git a/chickadee/graphics/text.scm b/chickadee/graphics/text.scm index 12269ac..20b8ca5 100644 --- a/chickadee/graphics/text.scm +++ b/chickadee/graphics/text.scm @@ -37,10 +37,10 @@ #:use-module (chickadee math matrix) #:use-module (chickadee math rect) #:use-module (chickadee math vector) - #:use-module (chickadee pixbuf) #:use-module (chickadee graphics blend) #:use-module (chickadee graphics color) #:use-module (chickadee graphics engine) + #:use-module (chickadee graphics pixbuf) #:use-module (chickadee graphics shader) #:use-module (chickadee graphics sprite) #:use-module (chickadee graphics texture) diff --git a/chickadee/graphics/texture.scm b/chickadee/graphics/texture.scm index b6595ee..c78db50 100644 --- a/chickadee/graphics/texture.scm +++ b/chickadee/graphics/texture.scm @@ -29,8 +29,8 @@ #:use-module (chickadee graphics color) #:use-module (chickadee graphics engine) #:use-module (chickadee graphics gl) + #:use-module (chickadee graphics pixbuf) #:use-module (chickadee image) - #:use-module (chickadee pixbuf) #:use-module (chickadee utils) #:export (make-texture make-texture-region diff --git a/chickadee/image.scm b/chickadee/image.scm index 48dddac..015891e 100644 --- a/chickadee/image.scm +++ b/chickadee/image.scm @@ -21,9 +21,9 @@ (define-module (chickadee image) #:use-module (chickadee graphics color) + #:use-module (chickadee graphics pixbuf) #:use-module (chickadee image jpeg) #:use-module (chickadee image png) - #:use-module (chickadee pixbuf) #:use-module (chickadee utils) #:use-module (ice-9 exceptions) #:use-module (ice-9 match) diff --git a/chickadee/pixbuf.scm b/chickadee/pixbuf.scm deleted file mode 100644 index c15a0b7..0000000 --- a/chickadee/pixbuf.scm +++ /dev/null @@ -1,191 +0,0 @@ -;;; Chickadee Game Toolkit -;;; Copyright © 2023 David Thompson -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; Commentary: -;; -;; CPU-side pixel data buffers. -;; -;;; Code: - -(define-module (chickadee pixbuf) - #:use-module (chickadee graphics color) - #:use-module (chickadee utils) - #:use-module (ice-9 exceptions) - #:use-module (rnrs bytevectors) - #:use-module (srfi srfi-9) - #:use-module (srfi srfi-9 gnu) - #:export (make-pixbuf - bytevector->pixbuf - pixbuf? - pixbuf-alpha? - pixbuf-pixels - pixbuf-width - pixbuf-height - pixbuf-format - pixbuf-bit-depth - pixbuf-copy-raw! - pixbuf-flip-vertically! - pixbuf-color-key!)) - -(define &pixbuf-error - (make-exception-type '&pixbuf-error &error '())) - -(define make-pixbuf-error (record-constructor &pixbuf-error)) - -(define (pixbuf-error message irritants) - (raise-exception - (make-exception - (make-pixbuf-error) - (make-exception-with-message message) - (make-exception-with-irritants irritants)))) - -;; A pixbuf is raw pixel data stored in memory that can be saved to -;; disk or loaded into a GPU texture. -(define-record-type - (%make-pixbuf pixels width height format bit-depth) - pixbuf? - (pixels pixbuf-pixels) - (width pixbuf-width) - (height pixbuf-height) - (format pixbuf-format) - (bit-depth pixbuf-bit-depth)) - -(define (print-pixbuf pixbuf port) - (format port "#" - (pixbuf-width pixbuf) - (pixbuf-height pixbuf) - (pixbuf-format pixbuf) - (pixbuf-bit-depth pixbuf))) - -(set-record-type-printer! print-pixbuf) - -(define (channel-count format) - (case format - ((rgba) 4))) - -(define (byte-depth bit-depth) - (/ bit-depth 8)) - -(define (buffer-length width height format bit-depth) - (* width height - (byte-depth bit-depth) - (channel-count format))) - -(define* (make-pixbuf width height #:key (format 'rgba) (bit-depth 8)) - "Return a new pixbuf object of WIDTH x HEIGHT pixels using color -channel FORMAT and BIT-DEPTH bits per channel. Initially, all color -channel values are 0. Currently, the only supported format is 'rgba' -and the only supported bit depth is 8." - (unless (= bit-depth 8) - (pixbuf-error "unsupported bit depth" (list bit-depth))) - (unless (eq? format 'rgba) - (pixbuf-error "unsupported format" (list format))) - (let* ((n (buffer-length width height format bit-depth)) - (buffer (make-bytevector n 0))) - (%make-pixbuf buffer width height format bit-depth))) - -(define* (bytevector->pixbuf bv width height #:key (format 'rgba) (bit-depth 8)) - (let ((pixbuf (make-pixbuf width height - #:format format - #:bit-depth bit-depth))) - (pixbuf-copy-raw! pixbuf bv) - pixbuf)) - -(define (pixbuf-alpha? pixbuf) - "Return #t if PIXBUF has an alpha channel." - (case (pixbuf-format pixbuf) - ((rgba) #t) - (else #f))) - -(define (pixbuf-byte-depth pixbuf) - (byte-depth (pixbuf-bit-depth pixbuf))) - -(define (pixbuf-red-channel-index pixbuf) - (case (pixbuf-format pixbuf) - ((rgba) 0))) - -(define (pixbuf-green-channel-index pixbuf) - (case (pixbuf-format pixbuf) - ((rgba) 1))) - -(define (pixbuf-blue-channel-index pixbuf) - (case (pixbuf-format pixbuf) - ((rgba) 2))) - -(define (pixbuf-alpha-channel-index pixbuf) - (case (pixbuf-format pixbuf) - ((rgba) 3))) - -(define (pixbuf-channel-count pixbuf) - "Return the number of channels per pixel in PIXBUF." - (channel-count (pixbuf-format pixbuf))) - -(define (pixbuf-copy-raw! pixbuf bv) - "Copy the contents of the bytevector BV into PIXBUF. BV must be -exactly the same size as the underlying buffer of PIXBUF." - (let* ((pixels (pixbuf-pixels pixbuf)) - (n (bytevector-length pixels))) - (if (= (bytevector-length bv) n) - (bytevector-copy! bv 0 pixels 0 n) - (pixbuf-error "improperly sized bytevector" (list bv))))) - -(define (pixbuf-flip-vertically! pixbuf) - "Flip the pixel data in PIXBUF upside-down." - (let* ((w (pixbuf-width pixbuf)) - (h (pixbuf-height pixbuf)) - (n (pixbuf-channel-count pixbuf)) - (d (pixbuf-byte-depth pixbuf)) - (row-length (* w n d)) - (temp-row (make-bytevector row-length 0)) - (pixels (pixbuf-pixels pixbuf))) - (for-range ((y (floor (/ h 2)))) - (let* ((y* (- h y 1)) - (source-start (* y row-length)) - (target-start (* y* row-length))) - ;; Copy the target row into the temp row. - (bytevector-copy! pixels target-start temp-row 0 row-length) - ;; Overwrite the target row with the source row. - (bytevector-copy! pixels source-start pixels target-start row-length) - ;; Overwrite the source row with the temp row. - (bytevector-copy! temp-row 0 pixels source-start row-length))))) - -(define (pixbuf-color-key! pixbuf color) - "Overwrite the alpha channel for pixels in PIXBUF that match COLOR -with full transparency." - (when (pixbuf-alpha? pixbuf) - (let* ((w (pixbuf-width pixbuf)) - (h (pixbuf-height pixbuf)) - (n (pixbuf-channel-count pixbuf)) - (d (pixbuf-byte-depth pixbuf)) - (ri (pixbuf-red-channel-index pixbuf)) - (gi (pixbuf-green-channel-index pixbuf)) - (bi (pixbuf-blue-channel-index pixbuf)) - (ai (pixbuf-alpha-channel-index pixbuf)) - (high (- (expt 256 d) 1)) - (r (inexact->exact (* (color-r color) high))) - (g (inexact->exact (* (color-g color) high))) - (b (inexact->exact (* (color-b color) high))) - (pixels (pixbuf-pixels pixbuf))) - (define (channel-ref i offset) - (bytevector-uint-ref pixels (+ i offset) (native-endianness) d)) - (define (channel-set! i offset x) - (bytevector-uint-set! pixels (+ i offset) x (native-endianness) d)) - (for-range ((i (bytevector-length pixels) 0 (* n d))) - ;; Zero the alpha channel of pixels that match the transparent - ;; color key. - (when (and (= r (channel-ref i ri)) - (= g (channel-ref i gi)) - (= b (channel-ref i bi))) - (channel-set! i ai 0)))))) -- cgit v1.2.3