hdr

package module
v0.2.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 4, 2023 License: MIT Imports: 3 Imported by: 15

README

HDR - High Dynamic Range

GoDoc Go Report Card License

HDR is a library that handles RAW image format written with Golang. Here some rendering examples.

It aims to provide tools to read HDR files and convert it to a LDR (Low Dynamic Range, aka PNG/JPEG/etc.) in an image.Image object.

Documentations:

Supported codecs (file formats)

  • Radiance RGBE/XYZE
  • PFM, Portable FloatMap file format
  • TIFF using mdouchement/tiff
  • CRAD, homemade HDR file format

Supported tone mapping operators

Read this documentation to find what TMO use.

Read this documentation to understand what is a TMO.

  • Linear
  • Logarithmic
  • Drago '03 - Adaptive logarithmic mapping for displaying high contrast scenes
  • Durand - Fast bilateral filtering for the display of high-dynamic-range images
  • Reinhard '05 - Photographic tone reproduction for digital images
    • Playing with parameters could provide better rendering
  • Custom Reinhard '05
    • Rendering looks like a JPEG photo taken with a smartphone
  • iCAM06 - A refined image appearance model for HDR image rendering

Usage

go get github.com/mdouchement/hdr
package main

import (
	"fmt"
	"image"
	"image/png"
	"os"
	"runtime"
	"time"

	"github.com/mdouchement/hdr"
	_ "github.com/mdouchement/hdr/codec/rgbe"
	"github.com/mdouchement/hdr/tmo"
)

// Samples:
//
// http://www.anyhere.com/gward/hdrenc/pages/originals.html
// http://resources.mpi-inf.mpg.de/tmo/logmap/ (High Contrast Scenes)

var (
	// input = "/Users/mdouchement/tmp/hdr/memorial_o876.hdr"
	// input = "/Users/mdouchement/tmp/hdr/MtTamWest_o281.hdr"
	// input = "/Users/mdouchement/tmp/hdr/rend02_oC95.hdr"
	// input = "/Users/mdouchement/tmp/hdr/Tree_oAC1.hdr"
	input  = "/Users/mdouchement/tmp/hdr/Apartment_float_o15C.hdr"
	output = "/Users/mdouchement/tmp/hdr/output.png"
)

func main() {
	fmt.Printf("Using %d CPUs\n", runtime.NumCPU())

	fi, err := os.Open(input)
	check(err)
	defer fi.Close()

	start := time.Now()

	m, fname, err := image.Decode(fi)
	check(err)

	fmt.Printf("Read image (%s) took %v\n", fname, time.Since(start))

	if hdrm, ok := m.(hdr.Image); ok {
		startTMO := time.Now()

		// t := tmo.NewLinear(hdrm)
		// t := tmo.NewLogarithmic(hdrm)
		// t := tmo.NewDefaultDrago03(hdrm)
		// t := tmo.NewDefaultDurand(hdrm)
		// t := tmo.NewDefaultCustomReinhard05(hdrm)
		t := tmo.NewDefaultReinhard05(hdrm)
		// t := tmo.NewDefaultICam06(hdrm)
		m = t.Perform()

		fmt.Println("Apply TMO took", time.Since(startTMO))
	}

	fo, err := os.Create(output)
	check(err)

	png.Encode(fo, m)

	fmt.Println("Total", time.Since(start))
}

func check(err error) {
	if err != nil {
		panic(err)
	}
}

HDR Tools

https://github.com/mdouchement/hdrtool

License

MIT

Implementing a TMO

A TMO must implement tmo.ToneMappingOperator:

type ToneMappingOperator interface {
	// Perform runs the TMO mapping.
	Perform() image.Image
}

Implementing an image codec

  • Reader
// DecodeConfig returns the color model and dimensions of a PFM image without
// decoding the entire image.
func DecodeConfig(r io.Reader) (image.Config, error) {
  // ...
  return m, err
}

// Decode reads a HDR image from r and returns an image.Image.
func Decode(r io.Reader) (img image.Image, err error) {
  // ...
  return
}

func init() {
  // Register the format in the official lib.
  // https://golang.org/pkg/image/#RegisterFormat
  image.RegisterFormat("format-name", "magic-code", Decode, DecodeConfig)
}
  • Writer
// Encode writes the Image m to w in PFM format.
func Encode(w io.Writer, m hdr.Image) error {
  return nil
}

Contributing

All PRs are welcome. If you implement a TMO or an image codec in a dedicated repository, please tell me in order to link it in this readme.

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

As possible, run the following commands to format and lint the code:

