/floatimage

A golang implementation of RGBA images based on float values.

Primary LanguageGoCreative Commons Zero v1.0 UniversalCC0-1.0

floatimage

This is image implementations based on float64 and float32 values for image channels RGBA.

Images are common RGB with alpha or premultiplied alpha channels. All channels are 64 bit or 32 bit float values.

This library implements float based images from scratch. They are fully compatible to those provided by the standard go library image. (Note: PNG image encoder will save these float images as 16bit/channel as these image types are not hardwired listed the PNG encoder as the standard image types.)

Expected value range for each channel is [0.0, 1.0]. Nothing stops the channel values to be outside the valid value interval but any call to the Color interface function RGBA() (r, g, b, a uint32) will clamp the values to the valid range. The image writing encoders of golang will also assume values are in the expected range. If you use values outside the assumed range you may need to scale your values to a valid range before any drawing or writing image to disc.

All image formats are backed by an accompanying color model.

  • NRGBAF64 - Color and RGB image with ordinary alpha (non premultiplied). All channels are encoded as a 64 bit float value (per pixel).

  • NRGBAF32 - Color and RGB image with ordinary alpha (non premultiplied). All channels are encoded as a 32 bit float value (per pixel).

  • RGBAF64 - Color and RGB image with premultiplied alpha. All channels are encoded as a 64 bit float value (per pixel).

  • RGBAF32 - Color and RGB image with premultiplied alpha. All channels are encoded as a 32 bit float value (per pixel).

License

CC0

It is not a requirement by the license, but if you do improve the code then any feedback or pull request is very appreciated. Sharing is caring.

Dependencies

Nope. No exotic dependencies to mention.

Example

Have look at the test example that renders a float image with float RGBA values in the range [0.0, 1.0] and then saves it as a common image.Image.

package main

import (
  "floatimage/pkg/floatcolor"
  "math"
  "testing"
)

func main() {
  nrgbaf64 := NewNRGBAF64(100, 100)

  width := nrgbaf64.Bounds().Dx()
  height := nrgbaf64.Bounds().Dy()
  diagonalMax := math.Sqrt(float64(width*width + height*height))

  for y := 0; y < height; y++ {
    for x := 0; x < width; x++ {
      diagonal := math.Sqrt(float64(x*x + y*y))

      c := floatcolor.NRGBAF64{
        R: float64(x) / float64(width),
        G: float64(y) / float64(height),
        B: diagonal / diagonalMax,
        A: diagonal / diagonalMax,
      }

      px := x + nrgbaf64.Bounds().Min.X
      py := y + nrgbaf64.Bounds().Min.Y
      nrgbaf64.Set(px, py, c)
    }
  }

  writeImage("NRGBAF64.png", nrgbaf64)
  writeImage("NRGBAF64_as_NRGBA.png", nrgbaf64.AsNRGBA())
  writeImage("NRGBAF64_as_RGBA.png", nrgbaf64.AsRGBA())
}

TODO

  • Function to check if all values are in valid normal range both for float color and for float image.

  • Function to clamp all values both in float color but also in float image to a range

NOT TODO

  • Images and colors will never have a min-max-range associated with them to automatically be compatible with each other and to make any range valid for drawing and image encoding out of the box. It would be feasible to implement but at a computationally expensive price. And the images need their efficiency as there is already a lot of floats in there to calculate.