Grayscale image: Difference between revisions

Rewritten D entry
(Added BBC BASIC)
(Rewritten D entry)
Line 214:
 
=={{header|D}}==
This example uses the bitmap module defined in the [[Bitmap]] Task page.
 
<lang d>module grayscale_image;
This example uses Bitmap template as defined on [[Basic bitmap storage]] problem page.
 
import core.stdc.stdio, std.array, std.algorithm, std.string, std.ascii;
public import bitmap;
 
<lang D>struct LuminGray {
ubyte[1] valuec;
voidenum opCall(ubyteblack l)= { value[Gray(0] = l); }
enum white = Gray(255);
void opCall(ubyte[1] v) { value[] = v[]; }
alias this = c;
ubyte l() { return value[0]; }
}
 
alias Bitmap!(Lumin) GrayBitmap;
 
Image!Color loadPGM(Color)(ref Image!Color img, in string fileName) {
GrayBitmap rgbToGray(RgbBitmap bitmap) {
static int readNum(FILE* f) nothrow {
auto gb = GrayBitmap(bitmap.width, bitmap.height);
int x, y int n;
foreach while (ref!fscanf(f, "%d elem;", gb&n)) {
elem if (bitmap[x,(n y].lumAVG= fgetc(f);) == '#') {
if (++x == bitmap.width) { x while ((n = 0;fgetc(f)) y++;!= }'\n')
if (n == EOF)
return 0;
} else
return 0;
}
return n;
}
 
return gb;
scope(exit) if (fin) fclose(fin);
if (img is null)
img = new Image!Color();
 
auto fin = fopen(fileName.toStringz(), "rb");
if (!fin)
throw new Exception("Can't open input file.");
 
if (fgetc(fin) != 'P' ||
fgetc(fin) != '5' ||
!isWhite(fgetc(fin)))
throw new Exception("Not a PGM (PPM P5) image.");
 
immutable int nc = readNum(fin);
immutable int nr = readNum(fin);
immutable int maxVal = readNum(fin);
if (nc <= 0 || nr <= 0 || maxVal <= 0)
throw new Exception("Wrong input image sizes.");
img.allocate(nc, nr);
auto pix = new ubyte[img.image.length];
 
immutable count = fread(pix.ptr, 1, nc * nr, fin);
if (count != nc * nr)
throw new Exception("Wrong number of items read.");
 
pix.copy(img.image);
return img;
}
 
RgbBitmap grayToRgb(GrayBitmap gray) {
auto rgb = RgbBitmap(gray.width, gray.height);
int x, y;
foreach (ref elem; rgb) {
elem(gray[x, y].l);
if (++x == gray.width) { x = 0; y++; }
}
return rgb;
}</lang>
 
void savePGM(Color)(in Image!Color img, in string fileName)
in {
assert(img !is null);
assert(!fileName.empty);
assert(img.nx > 0 && img.ny > 0 &&
img.image.length == img.nx * img.ny,
"Wrong image.");
} body {
auto fout = fopen(fileName.toStringz(), "wb");
if (fout == null)
throw new Exception("File can't be opened.");
fprintf(fout, "P5\n%d %d\n255\n", img.nx, img.ny);
auto pix = new ubyte[img.image.length];
foreach (i, ref p; pix)
p = cast(typeof(pix[0]))img.image[i];
immutable count = fwrite(pix.ptr, ubyte.sizeof,
img.nx * img.ny, fout);
if (count != img.nx * img.ny)
new Exception("Wrong number of items written.");
fclose(fout);
}
 
Adding the following opCall methods to Lumin and Rgb structs
would allow to create simple conversion function template instead of two separate functions.
<lang D>//in Rgb struct:
void opCall(Rgb v) { value[] = v.value[]; }
//in Lumin struct:
void opCall(Lumin l) { value[] = l.value[]; }</lang>
 
Gray lumCIE(in RGB c) pure nothrow {
Conversion function template:
return Gray(cast(ubyte)(0.2126 * c.r +
<lang D>Bitmap!(TO) convert(FR, TO)(Bitmap!(FR) source, TO delegate(FR) dg) {
0.7152 * c.g +
auto dest = Bitmap!(TO)(source.width, source.height);
0.0722 * c.b + 0.5));
int x, y;
}
foreach (ref elem; dest) {
 
elem( dg(source[x, y]) );
Gray lumAVG(in RGB c) pure nothrow {
if (++x == source.width) { x = 0; y++; }
return Gray(cast(ubyte)(0.3333 * c.r +
0.3333 * c.g +
0.3333 * c.b + 0.5));
}
 
Image!Gray rgb2grayImage(alias Conv=lumCIE)(in Image!RGB im) {
auto result = new typeof(return)(im.nx, im.ny);
foreach (i, immutable rgb; im.image)
result.image[i] = Conv(rgb);
return result;
}
 
Image!RGB gray2rgbImage(in Image!Gray im) {
auto result = new typeof(return)(im.nx, im.ny);
foreach (i, immutable gr; im.image)
result.image[i] = RGB(gr, gr, gr);
return result;
}
 
version (grayscale_image_main) {
void main() {
auto im1 = new Image!Gray();
im1.loadPGM("lena.pgm");
gray2rgbImage(im1).savePPM6("lena_rgb.ppm");
 
auto img2 = new Image!RGB();
img2.loadPPM6("quantum_frog.ppm");
img2.rgb2grayImage().savePGM("quantum_frog_grey.pgm");
}
return dest;
}</lang>
 
Sample usage of conversion function:
<lang D>// assuming t0 is of RgbBitmap type..
// convert RgbBitmap to GrayBitmap
auto t1 = convert(t0, delegate Lumin(Rgb v) { Lumin res; res(cast(ubyte)(0.2126*v.r + 0.7152*v.g + 0.0722*v.b)); return res; } );
// convert Graybitmap to grayscale - RgbBitmap
auto t2 = convert(t1, delegate Rgb(Lumin v) { Rgb res; res(v.l); return res; });</lang>
 
=={{header|Euphoria}}==