# Format
find . -name '*.go' -not -path './vendor*' -exec gofmt -s -w {} \;

# Lint
golangci-lint run -c .golangci.yml

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Split

func Split(x1, y1, x2, y2, n int) []image.Rectangle

Split tries to split the given rectangle coordinates in n tiles.

func SplitWithRectangle

func SplitWithRectangle(r image.Rectangle, n int) []image.Rectangle

SplitWithRectangle tries to split the given rectangle (image) in n tiles.

Types

type Image

type Image interface {
	image.Image

	// HDRAt returns the HDR pixel color at given coordinates.
	HDRAt(x, y int) hdrcolor.Color
	// Size returns the number of pixels.
	Size() int
}

Image is a finite rectangular grid of hdrcolor.Color values taken from a color model.

func Copy

func Copy(src Image) Image

Copy copies the src into a new image.

func EmptyAs

func EmptyAs(src Image) Image

EmptyAs returns a new empty image with the same underlying type and params as src.

type ImageSet

type ImageSet interface {
	// Set adds pixel to Image at given x, y.
	Set(x, y int, c color.Color)
}

ImageSet is an Image where we can set pixels.

type LMSCAT02w

type LMSCAT02w struct {
	Image
}

A LMSCAT02w wrapper hollows to get pixels in LMS-space using CIE CAT02 matrix. https://en.wikipedia.org/wiki/CIECAM02#Chromatic_adaptation

func NewLMSCAT02w

func NewLMSCAT02w(m Image) *LMSCAT02w

NewLMSCAT02w instanciates a new LMSCAT02w wrapper.

func (*LMSCAT02w) HDRAt

func (p *LMSCAT02w) HDRAt(x, y int) hdrcolor.Color

HDRAt returns the pixel in LMS-space using CIE CAT02 matrix.

type LMSHPEw

type LMSHPEw struct {
	Image
}

A LMSHPEw wrapper hollows to get pixels in LMS-space using Hunt-Pointer-Estevez matrix. https://en.wikipedia.org/wiki/LMS_color_space

func NewLMSHPEw

func NewLMSHPEw(m Image) *LMSHPEw

NewLMSHPEw instanciates a new LMSHPE wrapper.

func (*LMSHPEw) HDRAt

func (p *LMSHPEw) HDRAt(x, y int) hdrcolor.Color

HDRAt returns the pixel in LMS-space using Hunt-Pointer-Estevez matrix.

type RGB

type RGB struct {
	// Pix holds the image's pixels, in R, G, B order. The pixel at
	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
	Pix []float32
	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
	Stride int
	// Rect is the image's bounds.
	Rect image.Rectangle
}

RGB is an in-memory 32 bits floating points image whose At method returns hdrcolor.RGB values.

func NewRGB

func NewRGB(r image.Rectangle) *RGB

NewRGB returns a new HDR RGB image with the given bounds.

func (*RGB) At

func (p *RGB) At(x, y int) color.Color

At implements Image.

func (*RGB) Bounds

func (p *RGB) Bounds() image.Rectangle

Bounds implements Image.

func (*RGB) ColorModel

func (p *RGB) ColorModel() color.Model

ColorModel implements Image.

func (*RGB) HDRAt

func (p *RGB) HDRAt(x, y int) hdrcolor.Color

HDRAt implements Image.

func (*RGB) PixOffset

func (p *RGB) PixOffset(x, y int) int

PixOffset returns the index of the first element of Pix that corresponds to the pixel at (x, y).

func (*RGB) RGBAt

func (p *RGB) RGBAt(x, y int) hdrcolor.RGB

RGBAt returns the RGB color at this coordinate.

func (*RGB) Set

func (p *RGB) Set(x, y int, c color.Color)

Set adds pixel to Image at given x, y.

func (*RGB) SetRGB

func (p *RGB) SetRGB(x, y int, c hdrcolor.RGB)

SetRGB applies the given RGB color at this coordinate.

func (*RGB) Size

func (p *RGB) Size() int

Size implements Image.

type RGB64

type RGB64 struct {
	// Pix holds the image's pixels, in R, G, B order. The pixel at
	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
	Pix []float64
	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
	Stride int
	// Rect is the image's bounds.
	Rect image.Rectangle
}

RGB64 is an in-memory 64 bits floating points image whose At method returns hdrcolor.RGB values.

func NewRGB64

func NewRGB64(r image.Rectangle) *RGB64

NewRGB64 returns a new HDR RGB image with the given bounds.

func (*RGB64) At

func (p *RGB64) At(x, y int) color.Color

At implements Image.

