creativescala / doodle

Compositional vector graphics in Scala / Scala.JS
https://creativescala.org/doodle/
Apache License 2.0
327 stars 75 forks source link

Convert `Picture` to `BufferedImage` #87

Closed noelwelsh closed 6 months ago

noelwelsh commented 4 years ago

Create a stable Java2D specific method to convert a Picture to a BufferedImage. This will allow fun pixel art in conjunction with #85. This should be a new kind of effect type class, I think.

We already have a ToPicture type class. Perhaps FromPicture is the natural counterpart here? Not sure they would be symmetric though---rendering a picture is an effect but converting to a picture is not.

fireddd commented 2 years ago

Hi Noel, Is this what is needed here?? https://stackoverflow.com/questions/13605248/java-converting-image-to-bufferedimage

noelwelsh commented 2 years ago

That's not really the issue. This is about having a way to convert the Picture type in Doodle into a BufferedImage. All the code already exists, it just needs to presented in a stable API.

jCabala commented 6 months ago

I have one question about the end result. After the succesful implementation we want to be able to do something like:

val picture = circle(100)
val bi = picture.fromPicture

where bi is a BufferedImage or we want this function to evaluate the picture as well and get something like:

val picture = circle(100)
val (res, bi) = picture.fromPicture

Another possibility is to have a method .bufferedImage on picture that converts to the BufferedImage since there is such a method for the base64

noelwelsh commented 6 months ago

The closest equivalent is the Base64 effect.

I think the following is probably what is needed:

  1. An effect with a single method
def bufferedImage[A](picture: Picture[Alg, A]): IO[(A, BufferedImage)]
  1. Syntax to make it easier to use.

  2. An implementation for the Java2D backend. (Code already exists to do this conversion. It just needs to be exposed in this API.)

jCabala commented 6 months ago

The function renderBufferedImage() takes more arguments than just a picture:

image

Should we also make the user to specify those arguments in the effect? Also this function returns the IO with the types inside in a different order than the base64 function does:

image

Is that intended and should the effect also return this in that order?

noelwelsh commented 6 months ago

Yes, I think you're right. The parameters to renderBufferedImage are essentially the elements of Frame. So I think the correct signature is

def bufferedImage[A](frame: Frame, picture: Picture[Alg, A]): IO[(A, BufferedImage)]

The different order of types is just an accident. The external APIs should be as consistent as possible, and hence should follow the precedent in base64.

jCabala commented 6 months ago

Does the binary compatibillity check failing mean that I cannot make the Java2dWriter extend the BufferedImageConverter and should create a separate class for that?

noelwelsh commented 6 months ago

You can ignore binary compatibility issues. If you bump the base version defined in build.sbt the problem will go away.

jCabala commented 6 months ago

I made everything specific for java2d backend but now I started thinking that maybe the approach of making the converter generic with respect to the bitmap is better as other backends might have their own bitmap classes and that could be helpful for example if we want draw pixels on the screen or do the convolutions (#94)

noelwelsh commented 6 months ago

I made everything specific for java2d backend but now I started thinking that maybe the approach of making the converter generic with respect to the bitmap is better as other backends might have their own bitmap classes and that could be helpful for example if we want draw pixels on the screen or do the convolutions (#94)

Agreed with this. To avoid scope creep I opened another issue (#145) that includes this.