Skip to content

Commit

Permalink
Move renderBufferedImage() to effect/Java2d, add a writer marker clas…
Browse files Browse the repository at this point in the history
…s, move Java2dBufferedImageWriter to separate file
  • Loading branch information
jCabala committed Mar 15, 2024
1 parent 226f085 commit 4060d3f
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import doodle.algebra.Algebra
import doodle.algebra.Picture
import java.awt.image.BufferedImage

trait BufferedImageWriter[+Alg <: Algebra, Frame] {
trait BufferedImageWriter[+Alg <: Algebra, Frame] extends Writer[Alg, Frame] {
def bufferedImage[A](
description: Frame,
picture: Picture[Alg, A]
Expand Down
3 changes: 2 additions & 1 deletion core/shared/src/main/scala/doodle/effect/Base64Writer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import doodle.core.{Base64 => B64}
/** The Base64 type represent the ability to encode an image as a Base64 String
* in a given format.
*/
trait Base64Writer[+Alg <: Algebra, Frame, Fmt <: Format] {
trait Base64Writer[+Alg <: Algebra, Frame, Fmt <: Format]
extends Writer[Alg, Frame] {
def base64[A](
description: Frame,
picture: Picture[Alg, A]
Expand Down
3 changes: 2 additions & 1 deletion core/shared/src/main/scala/doodle/effect/FileWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import java.io.File
/** The `FileWriter` typeclass represents write a picture to a file in a given
* format.
*/
trait FileWriter[+Alg <: Algebra, Frame, Fmt <: Format] {
trait FileWriter[+Alg <: Algebra, Frame, Fmt <: Format]
extends Writer[Alg, Frame] {
def write[A](file: File, description: Frame, image: Picture[Alg, A]): IO[A]
def write[A](file: File, image: Picture[Alg, A]): IO[A]
}
22 changes: 22 additions & 0 deletions core/shared/src/main/scala/doodle/effect/Writer.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2015 Creative Scala
*
* 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.
*/

package doodle
package effect

import doodle.algebra.Algebra

trait Writer[+Alg <: Algebra, Frame]
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ import cats.effect.IO
import doodle.algebra.Algebra
import doodle.algebra.Picture
import fs2.Stream
import doodle.effect.Writer

import java.io.File

/** The `AnimationWriter` typeclass describes a data type that can write an
* animation to a file.
*/
trait AnimationWriter[Alg <: Algebra, Frame, Format] {
trait AnimationWriter[Alg <: Algebra, Frame, Format]
extends Writer[Alg, Frame] {

def write[A](
file: File,
Expand Down
52 changes: 52 additions & 0 deletions java2d/src/main/scala/doodle/java2d/effect/Java2d.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,22 @@ package doodle
package java2d
package effect

import cats.effect.IO
import doodle.core.BoundingBox
import doodle.core.{Transform => Tx}
import doodle.core.Color
import doodle.core.Transform

import doodle.algebra.generic.*
import doodle.java2d.algebra.Graphics2DGraphicsContext
import doodle.java2d.algebra.reified.Reified
import doodle.java2d.algebra.Algebra
import doodle.java2d.algebra.reified.Reification
import doodle.java2d.algebra.{Java2D => Java2dAlgebra}

import java.awt.Graphics2D
import java.awt.RenderingHints
import java.awt.image.BufferedImage

/** Utilities for rendering with Java2D */
object Java2d {
Expand Down Expand Up @@ -100,4 +109,47 @@ object Java2d {
image.foreach { _.render(gc, transform)(Graphics2DGraphicsContext) }
}

def renderBufferedImage[A](
size: Size,
center: Center,
background: Option[Color],
picture: Picture[A]
)(makeImage: (Int, Int) => BufferedImage): IO[(BufferedImage, A)] =
for {
rendered <- renderGraphics2D(size, center, background, picture) { bb =>
IO {
val (w, h) = Java2d.size(bb, size)
val image = makeImage(w.toInt, h.toInt)

(Java2d.setup(image.createGraphics()), image)
}
}
(image, a) = rendered
} yield (image, a)

private[java2d] def renderGraphics2D[A, I](
size: Size,
center: Center,
background: Option[Color],
picture: Picture[A]
)(graphicsContext: BoundingBox => IO[(Graphics2D, I)]): IO[(I, A)] =
for {
gc <- IO {
val bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)
Java2d.setup(bi.createGraphics())
}
drawing: Finalized[Reification, A] <- IO { picture(Algebra(gc)) }
(bb, rdr) = drawing.run(List.empty).value
(_, fa) = rdr.run(Transform.identity).value
(r, a) = fa.run.value
(width, height) = Java2d.size(bb, size)
tx = Java2d.transform(bb, width, height, center)
contextWithImage <- graphicsContext(bb)
(gc, image) = contextWithImage
_ = background.foreach { c =>
gc.setColor(Java2dAlgebra.toAwtColor(c))
gc.fillRect(0, 0, width.toInt, height.toInt)
}
_ = Java2d.render(gc, r, tx)
} yield (image, a)
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ object Java2dAnimationWriter
a <- frames
.evalMap { picture =>
for {
result <- doodle.java2d.effect.Java2dWriter
result <- doodle.java2d.effect.Java2d
.renderBufferedImage(
frame.size,
frame.center,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2015 Creative Scala
*
* 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.
*/

package doodle
package java2d
package effect

import cats.effect.IO
import doodle.effect.*
import doodle.java2d.effect.{Java2d => Java2dEffect}
import java.awt.image.BufferedImage

object Java2dBufferedImageWriter
extends BufferedImageWriter[doodle.java2d.Algebra, Frame] {
def makeImage(width: Int, height: Int): BufferedImage =
new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)

def bufferedImage[A](
frame: Frame,
picture: Picture[A]
): IO[(A, BufferedImage)] = for {
result <- Java2dEffect.renderBufferedImage(
frame.size,
frame.center,
frame.background,
picture
)(makeImage _)
(bi, a) = result
} yield (a, bi)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,12 @@ import cats.effect.IO
import de.erichseifert.vectorgraphics2d.intermediate.CommandSequence
import de.erichseifert.vectorgraphics2d.pdf.PDFProcessor
import de.erichseifert.vectorgraphics2d.util.PageSize
import doodle.algebra.generic.*
import doodle.core.BoundingBox
import doodle.core.Color
import doodle.core.Transform
import doodle.core.format._
import doodle.core.{Base64 => B64}
import doodle.effect.*
import doodle.java2d.algebra.Algebra
import doodle.java2d.algebra.Java2D
import doodle.java2d.algebra.reified.Reification
import doodle.java2d.effect.{Java2d => Java2dEffect}

import java.awt.Graphics2D
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.io.File
Expand All @@ -42,7 +36,7 @@ import java.io.OutputStream
import java.util.{Base64 => JBase64}
import javax.imageio.ImageIO

trait Java2dFileWriter[Fmt <: Format]
trait Java2dWriter[Fmt <: Format]
extends FileWriter[doodle.java2d.Algebra, Frame, Fmt]
with Base64Writer[doodle.java2d.Algebra, Frame, Fmt] {
def format: String
Expand All @@ -58,7 +52,7 @@ trait Java2dFileWriter[Fmt <: Format]

def write[A](file: File, frame: Frame, picture: Picture[A]): IO[A] = {
for {
result <- Java2dWriter.renderBufferedImage(
result <- Java2d.renderBufferedImage(
frame.size,
frame.center,
frame.background,
Expand All @@ -85,7 +79,7 @@ trait Java2dFileWriter[Fmt <: Format]
picture: Picture[A]
): IO[A] = {
for {
result <- Java2dWriter.renderBufferedImage(
result <- Java2dEffect.renderBufferedImage(
frame.size,
frame.center,
frame.background,
Expand All @@ -101,72 +95,27 @@ trait Java2dFileWriter[Fmt <: Format]
}

}
object Java2dWriter {
def renderBufferedImage[A](
size: Size,
center: Center,
background: Option[Color],
picture: Picture[A]
)(makeImage: (Int, Int) => BufferedImage): IO[(BufferedImage, A)] =
for {
rendered <- renderGraphics2D(size, center, background, picture) { bb =>
IO {
val (w, h) = Java2d.size(bb, size)
val image = makeImage(w.toInt, h.toInt)

(Java2d.setup(image.createGraphics()), image)
}
}
(image, a) = rendered
} yield (image, a)

private[java2d] def renderGraphics2D[A, I](
size: Size,
center: Center,
background: Option[Color],
picture: Picture[A]
)(graphicsContext: BoundingBox => IO[(Graphics2D, I)]): IO[(I, A)] =
for {
gc <- IO {
val bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)
Java2d.setup(bi.createGraphics())
}
drawing: Finalized[Reification, A] <- IO { picture(Algebra(gc)) }
(bb, rdr) = drawing.run(List.empty).value
(_, fa) = rdr.run(Transform.identity).value
(r, a) = fa.run.value
(width, height) = Java2d.size(bb, size)
tx = Java2d.transform(bb, width, height, center)
contextWithImage <- graphicsContext(bb)
(gc, image) = contextWithImage
_ = background.foreach { c =>
gc.setColor(Java2D.toAwtColor(c))
gc.fillRect(0, 0, width.toInt, height.toInt)
}
_ = Java2d.render(gc, r, tx)
} yield (image, a)

}
object Java2dGifWriter extends Java2dFileWriter[Gif] {
object Java2dGifWriter extends Java2dWriter[Gif] {
val format = "gif"

def makeImage(width: Int, height: Int): BufferedImage =
new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
}
object Java2dPngWriter extends Java2dFileWriter[Png] {
object Java2dPngWriter extends Java2dWriter[Png] {
val format = "png"

def makeImage(width: Int, height: Int): BufferedImage =
new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
}
object Java2dJpgWriter extends Java2dFileWriter[Jpg] {
object Java2dJpgWriter extends Java2dWriter[Jpg] {
val format = "jpeg"

def makeImage(width: Int, height: Int): BufferedImage =
new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
}

object Java2dPdfWriter extends Java2dFileWriter[Pdf] {
object Java2dPdfWriter extends Java2dWriter[Pdf] {
val format = "pdf"

def makeImage(width: Int, height: Int): BufferedImage =
Expand All @@ -179,7 +128,7 @@ object Java2dPdfWriter extends Java2dFileWriter[Pdf] {
picture: Picture[A]
): IO[((CommandSequence, BoundingBox), A)] =
for {
rendered <- Java2dWriter.renderGraphics2D(
rendered <- Java2dEffect.renderGraphics2D(
frame.size,
frame.center,
frame.background,
Expand Down Expand Up @@ -207,22 +156,3 @@ object Java2dPdfWriter extends Java2dFileWriter[Pdf] {
}
} yield value
}

object Java2dBufferedImageWriter
extends BufferedImageWriter[doodle.java2d.Algebra, Frame] {
def makeImage(width: Int, height: Int): BufferedImage =
new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)

def bufferedImage[A](
frame: Frame,
picture: Picture[A]
): IO[(A, BufferedImage)] = for {
result <- Java2dWriter.renderBufferedImage(
frame.size,
frame.center,
frame.background,
picture
)(makeImage _)
(bi, a) = result
} yield (a, bi)
}

0 comments on commit 4060d3f

Please sign in to comment.