Grayscale image: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|REXX}}: added whitespace, changed a glyph.)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(33 intermediate revisions by 17 users not shown)
Line 1:
{{task|Image processing}}[[Category:Raster graphics operations]]
 
Many image processing algorithms are defined for [[wp:Grayscale|grayscale]] (or else monochromatic) images.
Line 15:
When using floating-point arithmetic make sure that rounding errors would not cause run-time problems or else distorted results when calculated luminance is stored as an unsigned integer.
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">T Colour
Byte r, g, b
 
F (r, g, b)
.r = r
.g = g
.b = b
 
F ==(other)
R .r == other.r & .g == other.g & .b == other.b
 
V black = Colour(0, 0, 0)
V white = Colour(255, 255, 255)
 
T Bitmap
Int width, height
Colour background
[[Colour]] map
 
F (width = 40, height = 40, background = white)
assert(width > 0 & height > 0)
.width = width
.height = height
.background = background
.map = (0 .< height).map(h -> (0 .< @width).map(w -> @@background))
 
F fillrect(x, y, width, height, colour = black)
assert(x >= 0 & y >= 0 & width > 0 & height > 0)
L(h) 0 .< height
L(w) 0 .< width
.map[y + h][x + w] = colour
 
F set(x, y, colour = black)
.map[y][x] = colour
 
F get(x, y)
R .map[y][x]
 
F togreyscale()
L(h) 0 .< .height
L(w) 0 .< .width
V (r, g, b) = .get(w, h)
V l = Int(0.2126 * r + 0.7152 * g + 0.0722 * b)
.set(w, h, Colour(l, l, l))
 
F writeppmp3()
V magic = "P3\n"
V comment = "# generated from Bitmap.writeppmp3\n"
V s = magic‘’comment‘’("#. #.\n#.\n".format(.width, .height, 255))
L(h) (.height - 1 .< -1).step(-1)
L(w) 0 .< .width
V (r, g, b) = .get(w, h)
s ‘’= ‘ #3 #3 #3’.format(r, g, b)
s ‘’= "\n"
R s
 
V bitmap = Bitmap(4, 4, white)
bitmap.fillrect(1, 0, 1, 2, Colour(127, 0, 63))
bitmap.set(3, 3, Colour(0, 127, 31))
print(‘Colour:’)
print(bitmap.writeppmp3())
print(‘Grey:’)
bitmap.togreyscale()
print(bitmap.writeppmp3())</syntaxhighlight>
 
{{out}}
<pre>
Colour:
P3
# generated from Bitmap.writeppmp3
4 4
255
255 255 255 255 255 255 255 255 255 0 127 31
255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 127 0 63 255 255 255 255 255 255
255 255 255 127 0 63 255 255 255 255 255 255
 
Grey:
P3
# generated from Bitmap.writeppmp3
4 4
255
254 254 254 254 254 254 254 254 254 93 93 93
254 254 254 254 254 254 254 254 254 254 254 254
254 254 254 31 31 31 254 254 254 254 254 254
254 254 254 31 31 31 254 254 254 254 254 254
</pre>
 
=={{header|Action!}}==
Part of the solution is available in [http://www.rosettacode.org/wiki/Category:Action!_Bitmap_tools#RGB2GRAY.ACT RGB2GRAY.ACT].
{{libheader|Action! Bitmap tools}}
{{libheader|Action! Tool Kit}}
<syntaxhighlight lang="action!">INCLUDE "H6:RGB2GRAY.ACT" ;from task Grayscale image
 
PROC PrintB3(BYTE x)
IF x<10 THEN
Print(" ")
ELSEIF x<100 THEN
Print(" ")
FI
PrintB(x)
RETURN
 
PROC PrintRgbImage(RgbImage POINTER img)
BYTE x,y
RGB c
 
FOR y=0 TO img.h-1
DO
FOR x=0 TO img.w-1
DO
GetRgbPixel(img,x,y,c)
Put(32)
PrintB3(c.r) Put(32)
PrintB3(c.g) Put(32)
PrintB3(c.b) Put(32)
OD
PutE()
OD
RETURN
 
PROC PrintGrayImage(GrayImage POINTER img)
BYTE x,y,c
 
FOR y=0 TO img.h-1
DO
FOR x=0 TO img.w-1
DO
c=GetGrayPixel(img,x,y)
Put(32)
PrintB3(c)
OD
PutE()
OD
RETURN
 
PROC Main()
BYTE ARRAY rgbdata=[
0 0 0 0 0 255 0 255 0
255 0 0 0 255 255 255 0 255
255 255 0 255 255 255 31 63 127
63 31 127 127 31 63 127 63 31]
BYTE ARRAY graydata(12)
BYTE width=[3],height=[4],LMARGIN=$52,oldLMARGIN
RgbImage rgbimg
GrayImage grayimg
 
oldLMARGIN=LMARGIN
LMARGIN=0 ;remove left margin on the screen
Put(125) PutE() ;clear the screen
InitRgbToGray()
InitRgbImage(rgbimg,width,height,rgbdata)
InitGrayImage(grayimg,width,height,graydata)
PrintE("Original RGB image:")
PrintRgbImage(rgbimg) PutE()
 
RgbToGray(rgbimg,grayimg)
PrintE("RGB to grayscale image:")
PrintGrayImage(grayimg) PutE()
 
GrayToRgb(grayimg,rgbimg)
PrintE("Grayscale to RGB image:")
PrintRgbImage(rgbimg)
 
LMARGIN=oldLMARGIN ;restore left margin on the screen
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Grayscale_image.png Screenshot from Atari 8-bit computer]
<pre>
Original RGB image:
0 0 0 0 0 255 0 255 0
255 0 0 0 255 255 255 0 255
255 255 0 255 255 255 31 63 127
63 31 127 127 31 63 127 63 31
 
RGB to grayscale image:
0 18 182
54 201 73
237 255 61
45 54 74
 
Grayscale to RGB image:
0 0 0 18 18 18 182 182 182
54 54 54 201 201 201 73 73 73
237 237 237 255 255 255 61 61 61
45 45 45 54 54 54 74 74 74
</pre>
 
=={{header|Ada}}==
<langsyntaxhighlight lang="ada">type Grayscale_Image is array (Positive range <>, Positive range <>) of Luminance;</langsyntaxhighlight>
Conversion to a grayscale image:
<langsyntaxhighlight lang="ada">function Grayscale (Picture : Image) return Grayscale_Image is
type Extended_Luminance is range 0..10_000_000;
Result : Grayscale_Image (Picture'Range (1), Picture'Range (2));
Line 38 ⟶ 230:
end loop;
return Result;
end Grayscale;</langsyntaxhighlight>
Conversion to a color image:
<langsyntaxhighlight lang="ada">function Color (Picture : Grayscale_Image) return Image is
Result : Image (Picture'Range (1), Picture'Range (2));
begin
Line 49 ⟶ 241:
end loop;
return Result;
end Color;</langsyntaxhighlight>
 
=={{header|ATS}}==
 
