Working with image files

Reading and writing image files is a way to present visualized results to the user and is also a starting point to write out images to a web browser or GUI window. Here, we'll use my color.d and png.d or bmp.d modules to load an image file, convert it to grayscale, and then write it out to a new file.

Getting ready

Download color.d and either png.d or bmp.d from my Github repository and put them in your project's directory. In the example, we'll use png.d. Neither module requires any additional D or C libraries.

How to do it…

Let's work with image files by executing the following steps:

  1. Import arsd.png.
  2. Load the file with readPng, passing it a filename. Be sure that the file is already in the PNG format.
  3. Use the getAsTrueColorImage function to convert the input from whatever PNG format it was saved as into an RGBA array.
  4. Manipulate the pixels. Here, we'll convert to greyscale with a simple average-of-components algorithm.
  5. Write the new image out to a file with writePng.

The code is as follows:

import arsd.png;
void main() {
        auto image = readPng("test.png").getAsTrueColorImage();
        foreach(ref pixel; image.imageData.colors) {
                int average = (pixel.r + pixel.g + pixel.b) / 3;
                pixel.r = pixel.g = pixel.b = cast(ubyte) average;
        }
        writePng("test-bw.png", image);
}

The following image shows test.png after the conversion:

How to do it…

Tip

The bmp.d module works the same way as png.d; however, the functions are named readBmp and writeBmp instead of Png.

How it works…

The modules we dealt with in this recipe implement the file formats independently and provide a simple pixel buffer interface to the image.

The implementation of png.d builds on top of the lazy file input ranges Phobos provides to give a lazy input range of PNG data. This implementation was tricky because the Phobos byChunk range provides a fixed number of bytes, whereas the PNG file format is made out of a stream of variable sized bytes. To bridge the gap, I wrote a BufferedInputRange object with additional consume methods which manage variable sized chunks.

Underneath the readPng and writePng convenience functions, png.d offers both low- and mid-level access to the PNG data structures. The low-level functions provide access to the individual chunks that make up the file, the precise pixel format stored in the file, the palette, and so on. The mid-level functions provide input ranges of PNG file chunks and RgbaScanlines. The range of RgbaScanlines offers a potential hook to use the image data with std.algorithm and other lazy generic transformation functions.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.255.140