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.
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.
Let's work with image files by executing the following steps:
arsd.png
.readPng
, passing it a filename. Be sure that the file is already in the PNG format.getAsTrueColorImage
function to convert the input from whatever PNG format it was saved as into an RGBA array.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:
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.
3.142.255.140