You will need <code>bitmap_task.sats</code> and <code>bitmap_task.dats</code> from [[Bitmap#ATS]].
 
===The ATS static file===
This file should be called <code>bitmap_grayscale_task.sats</code>.
<syntaxhighlight lang="ats">
#define ATS_PACKNAME "Rosetta_Code.bitmap_grayscale_task"
 
staload "bitmap_task.sats"
 
(*------------------------------------------------------------------*)
 
(* Here is a type for 8-bit grayscale pixels. It is analogous to the
rgb24 type defined in bitmap_task.sats. A gray8 is the size of a
uint8. (It is, in fact, a uint8, but here that fact is hidden, so
the ATS2 template and overload systems will know to treat gray8 as
a distinct type.) *)
abst@ype gray8 = uint8
 
fn {tk : tkind}
gray8_make_uint : g0uint tk -<> gray8
 
fn {tk : tkind}
gray8_make_int : g0int tk -<> gray8
 
fn {}
gray8_value : gray8 -<> uint8
 
overload gray8_make with gray8_make_uint
overload gray8_make with gray8_make_int
 
(*------------------------------------------------------------------*)
(* Pixel conversions. *)
 
fn {}
rgb24_to_gray8 : rgb24 -<> gray8 (* This is a lossy conversion. *)
 
fn {}
gray8_to_rgb24 : gray8 -<> rgb24
 
fn {}
rgb24_to_rgb24 : rgb24 -<> rgb24
 
fn {}
gray8_to_gray8 : gray8 -<> gray8
 
(*------------------------------------------------------------------*)
(* What follows is actually a general pixmap conversion mechanism,
not just one for conversions between gray8 and rgb24 pixels.
 
There are several ways to tell the function how to convert a
pixel. These methods include passing a function or any of the
different kinds of closure. However, instead I will do it with the
template system.
 
To wit: when calling pixmap_convert<a,b> one must have an
implementation of pixmap$pixel_convert<a,b> within the scope of the
call.
 
Note that pixmap_convert<a,a> can COPY a pixmap, although faster
implementations of copying may be possible. *)
 
fn {a, b : t@ype}
pixmap_convert_copy :
{w, h : int}
(!pixmap (a, w, h),
&array (b?, w * h) >> array (b, w * h)) ->
void
 
fn {a, b : t@ype}
pixmap_convert_alloc :
{w, h : int}
(!pixmap (a, w, h)) ->
[p : addr | null < p]
@(mfree_gc_v p | pixmap (b, w, h, p))
 
fn {a, b : t@ype}
pixmap$pixel_convert :
a -> b
 
overload pixmap_convert with pixmap_convert_copy
overload pixmap_convert with pixmap_convert_alloc
 
(*------------------------------------------------------------------*)
</syntaxhighlight>
 
===The ATS dynamic file===
This file should be called <code>bitmap_grayscale_task.dats</code>.
<syntaxhighlight lang="ats">
(*------------------------------------------------------------------*)
 
#define ATS_DYNLOADFLAG 0
#define ATS_PACKNAME "Rosetta_Code.bitmap_grayscale_task"
 
#include "share/atspre_staload.hats"
 
staload "bitmap_task.sats"
 
(* You need to staload bitmap_task.dats, so the ATS compiler will have
access to its implementations of templates. But we staload it
anonymously, so the programmer will not have access. *)
staload _ = "bitmap_task.dats"
 
staload "bitmap_grayscale_task.sats"
 
(*------------------------------------------------------------------*)
 
assume gray8 = uint8
 
implement {tk}
gray8_make_uint i =
let
(* Define some type conversions we are likely to want, but which
the prelude might not have implemented. (The ats2-xprelude
package will have these conversions, but I am avoiding
dependencies.) *)
 
extern castfn g0uint2uint_uint8_uint8 : uint8 -<> uint8
extern castfn g0uint2uint_uint_uint8 : uint -<> uint8
 
implement
g0uint2uint<uint8knd,uint8knd> i = g0uint2uint_uint8_uint8 i
 
implement
g0uint2uint<uintknd,uint8knd> i = g0uint2uint_uint_uint8 i
in
g0u2u i
end
 
implement {tk}
gray8_make_int i =
let
(* Define a type conversion we are likely to want, but which the
prelude might not have implemented. (The ats2-xprelude package
will have the conversion, but I am avoiding dependencies.) *)
 
extern castfn g0int2uint_int_uint8 : int -<> uint8
 
implement
g0int2uint<intknd,uint8knd> i = g0int2uint_int_uint8 i
in
g0i2u i
end
 
implement {}
gray8_value gray = gray
 
(*------------------------------------------------------------------*)
 
implement {}
rgb24_to_gray8 rgb =
(* There is no need for floating point here, although equivalent
integer calculations are a bit longer to write out. *)
let
extern castfn i2u32 : int -<> uint32
extern castfn u8_to_u32 : uint8 -<> uint32
extern castfn u32_to_u8 : uint32 -<> uint8
 
val @(r, g, b) = rgb24_values rgb
val r = u8_to_u32 r
and g = u8_to_u32 g
and b = u8_to_u32 b
 
val Y = (i2u32 2126 * r) + (i2u32 7152 * g) + (i2u32 722 * b)
val Y1 = Y / i2u32 10000
and Y0 = Y mod (i2u32 10000)
in
if Y0 < i2u32 5000 then
gray8_make (u32_to_u8 Y1)
else if i2u32 5000 < Y0 then
gray8_make (succ (u32_to_u8 Y1))
else if Y0 mod (i2u32 2) = i2u32 0 then
gray8_make (u32_to_u8 Y1)
else
gray8_make (succ (u32_to_u8 Y1))
end
 
implement {}
gray8_to_rgb24 gray =
rgb24_make @(gray, gray, gray)
 
implement {}
rgb24_to_rgb24 rgb = rgb
 
implement {}
gray8_to_gray8 gray = gray
 
(*------------------------------------------------------------------*)
 
implement {a, b}
pixmap_convert_copy {w, h} (pix_a, arr_b) =
let
val w : size_t w = width pix_a
and h : size_t h = height pix_a
prval () = lemma_g1uint_param w
prval () = lemma_g1uint_param h
in
if w = i2sz 0 then
let
prval () = mul_isfun (mul_make {w, h} (), mul_make {0, h} ())
prval () = view@ arr_b := array_v_unnil_nil{b?,b} (view@ arr_b)
in
end
else if h = i2sz 0 then
let
prval () = mul_isfun (mul_make {w, h} (), mul_make {w, 0} ())
prval () = view@ arr_b := array_v_unnil_nil{b?,b} (view@ arr_b)
in
end
else
let
stadef n = w * h
 
val n = w * h
prval () = mul_gte_gte_gte {w, h} ()
 
val p = addr@ arr_b
prval [p : addr] EQADDR () = eqaddr_make_ptr p
 
fun
loop {i : nat | i <= n}
.<i>.
(pf_b : !array_v (b?, p, i) >> array_v (b, p, i) |
pix_a : !pixmap (a, w, h),
i : size_t i)
: void =
if i = i2sz 0 then
let
prval () = pf_b := array_v_unnil_nil pf_b
in
end
else
let
val i1 = pred i
 
(* An exercise for a reader with nothing better to do:
write a proof that i1/w < h, so that the "mod h" can
be removed. It is there solely to provide a proof
that y < h. *)
val x = i1 mod w
and y = (i1 / w) mod h
 
prval @(pf_b1, pf_elt) = array_v_unextend pf_b
val elt = pixmap$pixel_convert<a,b> pix_a[x, y]
val () = ptr_set<b> (pf_elt | ptr_add<b> (p, i1), elt)
val () = loop (pf_b1 | pix_a, i1)
prval () = pf_b := array_v_extend (pf_b1, pf_elt)
in
end
in
loop (view@ arr_b | pix_a, n)
end
end
 
implement {a, b}
pixmap_convert_alloc {w, h} pix_a =
let
val w : size_t w = width pix_a
and h : size_t h = height pix_a
prval () = lemma_g1uint_param w
prval () = lemma_g1uint_param h
 
stadef n = w * h
val n = w * h
prval () = mul_gte_gte_gte {w, h} ()
 
val @(pf, pfgc | p) = array_ptr_alloc<b> n
val () = pixmap_convert<a,b> (pix_a, !p);
 
val pix_b = pixmap_make<b> (pf | w, h, p)
in
@(pfgc | pix_b)
end
 
(*------------------------------------------------------------------*)
(* Implementations of pixmap$pixel_convert for conversions between
gray8 and rgb24. The template system will inline these
implementations into the code. *)
 
implement
pixmap$pixel_convert<rgb24,gray8> rgb =
rgb24_to_gray8 rgb
 
implement
pixmap$pixel_convert<gray8,rgb24> gray =
gray8_to_rgb24 gray
 
implement
pixmap$pixel_convert<rgb24,rgb24> rgb =
rgb24_to_rgb24 rgb (* For using pixmap_convert to COPY a pixmap. *)
 
implement
pixmap$pixel_convert<gray8,gray8> gray =
gray8_to_gray8 gray (* For using pixmap_convert to COPY a pixmap. *)
 
(*------------------------------------------------------------------*)
(* Support for dump and load. The bytes will be written in a way
that is directly usable in PGM and PAM files. *)
 
typedef FILEstar = $extype"FILE *"
extern castfn FILEref2star : FILEref -<> FILEstar
 
implement
pixmap$pixels_dump<gray8> (outf, pixels, n) =
let
val num_written =
$extfcall (size_t, "fwrite", addr@ pixels, sizeof<gray8>, n,
FILEref2star outf)
in
num_written = n
end
 
implement
pixmap$pixels_load<gray8> (inpf, pixels, n, elt) =
let
prval [n : int] EQINT () = eqint_make_guint n
val num_read =
$extfcall (size_t, "fread", addr@ pixels, sizeof<gray8>, n,
FILEref2star inpf)
in
if num_read = n then
let
prval () = $UNSAFE.castvwtp2void{@[gray8][n]} pixels
in
true
end
else
begin
array_initize_elt<gray8> (pixels, n, elt);
false
end
end
 
(*------------------------------------------------------------------*)
 
#ifdef BITMAP_GRAYSCALE_TASK_TEST #then
 
implement
main0 () =
let
val failure_color = rgb24_make (255, 0, 0)
 
stadef w = 512
stadef h = 512
val w : size_t w = i2sz 512
and h : size_t h = i2sz 512
 
val @(pfgc1 | pix1) = pixmap_make<rgb24> (w, h)
val inpf = fileref_open_exn ("4.2.07.raw", file_mode_r)
val success = load<rgb24> (inpf, pix1, failure_color)
val () = fileref_close inpf
val- true = success
 
val @(pfgc2 | pix2) = pixmap_convert<rgb24,gray8> pix1
val @(pfgc3 | pix3) = pixmap_convert<gray8,rgb24> pix2
 
(* Write a Portable Pixel Map. *)
val outf = fileref_open_exn ("image-color.ppm", file_mode_w)
val () =
begin
fprintln! (outf, "P6");
fprintln! (outf, w, " ", h);
fprintln! (outf, "255");
ignoret (dump<rgb24> (outf, pix1))
end
val () = fileref_close outf
 
(* Write a Portable Gray Map. *)
val outf = fileref_open_exn ("image-gray.pgm", file_mode_w)
val () =
begin
fprintln! (outf, "P5");
fprintln! (outf, w, " ", h);
fprintln! (outf, "255");
ignoret (dump<gray8> (outf, pix2))
end
val () = fileref_close outf
 
(* Write a Portable Pixel Map. *)
val outf = fileref_open_exn ("image-gray.ppm", file_mode_w)
val () =
begin
fprintln! (outf, "P6");
fprintln! (outf, w, " ", h);
fprintln! (outf, "255");
ignoret (dump<rgb24> (outf, pix3))
end
val () = fileref_close outf
in
free (pfgc1 | pix1);
free (pfgc2 | pix2);
free (pfgc3 | pix3)
end
 
#endif
 
(*------------------------------------------------------------------*)
</syntaxhighlight>
 
There is a test program, which can be compiled and run as follows:
<pre>$ patscc -std=gnu2x -g -O2 -DATS_MEMALLOC_LIBC -DATS BITMAP_GRAYSCALE_TASK_TEST bitmap{,_grayscale}_task.{s,d}ats
$ ./a.out</pre>
 
It expects raw 24-bit color data in a file called <code>4.2.07.raw</code>. I have data from the SIPI test image "Peppers" in that file. Output will be three files, named <code>image-color.ppm</code>, <code>image-gray.pgm</code>, and <code>image-gray.ppm</code>. The first is "Peppers" as a PPM image, the second is the grayscale conversion as a PGM image, and the last is the grayscale conversion converted to a PPM image.
 
{{out}}
[[File:Bitmap grayscale task ATS color.jpg|thumb|none|alt=Bell peppers in different colors.]]
[[File:Bitmap grayscale task ATS gray.jpg|thumb|none|alt=Bell and other peppers in grayscale.]]
 
=={{header|BASIC256}}==
[[Image:BASIC256_greyscale_Mona_Lisa.jpg|right]]
[[Image:BASIC256_greysacle_Grey_Mona_lisa.jpg|right]]
<langsyntaxhighlight BASIC256lang="basic256">w = 143
h = 188
name$ = "Mona_Lisa.jpg"
Line 76 ⟶ 678:
next x
 
imgsave "Grey_"+name$,"jpg"</langsyntaxhighlight>
{{omit from|Batch File}}
 
Line 84 ⟶ 686:
[[Image:original_bbc.jpg|right]]
[[Image:greyscale_bbc.jpg|right]]
<langsyntaxhighlight lang="bbcbasic"> Width% = 200
Height% = 200
Line 112 ⟶ 714:
col% = TINT(x%*2,y%*2)
SWAP ?^col%,?(^col%+2)
= col%</langsyntaxhighlight>
 
=={{header|C}}==
Definition/interface for a grayscale image.
 
<langsyntaxhighlight lang="c">typedef unsigned char luminance;
typedef luminance pixel1[1];
typedef struct {
Line 128 ⟶ 730:
grayimage alloc_grayimg(unsigned int, unsigned int);
grayimage tograyscale(image);
image tocolor(grayimage);</langsyntaxhighlight>
 
The same as <tt>alloc_img</tt>, but for grayscale images.
 
<langsyntaxhighlight lang="c">grayimage alloc_grayimg(unsigned int width, unsigned int height)
{
grayimage img;
Line 140 ⟶ 742:
img->height = height;
return img;
}</langsyntaxhighlight>
 
Convert from ''color'' image to ''grayscale'' image.
 
<langsyntaxhighlight lang="c">grayimage tograyscale(image img)
{
unsigned int x, y;
Line 166 ⟶ 768:
}
return timg;
}</langsyntaxhighlight>
 
And back from a ''grayscale'' image to a ''color'' image.
 
<langsyntaxhighlight lang="c">image tocolor(grayimage img)
{
unsigned int x, y;
Line 191 ⟶ 793:
}
return timg;
}</langsyntaxhighlight>
 
'''Notes'''
* <tt>tocolor</tt> and <tt>tograyscale</tt> do not free the previous image, so it must be freed normally calling <tt>free_img</tt>. With a cast we can use the same function also for grayscale images, or we can define something like
 
<langsyntaxhighlight lang="c">#define free_grayimg(IMG) free_img((image)(IMG))</langsyntaxhighlight>
 
* ''Luminance'' is rounded. Since the C implementation is based on unsigned char (256 possible values per components), L can be at most 255.0 and rounding gives 255, as we expect. Changing the color_component type would only change 256, 255.0 and 255 values here written in something else, the code would work the same.
Line 202 ⟶ 804:
=={{header|C sharp|C#}}==
To convert TO grayscale:
<langsyntaxhighlight lang="csharp">
Bitmap tImage = new Bitmap("spectrum.bmp");
 
Line 219 ⟶ 821:
// Save
tImage.Save("spectrum2.bmp");
</syntaxhighlight>
</lang>
 
=={{header|Clojure|Clojure}}==
<langsyntaxhighlight lang="clojure">
(import '[java.io File]
'[javax.imageio ImageIO]
Line 261 ⟶ 863:
"test-gray-cloj.png"))
 
</syntaxhighlight>
</lang>
 
=={{header|Common Lisp}}==
 
Use the function rgb-to-gray-image to convert a rgb-image as loaded by the function defined [[Bitmap/Read a PPM file#Common Lisp]]. The package identifier assumes that you have the package as defined in [[Basic bitmap storage#Common Lisp]]. With the function grayscale-image-to-pgm-file it is possible to write out the gray image as pgm file which can then be further processed.
<langsyntaxhighlight lang="lisp">
(in-package #:rgb-pixel-buffer)
 
Line 291 ⟶ 893:
(export 'grayscale-image-to-pgm-file)
 
</syntaxhighlight>
</lang>
 
=={{header|Crystal}}==
{{trans|Ruby}}
Extending [[Basic_bitmap_storage#Crystal]]
<langsyntaxhighlight lang="ruby">class RGBColour
def to_grayscale
luminosity = (0.2126*@red + 0.7152*@green + 0.0722*@blue).to_i
Line 313 ⟶ 915:
gray
end
end</langsyntaxhighlight>
 
=={{header|D}}==
This example uses the bitmap module defined in the [[Bitmap]] Task page.
 
<langsyntaxhighlight lang="d">module grayscale_image;
 
import core.stdc.stdio, std.array, std.algorithm, std.string, std.ascii;
Line 434 ⟶ 1,036:
img2.rgb2grayImage.savePGM("quantum_frog_grey.pgm");
}
}</langsyntaxhighlight>
 
=={{header|Delphi}}==
Solution in this page [[https://rosettacode.org/wiki/Bitmap/Read_a_PPM_file#Delphi]]
 
=={{header|Erlang}}==
Line 440 ⟶ 1,045:
The code below extends the erlang module on [[Bitmap]] task. This module supports RGB and grayscale modes. RGB colors are specified as {rgb, R, G, B} and saved as bytes into an array. Grayscale colors are likewise specified as {gray, L} where L is luminance.
 
<langsyntaxhighlight lang="erlang">-module(ros_bitmap).
 
-export([new/2, fill/2, set_pixel/3, get_pixel/2, convert/2]).
Line 513 ⟶ 1,118:
convert(#bitmap{mode=Mode}=Bitmap, Mode) ->
Bitmap.
</syntaxhighlight>
</lang>
 
=={{header|Euler Math Toolbox}}==
 
<syntaxhighlight lang="text">
>A=loadrgb("mona.jpg");
>insrgb(A);
Line 527 ⟶ 1,132:
>insrgb(grayscale(A));
>insrgb(A|grayscale(A));
</syntaxhighlight>
</lang>
 
=={{header|Euphoria}}==
<langsyntaxhighlight lang="euphoria">function to_gray(sequence image)
sequence color
for i = 1 to length(image) do
Line 549 ⟶ 1,154:
end for
return image
end function</langsyntaxhighlight>
 
=={{header|Factor}}==
{{works with|Factor|0.99 2020-07-03}}
<syntaxhighlight lang="factor">USING: arrays kernel math math.matrices math.vectors ;
 
: rgb>gray ( matrix -- new-matrix )
[ { 0.2126 0.7152 0.0722 } vdot >integer ] matrix-map ;
 
: gray>rgb ( matrix -- new-matrix )
[ dup dup 3array ] matrix-map ;</syntaxhighlight>
 
=={{header|FBSL}}==
24-bpp BMP-format P.O.T.-size image solution:
[[Image:FBSLLena.png|right]]
<langsyntaxhighlight lang="qbasic">DIM colored = ".\LenaClr.bmp", grayscale = ".\LenaGry.bmp"
DIM head, tail, r, g, b, l, ptr, blobsize = 54 ' sizeof BMP file headers
 
Line 568 ⟶ 1,183:
NEXT
 
FILEPUT(FILEOPEN(grayscale, BINARY_NEW), FILEGET): FILECLOSE(FILEOPEN) ' save buffer</langsyntaxhighlight>
 
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">\ grayscale bitmap (without word-alignment for scan lines)
 
\ bdim, bwidth, bdata all work with graymaps
Line 626 ⟶ 1,241:
over i j rot b!
loop
loop nip ;</langsyntaxhighlight>
 
=={{header|Fortran}}==
Line 634 ⟶ 1,249:
First let's define a new type; the <tt>sc</tt> stands for Single Channel, which can be luminance (as it is here).
 
<langsyntaxhighlight lang="fortran">type scimage
integer, dimension(:,:), pointer :: channel
integer :: width, height
end type scimage</langsyntaxhighlight>
 
In order to allow proper overloading, the following subroutines of the [[Basic bitmap storage#Fortran|storage]] should be renamed appending the <tt>_rgb</tt> suffix: valid_image, inside_image, alloc_img, free_img, fill_img, get_pixel, put_pixel, init_img. The ''single channel'' version would be named with the <tt>_sc</tt> suffix, then we should define the proper interfaces to use the already written code as before. Here there are only the interfaces and subroutines needed for the task.
 
<langsyntaxhighlight lang="fortran">interface alloc_img
module procedure alloc_img_rgb, alloc_img_sc
end interface
Line 647 ⟶ 1,262:
interface free_img
module procedure free_img_rgb, free_img_sc
end interface</langsyntaxhighlight>
 
Now we can define useful interfaces and subroutines more task-related:
 
<langsyntaxhighlight lang="fortran">interface assignment(=)
module procedure rgbtosc, sctorgb
end interface</langsyntaxhighlight>
 
<langsyntaxhighlight lang="fortran">subroutine alloc_img_sc(img, w, h)
type(scimage) :: img
integer, intent(in) :: w, h
Line 699 ⟶ 1,314:
end if
 
end subroutine sctorgb</langsyntaxhighlight>
 
'''Usage example''' (fragment) which can be used to convert from ''rgb'' image to ''grayscale'' image and back (since we only can output the ''rgb'' kind):
 
<langsyntaxhighlight lang="fortran">type(scimage) :: gray
type(rgbimage) :: animage
! ... here we "load" or create animage
Line 711 ⟶ 1,326:
gray = animage
animage = gray
call output_ppm(an_unit, animage)</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
{{trans|BASIC256}}
<syntaxhighlight lang="freebasic">Dim As Integer ancho = 143, alto = 188, x, y, p, red, green, blue, luminancia
Dim As String imagen = "Mona_Lisa.bmp"
Screenres ancho,alto,32
Bload imagen
 
For x = 0 To ancho-1
For y = 0 To alto-1
p = Point(x,y)
red = p Mod 256
p = p \ 256
green = p Mod 256
p = p \ 256
blue = p Mod 256
luminancia = 0.2126*red + 0.7152*green + 0.0722*blue
Pset(x,y), Rgb(luminancia,luminancia,luminancia)
Next y
Next x
 
Bsave "Grey_"+imagen+".bmp",0
Sleep</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de BASIC256
</pre>
 
=={{header|FutureBasic}}==
There are several ways to handle grayscaling images in FB. Here's a function that accepts any of a variety of color images — JPEG, TIFF, PNG, BMP, GIF, etc. — and converts them to grayscale. The function uses a convenient build-in Core Image filter to generate the optimized grayscale image. This code compiles as a standalone application featuring a window with two image views, one showing the original color image, and the other with the converted grayscale image. The app uses a relatively square color image of flowers. It proportionately resizes the image to fit the left hand image view, and displays the converted image in the right hand view.
 
Resource: [[Media:Flowersfb.jpg]]
 
<syntaxhighlight lang="text">include resources "Flowersfb.jpg"
 
_window = 1
begin enum output 1
_imageviewColor
_imageviewGray
end enum
 
void local fn BuildWindow
CGRect r = fn CGRectMake( 0, 0, 580, 300 )
window _window, @"Color to Grayscale", r
r = fn CGRectMake( 20, 20, 260, 260 )
imageview _imageviewColor, YES, @"Flowersfb.jpg", r, NSImageScaleAxesIndependently, NSImageAlignCenter, NSImageFramePhoto
r = fn CGRectMake( 300, 20, 260, 260 )
imageview _imageviewGray, YES, @"Flowersfb.jpg", r, NSImageScaleAxesIndependently, NSImageAlignCenter, NSImageFramePhoto
end fn
 
local fn GrayscaleImage( image as ImageRef ) as ImageRef
CGSize size = fn ImageSize( image )
CGRect bounds = fn CGRectMake( 0, 0, size.width, size.height )
ImageRef finalImage = fn ImageWithSize( size )
CFDataRef dta = fn ImageTIFFRepresentationUsingCompression( image, NSTIFFCompressionNone, 0.0 )
CIImageRef inputImage = fn CIImageWithData( dta )
ImageLockFocus( finalImage )
CIFilterRef filter = fn CIFilterWithNameAndInputParameters( @"CIPhotoEffectMono", @{kCIInputImageKey:inputImage} )
CIImageRef outputCIImage = fn CIFilterOutputImage( filter )
CIImageDrawAtPoint( outputCIImage, CGPointZero, bounds, NSCompositeCopy, 1.0 )
ImageUnlockFocus( finalImage )
end fn = finalImage
 
fn BuildWindow
 
ImageRef colorFlowers
ImageRef grayflowers
 
colorFlowers = fn ImageNamed( @"Flowersfb.jpg" )
grayflowers = fn GrayscaleImage( colorFlowers )
ImageViewSetImage( _imageviewGray, grayFlowers )
 
HandleEvents</syntaxhighlight>
{{output}}
[[File:Color to Grayscale.png]]
 
=={{header|Fōrmulæ}}==
 
In [{{FormulaeEntry|page=https://wiki.formulae.org/?script=examples/Grayscale_image this] page you can see the solution of this task.}}
 
'''Solution'''
 
Note the use of the dot product in the calculation of the gray level.
 
[[File:Fōrmulæ - Grayscale image 01.png]]
 
'''Test case'''
 
[[File:Fōrmulæ - Grayscale image 02.png]]
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text ([http://wiki.formulae.org/Editing_F%C5%8Drmul%C3%A6_expressions more info]). Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation &mdash;i.e. XML, JSON&mdash; they are intended for transportation effects more than visualization and edition.
 
[[File:Fōrmulæ - Grayscale image 03.png]]
The option to show Fōrmulæ programs and their results is showing images. Unfortunately images cannot be uploaded in Rosetta Code.
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package raster
 
import (
Line 821 ⟶ 1,522:
}
return b
}</langsyntaxhighlight>
For demonstration program see task [[Bitmap/Read a PPM file]].
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">module Bitmap.Gray(module Bitmap.Gray) where
 
import Bitmap
Line 842 ⟶ 1,543:
 
toGrayImage :: Color c => Image s c -> ST s (Image s Gray)
toGrayImage = mapImage $ Gray . luminance</langsyntaxhighlight>
 
A <tt>Gray</tt> image can be converted to an <tt>RGB</tt> image with <tt>Bitmap.RGB.toRGBImage</tt>, defined [[Basic bitmap storage|here]].
Line 852 ⟶ 1,553:
Grayscale image is stored as two-dimensional array of luminance values. Allowed luminance scale is the same as for the color bitmap; the functions below are neutral to scale.
 
<langsyntaxhighlight lang="j">NB. converts the image to grayscale according to formula
NB. L = 0.2126*R + 0.7152*G + 0.0722*B
toGray=: [: <. +/ .*"1&0.2126 0.7152 0.0722
 
NB. converts grayscale image to the color image, with all channels equal
toColor=: 3 & $"0</langsyntaxhighlight>
 
Example:
 
<syntaxhighlight lang ="j">viewRGB toColor toGray myimg</langsyntaxhighlight>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">void convertToGrayscale(final BufferedImage image){
for(int i=0; i<image.getWidth(); i++){
for(int j=0; j<image.getHeight(); j++){
Line 887 ⟶ 1,588:
}
}
</syntaxhighlight>
</lang>
 
=={{header|JavaScript}}==
HTML 5
Demonstration: https://repl.it/repls/NiceFaroffRockrat
<syntaxhighlight lang="javascript">
<lang JavaScript>
function toGray(img) {
let cnv = document.getElementById("canvas");
Line 916 ⟶ 1,617:
return cnv.toDataURL();
}
</syntaxhighlight>
</lang>
 
=={{header|Julia}}==
'''Adhering to the Task Description'''
<syntaxhighlight lang="julia">
<lang Julia>
using Color, Images, FixedPointNumbers
 
Line 941 ⟶ 1,642:
imc = gray2rgb(imb)
imwrite(imc, "grayscale_image_rc.png")
</syntaxhighlight>
</lang>
Rounding errors are unlikely to be an issue for <code>rgb2gray</code>. The calculation of <code>g</code> promotes it to the literal float type (typically <code>Float64</code>).
 
'''A More Idiomatic Approach'''
<syntaxhighlight lang="julia">
<lang Julia>
using Color, Images, FixedPointNumbers
 
Line 951 ⟶ 1,652:
imb = convert(Image{Gray{Ufixed8}}, ima)
imwrite(imb, "grayscale_image_julia.png")
</syntaxhighlight>
</lang>
 
{{output}}
Line 964 ⟶ 1,665:
 
As it's not possible to recover the original colored image (because different combinations of RGB values could have produced the same luminance), I have not bothered with the reverse operation.
<langsyntaxhighlight lang="scala">// version 1.2.10
 
import java.io.File
Line 990 ⟶ 1,691:
val grayFile = File("bbc_gray.jpg")
ImageIO.write(image, "jpg", grayFile)
}</langsyntaxhighlight>
 
{{out}}
Line 998 ⟶ 1,699:
 
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
<lang lb>
nomainwin
WindowWidth = 400
Line 1,020 ⟶ 1,721:
wait
[q] unloadbmp "clr":close #1:end
</syntaxhighlight>
</lang>
 
=={{header|Lingo}}==
<langsyntaxhighlight lang="lingo">on rgbToGrayscaleImageFast (img)
res = image(img.width, img.height, 8)
res.paletteRef = #grayScale
Line 1,041 ⟶ 1,742:
end repeat
return res
end</langsyntaxhighlight>
 
=={{header|Lua}}==
 
<langsyntaxhighlight lang="lua">function ConvertToGrayscaleImage( bitmap )
local size_x, size_y = #bitmap, #bitmap[1]
local gray_im = {}
Line 1,070 ⟶ 1,771:
return bitmap
end</langsyntaxhighlight>
 
=={{header|M2000 Interpreter}}==
<syntaxhighlight lang="m2000 interpreter">
Module P6P5 {
Function Bitmap {
def x as long, y as long, Import as boolean, P5 as boolean
If match("NN") then {
Read x, y
} else.if Match("N") Then {
\\ is a file?
Read f as long
buffer whitespace as byte
if not Eof(f) then {
get #f, whitespace :P6$=eval$(whitespace)
get #f, whitespace : P6$+=eval$(whitespace)
def boolean getW=true, getH=true, getV=true
def long v
\\ str$("P6") has 2 bytes. "P6" has 4 bytes
P5=p6$=str$("P5")
If p6$=str$("P6") or P5 Then {
do {
get #f, whitespace
if Eval$(whitespace)=str$("#") then {
do {get #f, whitespace} until eval(whitespace)=10
} else {
select case eval(whitespace)
case 32, 9, 13, 10
{ if getW and x<>0 then {
getW=false
} else.if getH and y<>0 then {
getH=false
} else.if getV and v<>0 then {
getV=false
}
}
case 48 to 57
{if getW then {
x*=10
x+=eval(whitespace, 0)-48
} else.if getH then {
y*=10
y+=eval(whitespace, 0)-48
} else.if getV then {
v*=10
v+=eval(whitespace, 0)-48
}
}
End Select
}
iF eof(f) then Error "Not a ppm file"
} until getV=false
} else Error "Not a P6 ppm or P5 ppm file"
Import=True
}
} else Error "No proper arguments"
if x<1 or y<1 then Error "Wrong dimensions"
structure rgb {
red as byte
green as byte
blue as byte
}
m=len(rgb)*x mod 4
if m>0 then m=4-m ' add some bytes to raster line
m+=len(rgb) *x
Structure rasterline {
{
pad as byte*m
}
hline as rgb*x
}
Structure Raster {
magic as integer*4
w as integer*4
h as integer*4
{
linesB as byte*len(rasterline)*y
}
lines as rasterline*y
}
Buffer Clear Image1 as Raster
Return Image1, 0!magic:="cDIB", 0!w:=Hex$(x,2), 0!h:=Hex$(y, 2)
if not Import then Return Image1, 0!lines:=Str$(String$(chrcode$(255), Len(rasterline)*y))
Buffer Clear Pad as Byte*4
SetPixel=Lambda Image1, Pad,aLines=Len(Raster)-Len(Rasterline), blines=-Len(Rasterline) (x, y, c) ->{
where=alines+3*x+blines*y
if c>0 then c=color(c)
c-!
Return Pad, 0:=c as long
Return Image1, 0!where:=Eval(Pad, 2) as byte, 0!where+1:=Eval(Pad, 1) as byte, 0!where+2:=Eval(Pad, 0) as byte
}
GetPixel=Lambda Image1,aLines=Len(Raster)-Len(Rasterline), blines=-Len(Rasterline) (x,y) ->{
where=alines+3*x+blines*y
=color(Eval(image1, where+2 as byte), Eval(image1, where+1 as byte), Eval(image1, where as byte))
}
GetPixelGray=Lambda Image1,aLines=Len(Raster)-Len(Rasterline), blines=-Len(Rasterline) (x,y) ->{
where=alines+3*x+blines*y
grayval=round(0.2126*Eval(image1, where+2 as byte) + 0.7152*Eval(image1, where+1 as byte) + 0.0722*Eval(image1, where as byte), 0)
=color(grayval,grayval,grayval)
}
StrDib$=Lambda$ Image1, Raster -> {
=Eval$(Image1, 0, Len(Raster))
}
CopyImage=Lambda Image1 (image$) -> {
if left$(image$,12)=Eval$(Image1, 0, 24 ) Then {
Return Image1, 0:=Image$
} Else Error "Can't Copy Image"
}
Export2File=Lambda Image1, x, y (f) -> {
Print #f, "P6";chr$(10);"# Created using M2000 Interpreter";chr$(10);
Print #f, x;" ";y;" 255";chr$(10);
x2=x-1 : where=0 : rasterline=x*3
m=rasterline mod 4 : if m<>0 then rasterline+=4-m
Buffer pad as byte*3
For y1=y-1 to 0 {
where=rasterline*y1
For x1=0 to x2 {
Return pad, 0:=eval$(image1, 0!linesB!where, 3)
Push Eval(pad, 2) : Return pad, 2:=Eval(pad, 0), 0:=Number
Put #f, pad : where+=3
}
}
}
Export2FileGray=Lambda Image1, x, y (f) -> {
Print #f, "P5";chr$(10);"# Created using M2000 Interpreter";chr$(10);
Print #f, x;" ";y;" 255";chr$(10);
x2=x-1 : where=0 : rasterline=x*3
m=rasterline mod 4 : if m<>0 then rasterline+=4-m
Buffer pad as byte*3
Buffer bytepad as byte
const R=0.2126, G=0.7152, B=0.0722
For y1=y-1 to 0 {
where=rasterline*y1
For x1=0 to x2 {
Return pad, 0:=eval$(image1, 0!linesB!where, 3)
Return bytepad, 0:=round(R*Eval(pad, 2) + G*Eval(pad, 1) + B*Eval(pad, 0), 0)
Put #f, bytepad : where+=3
}
}
}
if Import then {
x0=x-1 : where=0
Buffer Pad1 as byte*3
Buffer Pad2 as byte
local rasterline=x*3
m=rasterline mod 4 : if m<>0 then rasterline+=4-m
For y1=y-1 to 0 {
where=rasterline*y1
For x1=0 to x0 {
if p5 then
Get #f, Pad2: m=eval(Pad2,0) : Return pad1, 0:=m, 1:=m, 2:=m
else
Get #f, Pad1 : Push Eval(pad1, 2) : Return pad1, 2:=Eval(pad1, 0), 0:=Number
End if
Return Image1, 0!linesB!where:=Eval$(Pad1) : where+=3
}
}
}
Group Bitmap {
SetPixel=SetPixel
GetPixel=GetPixel
Image$=StrDib$
Copy=CopyImage
ToFile=Export2File
ToFileGray=Export2FileGray
GetPixelGray=GetPixelGray
}
=Bitmap
}
Cls 5,0
A=Bitmap(15,10)
B=Bitmap(15,10)
c1=color(100, 200, 255)
c2=color(180, 250, 128)
For i=0 to 8
Call A.SetPixel(i, i, c1)
Call A.SetPixel(9, i,c2)
Next
Call A.SetPixel(i,i,c1)
// make a new one GrayScale (but 24bit) as B
For i=0 to 14 { For J=0 to 9 {Call B.SetPixel(i, j, A.GetPixelGray(i,j))}}
// place image A at 200 pixel from left margin, 100 pixel from top margin
Copy 200*twipsX, 100*twipsY use A.Image$(), 0, 400 ' zoom 400%, angle 0
// place image B at 400 pixel from left margin, 100 pixel from top margin
Copy 400*twipsX, 100*twipsY use B.Image$(), 0, 400 ' zoom 400%
Try {
Open "P6example.ppm" For Output as #f
Call A.Tofile(f)
Close #f
Open "P5example.ppm" For Output as #f
Call A.TofileGray(f)
Close #f
Open "P5example.ppm" For Input as #f
C=Bitmap(f)
close #f
Copy 600*twipsX, 100*twipsY use C.Image$(), 0, 400 ' zoom 400%
Open "P6example.ppm" For Input as #f
C=Bitmap(f)
close #f
// use of Top clause to make the border color transparent at rotation
Copy 800*twipsX, 100*twipsY top C.Image$(), 30, 400 ' zoom 400%, angle 30 degree
}
Print "Done"
}
P6P5
</syntaxhighlight>
[[File:Grayscale.png|thumb|alt=M2000 Console Output|M2000 Console Output]]
 
 
=={{header|Maple}}==
Maple has builtin command for conversion from RGB to Grayscale image: ImageTools:-ToGrayScale, which uses gray = 0.30 red + 0.59 green + 0.11 blue, the following implementation uses the CIE formula. Note that the conversion back from GrayScale to RGB uses Maple's builtin command: ImageTools:-ToRGB.
<langsyntaxhighlight Maplelang="maple">with(ImageTools):
#conversion forward
dimensions:=[upperbound(img)];
Line 1,089 ⟶ 1,997:
ToRGB(x);
#display the result
Embed(x);</langsyntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
Mathematica has a built-in grayscale conversion function called "ColorConvert". This example does not use it since it appears the luminance calculation is different from the CIE spec. Grayscale to RGB "conversion" just changes the single channel grayscale image to a triple channel image.
<langsyntaxhighlight Mathematicalang="mathematica">toGrayscale[rgb_Image] := ImageApply[#.{0.2126, 0.7152, 0.0722}&, rgb]
toFakeRGB[L_Image] := ImageApply[{#, #, #}&, L] </langsyntaxhighlight>
 
=={{header|MATLAB}}==
Built in colour to grayscale converter uses the following forumula:
0.2989*R + 0.5870*G + 0.1140*B
<langsyntaxhighlight Matlablang="matlab">function [grayImage] = colortograyscale(inputImage)
grayImage = rgb2gray(inputImage);</langsyntaxhighlight>
 
=={{header|MiniScript}}==
This GUI implementation is for use with [http://miniscript.org/MiniMicro Mini Micro].
<syntaxhighlight lang="miniscript">
greyedColor = function(colr)
clist = color.toList(colr)
lum = [0.2126, 0.7152, 0.0722]
red = clist[0] * lum[0]
green = clist[1] * lum[1]
blue = clist[2] * lum[2]
grey = red + green + blue
return color.fromList([grey, grey, grey, clist[3]])
end function
 
toGreyScale = function(img)
greyImg = Image.create(img.width, img.height)
for x in range(0, img.width - 1)
for y in range(0, img.height - 1)
greyed = greyedColor(img.pixel(x, y))
greyImg.setPixel x, y, greyed
end for
end for
return greyImg
end function
 
clear
 
// The turtle and color wheel images are included with MiniMicro
turtle = file.loadImage("/sys/pics/animals/turtle.png")
greyTurtle = toGreyScale(turtle)
gfx.drawImage turtle, 0, 0
gfx.drawImage greyTurtle, turtle.width, 0
 
colorWheel = file.loadImage("/sys/pics/ColorWheel.png")
greyWheel = toGreyScale(colorWheel)
gfx.drawImage colorWheel, 0, 320
gfx.drawImage greyWheel, greyWheel.width, 320
</syntaxhighlight>
 
=={{header|Nim}}==
The right way to proceed would have been to add the case of gray scale images to our Image type (using a “variant object” with a discriminator). But we didn’t want to change the Image type, so we have created a GrayImage type and duplicated most procedures.
 
<syntaxhighlight lang="nim">
import bitmap
import lenientops
 
type
 
GrayImage* = object
w*, h*: Index
pixels*: seq[Luminance]
 
proc newGrayImage*(width, height: int): GrayImage =
## Create a gray image with given width and height.
new(result)
result.w = width
result.h = height
result.pixels.setLen(width * height)
 
iterator indices*(img: GrayImage): Point =
## Yield the pixels coordinates as tuples.
for y in 0 ..< img.h:
for x in 0 ..< img.w:
yield (x, y)
 
proc `[]`*(img: GrayImage; x, y: int): Luminance =
## Get a pixel luminance value.
img.pixels[y * img.w + x]
 
proc `[]=`*(img: GrayImage; x, y: int; lum: Luminance) =
## Set a pixel luminance to given value.
img.pixels[y * img.w + x] = lum
 
proc fill*(img: GrayImage; lum: Luminance) =
## Set the pixels to a given luminance.
for x, y in img.indices:
img[x, y] = lum
 
func toGrayLuminance(color: Color): Luminance =
## Compute the luminance from RGB value.
Luminance(0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b + 0.5)
 
func toGrayImage*(img: Image): GrayImage =
##
result = newGrayImage(img.w, img.h)
for pt in img.indices:
result[pt.x, pt.y] = img[pt.x, pt.y].toGrayLuminance()
 
func toImage*(img: GrayImage): Image =
result = newImage(img.w, img.h)
for pt in img.indices:
let lum = img[pt.x, pt.y]
result[pt.x, pt.y] = (lum, lum, lum)
 
#———————————————————————————————————————————————————————————————————————————————————————————————————
 
when isMainModule:
 
import ppm_write
 
# Create a RGB image.
var image = newImage(100, 50)
image.fill(color(128, 128, 128))
for row in 10..20:
for col in 0..<image.w:
image[col, row] = color(0, 255, 0)
for row in 30..40:
for col in 0..<image.w:
image[col, row] = color(0, 0, 255)
 
# Convert it to grayscale.
var grayImage = image.toGrayImage()
 
# Convert it back to RGB in order to save it in PPM format using the available procedure.
var convertedImage = grayImage.toImage()
convertedImage.writePPM("output_gray.ppm")</syntaxhighlight>
 
=={{header|OCaml}}==
 
Conversion to a grayscale image:
<langsyntaxhighlight lang="ocaml">let to_grayscale ~img:(_, r_channel, g_channel, b_channel) =
let width = Bigarray.Array2.dim1 r_channel
and height = Bigarray.Array2.dim2 r_channel in
Line 1,124 ⟶ 2,149:
done;
done;
(gray_channel)</langsyntaxhighlight>
 
Conversion to a color image:
<langsyntaxhighlight lang="ocaml">let to_color ~img:gray_channel =
let width = Bigarray.Array2.dim1 gray_channel
and height = Bigarray.Array2.dim2 gray_channel in
Line 1,146 ⟶ 2,171:
r_channel,
g_channel,
b_channel)</langsyntaxhighlight>
 
and functions to get/set a pixel:
 
<langsyntaxhighlight lang="ocaml">let gray_get_pixel_unsafe (gray_channel) =
(fun x y -> gray_channel.{x,y})
 
let gray_put_pixel_unsafe (gray_channel) v =
(fun x y -> gray_channel.{x,y} <- v)</langsyntaxhighlight>
 
=={{header|Octave}}==
Line 1,160 ⟶ 2,185:
'''Use package''': image
 
<langsyntaxhighlight lang="octave">function [grayImage] = colortograyscale(inputImage)
grayImage = rgb2gray(inputImage);</langsyntaxhighlight>
 
Differently from [[Grayscale image#MATLAB|MATLAB]], the grayscale is computed as mean of the three RGB values. Changing this non-optimal behaviour is a matter of fixing three lines in the <tt>rgb2gray.m</tt> file; since it's a GPL-ed code, here it is a semplified version (error checking, usage help, argument checking removed)
 
<langsyntaxhighlight lang="octave">function gray = rgb2gray (rgb)
switch(class(rgb))
case "double"
Line 1,178 ⟶ 2,203:
function lum = luminance(rgb)
lum = 0.2126*rgb(:,:,1) + 0.7152*rgb(:,:,2) + 0.0722*rgb(:,:,3);
endfunction</langsyntaxhighlight>
 
Original code of the <tt>rgb2gray.m</tt> in the image package version 1.0.8 is by Kai Habel (under the GNU General Public License)
Line 1,185 ⟶ 2,210:
We define a "graymap" as a two-dimensional array of floats. In module <code>"Grayscale.oz"</code>, we implement conversion functions from and to bitmaps:
 
<langsyntaxhighlight lang="oz">functor
import
Array2D
Line 1,211 ⟶ 2,236:
color(L L L)
end
end</langsyntaxhighlight>
 
=={{header|Perl}}==
Line 1,219 ⟶ 2,244:
Since we are using Imlib2, this one '''does''' '''not''' implement really a gray-scale (single channel) storage; it only ''converts'' an RGB image to an RGB image with the same three colour components for each pixel (which result in a gray-scale-like image)
 
<langsyntaxhighlight lang="perl">#! /usr/bin/perl
 
use strict;
Line 1,245 ⟶ 2,270:
$gscale->save("Lennagray.jpg");
 
exit 0;</langsyntaxhighlight>
 
=={{header|Phix}}==
{{Trans|Euphoria}}
Requires read_ppm() from [[Bitmap/Read_a_PPM_file#Phix|Read_a_PPM_fileRead a PPM file]], seeand write_ppm() from [[Bitmap/Write_a_PPM_file#Phix|Write_a_PPM_file]]Write fora actualPPM usefile]].
Included<syntaxhighlight aslang="phix">-- demo\rosetta\Bitmap_Greyscale.exw (runnable version)
 
<lang Phix>function to_gray(sequence image)
function to_grey(sequence colorimage)
forinteger dimx i=1 to length(image) do,
for j=1 to dimy = length(image[i1]) do
for x=1 to dimx do
-- unpack color triple
for y=1 to dimy do
color = sq_div(sq_and_bits(image[i][j], {#FF0000,#FF00,#FF}),
integer pixel = image[x][y] -- {#010000red,#0100green,#01})blue
sequence r_g_b = sq_and_bits(pixel,{#FF0000,#FF00,#FF})
image[i][j] = floor(0.2126*color[1] + 0.7152*color[2] + 0.0722*color[3])*#010101
integer {r,g,b} = sq_floor_div(r_g_b,{#010000,#0100,#01})
image[x][y] = floor(0.2126*r + 0.7152*g + 0.0722*b)*#010101
end for
end for
return image
end function
 
--include ppm.e -- read_ppm(), write_ppm(), to_grey() (as distributed, instead of the above)
 
sequence img = read_ppm("Lena.ppm")
img = to_grayto_grey(img)</lang>
write_ppm("LenaGray.ppm",img)</syntaxhighlight>
 
=={{header|PHP}}==
Uses the [[Write ppm file#PHP|Bitmap class]] defined for writing a PPM file
<langsyntaxhighlight PHPlang="php">class BitmapGrayscale extends Bitmap {
public function toGrayscale(){
for ($i = 0; $i < $this->h; $i++){
Line 1,289 ⟶ 2,319:
$b->setPixel(0, 13, array(0,0,255));
$b->toGrayscale();
$b->writeP6('p6-grayscale.ppm');</langsyntaxhighlight>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp"># Convert color image (PPM) to greyscale image (PGM)
(de ppm->pgm (Ppm)
(mapcar
Line 1,314 ⟶ 2,344:
'((G) (list G G G))
Y ) )
Pgm ) )</langsyntaxhighlight>
<langsyntaxhighlight PicoLisplang="picolisp"># Write greyscale image (PGM) to file
(de pgmWrite (Pgm File)
(out File
Line 1,340 ⟶ 2,370:
 
# Convert to color image and write to .ppm file
(ppmWrite (pgm->ppm *Pgm) "img.ppm")</langsyntaxhighlight>
 
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">
<lang PL/I>
do j = 1 to hbound(image,1);
do i = 0 to hbound(image,2);
Line 1,355 ⟶ 2,385:
end;
end;
</syntaxhighlight>
</lang>
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">Procedure ImageGrayout(image)
Protected w, h, x, y, r, g, b, gray, color
Line 1,392 ⟶ 2,422:
Next
StopDrawing()
EndProcedure</langsyntaxhighlight>
 
=={{header|Python}}==
Line 1,398 ⟶ 2,428:
 
Extending the example given [[Basic_bitmap_storage#Alternative_version|here]]
<langsyntaxhighlight lang="python"># String masquerading as ppm file (version P3)
import io
ppmfileout = io.StringIO('')
Line 1,450 ⟶ 2,480:
254 254 254 31 31 31 254 254 254 254 254 254
 
'''</langsyntaxhighlight>
 
=={{header|R}}==
{{libheader|pixmap}}
<langsyntaxhighlight lang="r"># Conversion from Grey to RGB uses the following code
setAs("pixmapGrey", "pixmapRGB",
function(from, to){
Line 1,486 ⟶ 2,516:
 
# Convert back to "colour"
plot(p3 <- as(p2, "pixmapRGB"))</langsyntaxhighlight>
 
=={{header|Racket}}==
Line 1,493 ⟶ 2,523:
I gave up on uploading to Rosetta Code.
 
<langsyntaxhighlight lang="racket">
#lang racket
(require racket/draw)
Line 1,535 ⟶ 2,565:
(color->gray rosetta)
(gray->color (color->gray rosetta))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 1,541 ⟶ 2,571:
 
This script expects to be fed a P6 .ppm file name at the command line. It will convert it to grey scale and save it as a binary portable grey map (P5 .pgm) file.
<syntaxhighlight lang="raku" perl6line>sub MAIN ($filename = 'default.ppm') {
 
my $in = open($filename, :r, :enc<iso-8859-1>) or die $in;
Line 1,554 ⟶ 2,584:
for $in.lines.ords -> $r, $g, $b {
my $gs = $r * 0.2126 + $g * 0.7152 + $b * 0.0722;
$out.print: chr($gs.floor min 255);
}
 
$in.close;
$out.close;
}</langsyntaxhighlight>
Using the .ppm file from the [[Bitmap/Write a PPM file#Raku|Write a PPM file]] task:
 
Line 1,567 ⟶ 2,597:
Note: &nbsp; REXX uses decimal (characters) instead of binary for storing numbers, &nbsp; so there is no rounding &nbsp; (using
<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;characters to store numbers is almost the same as using decimal floating point).
<langsyntaxhighlight lang="rexx">/*REXX program converts a RGB (red─green─blue) image into a grayscale/greyscale image.*/
blue= '00 00 ff'x /*define the blue color (hexadecimal).*/
@.= blue /*set the entire image to blue color.*/
Line 1,582 ⟶ 2,612:
end /*row*/ /* [↑] D2C convert decimal ───► char*/
end /*col*/ /* [↑] x%1 is the same as TRUNC(x) */
/*stick a fork in it, we're all done. */</langsyntaxhighlight><br><br>
 
=={{header|Ruby}}==
Extending [[Basic_bitmap_storage#Ruby]]
<langsyntaxhighlight lang="ruby">class RGBColour
def to_grayscale
luminosity = Integer(0.2126*@red + 0.7152*@green + 0.0722*@blue)
Line 1,603 ⟶ 2,633:
gray
end
end</langsyntaxhighlight>
 
=={{header|Scala}}==
Uses the [[Basic_bitmap_storage#Scala|Scala Basic Bitmap Storage]] class.
<langsyntaxhighlight lang="scala">object BitmapOps {
def luminosity(c:Color)=(0.2126*c.getRed + 0.7152*c.getGreen + 0.0722*c.getBlue+0.5).toInt
 
Line 1,616 ⟶ 2,646:
image
}
}</langsyntaxhighlight>
 
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">require('Image::Imlib2')
 
func tograyscale(img) {
Line 1,638 ⟶ 2,668:
var gscale = tograyscale(image)
gscale.set_quality(80)
gscale.save(output)</langsyntaxhighlight>
 
=={{header|Tcl}}==
<!-- L = 0.2126·R + 0.7152·G + 0.0722·B -->
{{libheader|Tk}}
<langsyntaxhighlight lang="tcl">package require Tk
 
proc grayscale image {
Line 1,655 ⟶ 2,685:
}
}
}</langsyntaxhighlight>
Photo images are always 8-bits-per-channel RGBA.
 
=={{header|Vedit macro language}}==
Conversion to a grayscale image.<br>
<langsyntaxhighlight lang="vedit">// Convert RGB image to grayscale (8 bit/pixel)
// #10 = buffer that contains image data
// On return:
Line 1,680 ⟶ 2,710:
Buf_Switch(#10)
}
Return</langsyntaxhighlight>
 
Conversion to a color image.<br>
<langsyntaxhighlight lang="vedit">// Convert grayscale image (8 bits/pixel) into RGB (24 bits/pixel)
// #20 = buffer that contains image data
// On return:
Line 1,702 ⟶ 2,732:
Buf_Switch(#20)
}
Return</langsyntaxhighlight>
 
=={{header|Visual Basic}}==
{{works with|Visual Basic|5}}
{{works with|Visual Basic|6}}
{{libheader|Win32}}
<syntaxhighlight lang="vb">Option Explicit
 
Private Type BITMAP
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
 
Private Type RGB
Red As Byte
Green As Byte
Blue As Byte
Alpha As Byte
End Type
 
Private Type RGBColor
Color As Long
End Type
 
Public Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Public Declare Function GetObjectA Lib "gdi32.dll" (ByVal hObject As Long, ByVal nCount As Long, ByRef lpObject As Any) As Long
Public Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal hObject As Long) As Long
Public Declare Function GetPixel Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Public Declare Function SetPixel Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long) As Long
Public Declare Function DeleteDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
 
 
Sub Main()
Dim p As stdole.IPictureDisp
Dim hdc As Long
Dim bmp As BITMAP
Dim i As Long, x As Long, y As Long
Dim tRGB As RGB, cRGB As RGBColor
 
Set p = VB.LoadPicture("T:\TestData\Input_Colored.bmp")
GetObjectA p.Handle, Len(bmp), bmp
 
hdc = CreateCompatibleDC(0)
SelectObject hdc, p.Handle
 
For x = 0 To bmp.bmWidth - 1
For y = 0 To bmp.bmHeight - 1
cRGB.Color = GetPixel(hdc, x, y)
LSet tRGB = cRGB
i = (0.2126 * tRGB.Red + 0.7152 * tRGB.Green + 0.0722 * tRGB.Blue)
SetPixel hdc, x, y, RGB(i, i, i)
Next y
Next x
 
VB.SavePicture p, "T:\TestData\Output_GrayScale.bmp"
DeleteDC hdc
 
End Sub</syntaxhighlight>
 
=={{header|Visual Basic .NET}}==
Line 1,708 ⟶ 2,800:
Convert a Bitmap to Grayscale.
 
<langsyntaxhighlight lang="vbnet">
Imports System.Drawing.Imaging
 
Line 1,765 ⟶ 2,857:
Map.UnlockBits(oBMPData)
 
End Sub</langsyntaxhighlight>
 
=={{header|Wren}}==
{{libheader|DOME}}
This script converts the image [https://rosettacode.org/File:Lenna100.jpg Lenna100.jpg] to grayscale and then displays the two images side by side.
<syntaxhighlight lang="wren">import "graphics" for Canvas, Color, ImageData
import "dome" for Window
 
class PercentageDifference {
construct new(width, height, image1, image2) {
Window.title = "Grayscale Image"
Window.resize(width, height)
Canvas.resize(width, height)
_image1 = image1
_image2 = image2
_img1 = ImageData.loadFromFile(image1)
_img2 = ImageData.create(image2, _img1.width, _img1.height)
}
 
init() {
toGrayScale()
// display images side by side
_img1.draw(0, 0)
_img2.draw(550, 0)
Canvas.print(_image1, 200, 525, Color.white)
Canvas.print(_image2, 750, 525, Color.white)
}
 
toGrayScale() {
for (x in 0..._img1.width) {
for (y in 0..._img1.height) {
var c1 = _img1.pget(x, y)
var lumin = (0.2126 * c1.r + 0.7152 * c1.g + 0.0722 * c1.b).floor
var c2 = Color.rgb(lumin, lumin,lumin, c1.a)
_img2.pset(x, y, c2)
}
}
}
 
update() {}
 
draw(alpha) {}
}
 
var Game = PercentageDifference.new(1100, 550, "Lenna100.jpg", "Lenna-grayscale.jpg")</syntaxhighlight>
 
=={{header|Yabasic}}==
{{trans|BASIC256}}
"image" is a library created by Hermang Mansilla for import and show .BMP files. http://www.oocities.org/sunsetstrip/palms/1624/yabasic/libs/IMAGE.TXT
<langsyntaxhighlight Yabasiclang="yabasic">import image
 
open window 600,600
Line 1,789 ⟶ 2,925:
dot x+300,y+300
next y
next x</langsyntaxhighlight>
 
=={{header|zkl}}==
Line 1,798 ⟶ 2,934:
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
{{trans|BASIC256}}
<langsyntaxhighlight lang="zkl">fcn toGrayScale(img){ // in-place conversion
foreach x,y in (img.w,img.h){
r,g,b:=img[x,y].toBigEndian(3);
Line 1,804 ⟶ 2,940:
img[x,y]=((lum*256) + lum)*256 + lum;
}
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">img:=PPM.readPPMFile("lena.ppm");
toGrayScale(img);
img.write(File("foo.ppm","wb"));</langsyntaxhighlight>
{{out}}
http://www.zenkinetic.com/Images/RosettaCode/lenaGray.jpg
9,476

edits