func (*RGB64) Bounds

func (p *RGB64) Bounds() image.Rectangle

Bounds implements Image.

func (*RGB64) ColorModel

func (p *RGB64) ColorModel() color.Model

ColorModel implements Image.

func (*RGB64) HDRAt

func (p *RGB64) HDRAt(x, y int) hdrcolor.Color

HDRAt implements Image.

func (*RGB64) PixOffset

func (p *RGB64) PixOffset(x, y int) int

PixOffset returns the index of the first element of Pix that corresponds to the pixel at (x, y).

func (*RGB64) RGBAt

func (p *RGB64) RGBAt(x, y int) hdrcolor.RGB

RGBAt returns the RGB color at this coordinate.

func (*RGB64) Set

func (p *RGB64) Set(x, y int, c color.Color)

Set adds pixel to Image at given x, y.

func (*RGB64) SetRGB

func (p *RGB64) SetRGB(x, y int, c hdrcolor.RGB)

SetRGB applies the given RGB color at this coordinate.

func (*RGB64) Size

func (p *RGB64) Size() int

Size implements Image.

type XYZ

type XYZ struct {
	// Pix holds the image's pixels, in X, Y and Z order. The pixel at
	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
	Pix []float32
	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
	Stride int
	// Rect is the image's bounds.
	Rect image.Rectangle
}

XYZ is an in-memory 32 bits floating points image whose At method returns hdrcolor.XYZ values.

func NewXYZ

func NewXYZ(r image.Rectangle) *XYZ

NewXYZ returns a new HDR RGB image with the given bounds.

func (*XYZ) At

func (p *XYZ) At(x, y int) color.Color

At implements Image.

func (*XYZ) Bounds

func (p *XYZ) Bounds() image.Rectangle

Bounds implements Image.

func (*XYZ) ColorModel

func (p *XYZ) ColorModel() color.Model

ColorModel implements Image.

func (*XYZ) HDRAt

func (p *XYZ) HDRAt(x, y int) hdrcolor.Color

HDRAt implements Image.

func (*XYZ) PixOffset

func (p *XYZ) PixOffset(x, y int) int

PixOffset returns the index of the first element of Pix that corresponds to the pixel at (x, y).

func (*XYZ) Set

func (p *XYZ) Set(x, y int, c color.Color)

Set adds pixel to Image at given x, y.

func (*XYZ) SetXYZ

func (p *XYZ) SetXYZ(x, y int, c hdrcolor.XYZ)

SetXYZ applies the given XYZ color at this coordinate.

func (*XYZ) Size

func (p *XYZ) Size() int

Size implements Image.

func (*XYZ) XYZAt

func (p *XYZ) XYZAt(x, y int) hdrcolor.XYZ

XYZAt returns the XYZ color at this coordinate.

type XYZ64

type XYZ64 struct {
	// Pix holds the image's pixels, in X, Y and Z order. The pixel at
	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
	Pix []float64
	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
	Stride int
	// Rect is the image's bounds.
	Rect image.Rectangle
}

XYZ64 is an in-memory 64 bits floating points image whose At method returns hdrcolor.XYZ values.

func NewXYZ64

func NewXYZ64(r image.Rectangle) *XYZ64

NewXYZ64 returns a new HDR RGB image with the given bounds.

func (*XYZ64) At

func (p *XYZ64) At(x, y int) color.Color

At implements Image.

func (*XYZ64) Bounds

func (p *XYZ64) Bounds() image.Rectangle

Bounds implements Image.

func (*XYZ64) ColorModel

func (p *XYZ64) ColorModel() color.Model

ColorModel implements Image.

func (*XYZ64) HDRAt

func (p *XYZ64) HDRAt(x, y int) hdrcolor.Color

HDRAt implements Image.

func (*XYZ64) PixOffset

func (p *XYZ64) PixOffset(x, y int) int

PixOffset returns the index of the first element of Pix that corresponds to the pixel at (x, y).

func (*XYZ64) Set

func (p *XYZ64) Set(x, y int, c color.Color)

Set adds pixel to Image at given x, y.

func (*XYZ64) SetXYZ

func (p *XYZ64) SetXYZ(x, y int, c hdrcolor.XYZ)

SetXYZ applies the given XYZ color at this coordinate.

func (*XYZ64) Size

func (p *XYZ64) Size() int

Size implements Image.

func (*XYZ64) XYZAt

func (p *XYZ64) XYZAt(x, y int) hdrcolor.XYZ

XYZAt returns the XYZ color at this coordinate.

Directories

Path Synopsis
codec
hli
pfm

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL