halide-JuicyPixels (empty) → 0.0.2.1
raw patch · 5 files changed
+184/−0 lines, 5 filesdep +JuicyPixelsdep +basedep +halide-JuicyPixels
Dependencies added: JuicyPixels, base, halide-JuicyPixels, halide-haskell, hspec, vector
Files
- LICENSE +30/−0
- README.md +19/−0
- halide-JuicyPixels.cabal +55/−0
- src/Language/Halide/JuicyPixels.hs +45/−0
- test/Main.hs +35/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2023, twesterhout++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of twesterhout nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,19 @@+<h1 align="center">+halide-JuicyPixels+</h1>++<div align="center">+<br />++[](LICENSE)++[](https://github.com/twesterhout/halide-haskell/actions/workflows/ci.yml)+[](https://hackage.haskell.org/package/halide-JuicyPixels)++</div>++This package integrates+[halide-haskell](https://github.com/twesterhout/halide-haskell/) with+[JuicyPixels](https://github.com/Twinside/Juicy.Pixels) by implementing+instances of `IsHalideBuffer` for `Image` and `MutableImage` types. See [this+test](test/Main.hs) for an example usage.
+ halide-JuicyPixels.cabal view
@@ -0,0 +1,55 @@+cabal-version: 3.0+name: halide-JuicyPixels+version: 0.0.2.1+synopsis: Integration between Halide and JuicyPixels+description:+ This package provides instances of [Language.Halide.IsHalideBuffer](https://hackage.haskell.org/package/halide-haskell/docs/Language-Halide.html#t:IsHalideBuffer)+ for image types from the [JuicyPixels](https://hackage.haskell.org/package/JuicyPixels) library.++homepage: https://github.com/twesterhout/halide-haskell+bug-reports: https://github.com/twesterhout/halide-haskell/issues+license: BSD-3-Clause+license-file: LICENSE+author: Tom Westerhout+maintainer:+ Tom Westerhout <14264576+twesterhout@users.noreply.github.com>++category: Language+copyright: 2022-2023 Tom Westerhout+build-type: Simple+extra-doc-files: README.md+tested-with: GHC ==9.2.7 || ==9.4.4 || ==9.4.5++common setup+ ghc-options: -Wall+ default-language: GHC2021+ default-extensions:+ DataKinds+ InstanceSigs+ LambdaCase+ OverloadedRecordDot+ TypeFamilies++library+ import: setup+ exposed-modules: Language.Halide.JuicyPixels+ build-depends:+ , base >=4.16.0.0 && <5+ , halide-haskell >=0.0.2.0 && <0.1.0.0+ , JuicyPixels >=3.3.0 && <4+ , vector >=0.12.3.0 && <0.13++ ghc-options: -Wno-orphans+ hs-source-dirs: src++test-suite halide-JuicyPixels-test+ import: setup+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Main.hs+ build-depends:+ , base+ , halide-haskell+ , halide-JuicyPixels+ , hspec >=2.9.7 && <3+ , JuicyPixels
+ src/Language/Halide/JuicyPixels.hs view
@@ -0,0 +1,45 @@+-- |+-- Module : Language.Halide.JuicyPixels+-- Copyright : (c) Tom Westerhout, 2023+--+-- This package allows you to use [JuicyPixels](https://hackage.haskell.org/package/JuicyPixels)+-- together with [halide-haskell](https://hackage.haskell.org/package/halide-haskell).+-- It defines 'Language.Halide.IsHalideBuffer' instances for 'Image' and+-- 'MutableImage' types from the JuicyPixels library.+--+-- That allows you to write code such as:+--+-- @+-- kernel :: Ptr ('HalideBuffer' 3 Word8) -> Ptr ('HalideBuffer' 3 Word8) -> IO ()+-- kernel = ...+--+-- brighten :: 'Image' 'PixelRGB8' -> 'MutableImage' 'RealWorld' 'PixelRGB8' -> IO ()+-- brighten input output = do+-- 'withHalideBuffer' @3 @Word8 input $ \input' ->+-- 'withHalideBuffer' @3 @Word8 output $ \output' ->+-- kernel input' output'+-- @+module Language.Halide.JuicyPixels ()+where++import Codec.Picture+import Codec.Picture.Types+import Control.Monad.ST (RealWorld)+import Data.Vector.Storable qualified as S+import Data.Vector.Storable.Mutable qualified as SM+import Language.Halide++instance (Pixel a, r ~ PixelBaseComponent a, IsHalideType r) => IsHalideBuffer (Image a) 3 r where+ withHalideBufferImpl :: Image a -> (Ptr (HalideBuffer 3 r) -> IO b) -> IO b+ withHalideBufferImpl im action =+ S.unsafeWith im.imageData $ \cpuPtr ->+ bufferFromPtrShape cpuPtr [componentCount (undefined :: a), im.imageWidth, im.imageHeight] action++instance (Pixel a, r ~ PixelBaseComponent a, IsHalideType r) => IsHalideBuffer (MutableImage RealWorld a) 3 r where+ withHalideBufferImpl :: MutableImage RealWorld a -> (Ptr (HalideBuffer 3 r) -> IO b) -> IO b+ withHalideBufferImpl im action =+ SM.unsafeWith im.mutableImageData $ \cpuPtr ->+ bufferFromPtrShape+ cpuPtr+ [componentCount (undefined :: a), im.mutableImageWidth, im.mutableImageHeight]+ action
+ test/Main.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}++module Main (main) where++import Codec.Picture+import Codec.Picture.Types+import Data.Word (Word8)+import Language.Halide+import Language.Halide.JuicyPixels+import System.IO.Unsafe (unsafePerformIO)+import Prelude hiding (min)++brighten :: Expr Float -> Parameter 3 Word8 -> IO (Function 3 Word8)+brighten factor input = do+ [x, y, c] <- mapM mkVar ["x", "y", "c"]+ let value = cast . min 255 . (factor *) . cast $ input ! (c, x, y)+ define "brighter" (c, x, y) value++main :: IO ()+main = do+ kernel <- compile brighten++ readImage "test/cat.jpg" >>= \case+ Right image -> do+ let rgb@(Image width height _) = convertRGB8 image+ output <- newMutableImage width height++ withHalideBuffer @3 @Word8 rgb $ \input ->+ withHalideBuffer @3 @Word8 output $ \output' ->+ kernel 2.5 input output'++ savePngImage "test.png" . ImageRGB8 =<< unsafeFreezeImage output+ Left e -> error e