(String: {%- set hs_blog_post_body -%} {%- set in_blog_post_body = true -%} <span id="hs_cos_wrapper_post_body" class="hs_cos_wrapper hs_cos_wrapper_meta_field hs_cos_wrapper_type_rich_text" style="" data-hs-cos-general-type="meta_field" data-hs-cos-type="rich_text"><p><span id="hs_cos_wrapper_post_body" data-hs-cos-general-type="meta_field" data-hs-cos-type="rich_text">This post is the continuation of <a href="https://www.netguru.com/blog/vector-operations-in-go">Vector Operations in Go</a> which originally appeared on After Eight Coding.</span></p></span>)

Creating Images in Go

Photo of Szymon Szeliga

Szymon Szeliga

Updated Feb 21, 2024 • 6 min read
Produced image

This post is the continuation of Vector Operations in Go which originally appeared on After Eight Coding.

Foreword

Before moving forward with implementing a camera model, it would be good to have some sort of debugging tool. When writing a ray tracer, that tool is a rendered image.

Go has a built-in image package that allows creating images easily and saving them as files on the disk.

The code for this post can be viewed here.

Design

The scene will be represented by a struct. Internally, it will store the width and height of the desired image along with a pointer to an instance of image.RGBA.

[code]

Initialisation

In order to initialise the scene, we need to initialise the image.RGBA with the given dimensions. In Go, this is done by creating an image.Rect struct and passing it to the image.NewRGBA function.

The whole code required to initialise the scene will be done in the NewScene function. The function should accept two integers as arguments that represent the width and height of the image:

[code]

The assert library exposes some nifty helper functions like ObjectsAreEqualValues, which does a deep equality check of an object’s values.

Test Helpers

In order to test the following functions, I needed to write two helper functions to generate a new image.RGBA and fill the image with a random colour:

[code]

I use these helpers to generate expected image.RGBA objects for ObjectsAreEqualValues.

Traversing the Image

For each pixel of the image, I want to set a specific color. This can be done simply enough by a double for loop, but we can expose a convenience function on Scene, called EachPixel. Go allows us to specify functions as arguments for other functions. We will leverage this fact by requiring a single argument in EachPixel — a function with the following signature func(int, int) color.RGBA. The two int values are the x and y coordinates of the image (which will be used later on for calculating a pixel in the image plane). The full implementation of EachPixel function looks like this:

[code]

The setPixel function is just an adapter for Go’s built-in image.RGBA.Set.

Saving the Image

Finally, I want to save the image to a PNG file. As one might suspect, Go provides such a function in the image/png package, called png.Encode. Again, I’ve built an adapter for this function that takes a filename under which it should save the image.

[code]

Several interesting things happen in this code:

  • os.Create(filename) — the function has multiple returns; this is a common pattern for error handling in Go:
    • f — the file descriptor,
    • err — any error that may have happened during the file creation, for example insufficient privileges;
  • defer f.Close() — the defer keyword delays execution of the passed code until the surrounding function returns; in this case, the file won’t close until the Save function finishes executing its commands;
  • assert.Panics — another nice feature of the assert library, instead of taking expected/actual values of the assertion, it takes a function that is supposed to panic (raise an exception), if the function does panic, it passes the test; this is similar to RSpec’s expect { subject }.to raise_error StandardError;

Putting It All Together

Here’s a simple main function that fills the image with values based on the current pixel:

[code]

This code produces the following image:

image.png

That’s all regarding creating and saving images in Go. Next up, a basic camera model, stay tuned.

Photo of Szymon Szeliga

More posts by this author

Szymon Szeliga

A problem solver who graduated the Wroclaw University of Technology. Loves black coffee, listens to...
How to build products fast?  We've just answered the question in our Digital Acceleration Editorial  Sign up to get access

We're Netguru!

At Netguru we specialize in designing, building, shipping and scaling beautiful, usable products with blazing-fast efficiency
Let's talk business!

Trusted by: