Bitmap/Histogram: Difference between revisions
m
→{{header|Wren}}: ImageData.loadFromFile now deprecated, changed to ImageData.load
(Added Wren) |
m (→{{header|Wren}}: ImageData.loadFromFile now deprecated, changed to ImageData.load) |
||
(8 intermediate revisions by 5 users not shown) | |||
Line 11:
* Replace each pixel of luminance lesser than the median to black, and others to white.
Use [[read ppm file | read]]/[[write ppm file]], and [[grayscale image]] solutions.
=={{header|Action!}}==
In the following solution the input file [https://gitlab.com/amarok8bit/action-rosetta-code/-/blob/master/source/lena30g.PPM lena30g.PPM] is loaded from H6 drive. Altirra emulator automatically converts CR/LF character from ASCII into 155 character in ATASCII charset used by Atari 8-bit computer when one from H6-H10 hard drive under DOS 2.5 is used.
{{libheader|Action! Bitmap tools}}
<syntaxhighlight lang="action!">INCLUDE "H6:LOADPPM5.ACT"
DEFINE HISTSIZE="256"
PROC PutBigPixel(INT x,y BYTE col)
IF x>=0 AND x<=79 AND y>=0 AND y<=47 THEN
y==LSH 2
col==RSH 4
IF col<0 THEN col=0
ELSEIF col>15 THEN col=15 FI
Color=col
Plot(x,y)
DrawTo(x,y+3)
FI
RETURN
PROC DrawImage(GrayImage POINTER image INT x,y)
INT i,j
BYTE c
FOR j=0 TO image.gh-1
DO
FOR i=0 TO image.gw-1
DO
c=GetGrayPixel(image,i,j)
PutBigPixel(x+i,y+j,c)
OD
OD
RETURN
PROC CalcHistogram(GrayImage POINTER image INT ARRAY hist)
INT i,j
BYTE c
Zero(hist,HISTSIZE*2)
FOR j=0 TO image.gh-1
DO
FOR i=0 TO image.gw-1
DO
c=GetGrayPixel(image,i,j)
hist(c)==+1
OD
OD
RETURN
BYTE FUNC CalcThresholdValue(INT width,height INT ARRAY hist)
INT i,sum,total,curr
total=width*height
sum=0
FOR i=0 TO HISTSIZE-1
DO
curr=hist(i)
IF sum>=(total-curr)/2 THEN
RETURN (i)
FI
sum==+curr
OD
RETURN (HISTSIZE-1)
PROC Binarize(GrayImage POINTER src,dst BYTE threshold)
INT i,j
BYTE c
FOR j=0 TO src.gh-1
DO
FOR i=0 TO src.gw-1
DO
c=GetGrayPixel(src,i,j)
IF c<threshold THEN
c=0
ELSE
c=255
FI
SetGrayPixel(dst,i,j,c)
OD
OD
RETURN
PROC Main()
BYTE CH=$02FC ;Internal hardware value for last key pressed
BYTE ARRAY dataIn(900),dataOut(900)
GrayImage in,out
INT ARRAY hist(HISTSIZE)
BYTE threshold
INT size=[30],x,y
Put(125) PutE() ;clear the screen
InitGrayImage(in,size,size,dataIn)
InitGrayImage(out,size,size,dataOut)
PrintE("Loading source image...")
LoadPPM5(in,"H6:LENA30G.PPM")
PrintE("Calc histogram...")
CalcHistogram(in,hist)
PrintE("Calc threshold value...")
threshold=CalcThresholdValue(in.gw,in.gh,hist)
PrintE("Binarization...")
Binarize(in,out,threshold)
Graphics(9)
x=(40-size)/2
y=(48-size)/2
DrawImage(in,x,y)
DrawImage(out,x+40,y)
DO UNTIL CH#$FF OD
CH=$FF
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Bitmap_Histogram.png Screenshot from Atari 8-bit computer]
=={{header|Ada}}==
Histogram of an image:
<
type Histogram is array (Luminance) of Pixel_Count;
Line 30 ⟶ 143:
end loop;
return Result;
end Get_Histogram;</
Median of a histogram:
<
From : Luminance := Luminance'First;
To : Luminance := Luminance'Last;
Line 48 ⟶ 161:
end loop;
return From;
end Median;</
Conversion of an image to black and white art:
<
begin
Open (F1, In_File, "city.ppm");
Line 71 ⟶ 184:
Put_PPM (F2, X);
end;
Close (F2);</
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
[[Image:greyscale_bbc.jpg|right]]
[[Image:histogram_bbc.gif|right]]
<
Sort% = FN_sortinit(0,0)
Line 135 ⟶ 247:
col% = TINT(x%*2,y%*2)
SWAP ?^col%,?(^col%+2)
= col%</
=={{header|C}}==
<
typedef histogram_t *histogram;
Line 145 ⟶ 256:
histogram get_histogram(grayimage im);
luminance histogram_median(histogram h);</
<
{
histogram t;
Line 166 ⟶ 277:
}
return t;
}</
The given <tt>histogram</tt> must be freed with a simple <tt>free(histogram)</tt>.
Line 172 ⟶ 283:
{{trans|Ada}}
<
{
luminance From, To;
Line 190 ⟶ 301:
}
return From;
}</
An example of usage is the following code.
<
#include <stdlib.h>
#include "imglib.h"
Line 243 ⟶ 354:
free_img((image)g_img);
free_img(color_img);
}</
Which reads from the file specified from the command line and outputs to the standard out the PPM B/W version of the input image. The input image can be of any format handled by ImageMagick (see [[Read image file through a pipe]])
=={{header|Common Lisp}}==
{{libheader|opticl}}
<
(:use #:cl
#:opticl))
Line 294 ⟶ 404:
(let* ((image (read-jpeg-file "lenna.jpg"))
(bw-image (gray->black&white-image (color->gray-image image))))
(write-pbm-file "lenna-bw.pbm" bw-image)))</
=={{header|D}}==
{{trans|Ada}}
It uses the grayscale_image from the Grayscale image Task. The loaded frog image is from the Color quantization Task.
<
Color findSingleChannelMedian(Color)(in Image!Color img)
Line 345 ⟶ 454:
img.binarizeInPlace(img.findSingleChannelMedian())
.savePGM("quantum_frog_bin.pgm");
}</
=={{header|FBSL}}==
FBSL volatiles and function call concatenation used heavily for brevity.
Line 352 ⟶ 460:
'''24-bpp P.O.T.-size BMP solution:'''
[[File:FBSLHistogram.PNG|right]]
<
DIM colored = ".\LenaClr.bmp", grayscale = ".\LenaGry.bmp", blackwhite = ".\LenaBnw.bmp"
Line 401 ⟶ 509:
NEXT
FILEPUT(FILEOPEN(blackwhite, BINARY_NEW), FILEGET): FILECLOSE(FILEOPEN) ' save b/w image
END SUB</
=={{header|Forth}}==
<
over 256 cells erase
dup bdim * over bdata + swap bdata
do 1 over i c@ cells + +! loop drop ;</
\ will not work as far as bdim bdata are not ans forth words
\ do not forget to assign them yourself in your code
=={{header|GnuForth 0.7}}==
<syntaxhighlight lang="forth">
: bar ( v y x -- )
2dup at-xy .\" [" 100 spaces .\" ]" swap 1 + swap at-xy 0
DO .\" #"
LOOP
cr ;
: demo \ just demo to show it working in percentage 1% to 4%
5 1
DO i 10 i bar
LOOP
cr ;
\ will display :
[# ]
[## ]
[### ]
[#### ]
</syntaxhighlight>
Call it from an array
0 toto swap cells + @ 10 5 bar \ draws bar from first item of toto array
=={{header|Fortran}}==
Line 414 ⟶ 544:
'''Note''': ''luminance'' range is hard-encoded and is from 0 to 255. This could be enhanced.
<
use RCImageBasic
implicit none
Line 453 ⟶ 583:
end function histogram_median
end module RCImageProcess</
Example:
<
use RCImageBasic
use RCImageIO
Line 498 ⟶ 628:
call free_img(gray)
end program BasicImageTests</
=={{header|Go}}==
Histogram and Threshold functions are be added to the Grmap type for this task:
<
import "math"
Line 525 ⟶ 654:
}
}
}</
Demonstration program computes the median:
<
// Files required to build supporting package raster are found in:
Line 571 ⟶ 700:
fmt.Println(err)
}
}</
=={{header|Haskell}}==
First, an implementation of a black-and-white instance of <tt>Color</tt>. For simplicty, we use ASCII PBM for output instead of the raw format.
<
import Bitmap
Line 606 ⟶ 734:
toBWImage' darkestWhite = mapImage $ f . luminance
where f x | x < darkestWhite = black
| otherwise = white</
Every instance of <tt>Color</tt> has a <tt>luminance</tt> method, so we don't need to convert an image to <tt>Gray</tt> to calculate its histogram.
<
import Bitmap.RGB
import Bitmap.BW
Line 635 ⟶ 763:
if left < right
then (n + 1, left + l, right, ls, rL)
else (n, left, right + r, lL, rs)</
=={{header|J}}==
'''Solution:'''
Using <code>toGray</code> from [[Grayscale image#J|Grayscale image]].
<
medianHist=: {."1 {~ [: (+/\ I. -:@(+/)) {:"1
toBW=: 255 * medianHist@getImgHist < toGray</
'''Example Usage:'''
Line 649 ⟶ 776:
Use [http://rosettacode.org/mw/images/b/b6/Lenna100.jpg Lenna100.jpg] for testing (read using the [[j:Addons/media/platimg|media/platimg]] addon and convert to ppm file).
<
'Lenna100.ppm' writeppm~ 256#.inv readimg 'Lenna100.jpg'
786447</
Read ppm file, convert to black and white and write to a new ppm file using <code>writeppm</code>, <code>readppm</code> and <code>toColor</code> from the [[read ppm file#J | read]]/[[write ppm file#J|write ppm file]], and [[grayscale image#J|grayscale image]] solutions.
<
786447</
=={{header|Java}}==
<
import java.io.File;
import java.io.IOException;
Line 720 ⟶ 846:
return median;
}
}</
=={{header|Julia}}==
{{works with|Julia|0.6}}
<
ima = load("data/lenna50.jpg")
Line 733 ⟶ 858:
imb[imb .≤ medcol] = Gray(0.0)
imb[imb .> medcol] = Gray(1.0)
save("data/lennaGray.jpg", imb)</
=={{header|Kotlin}}==
Uses the image from the [[Percentage difference between images]] task as an example.
<
import java.io.File
Line 797 ⟶ 921:
val bwFile = File("Lenna_bw.jpg")
ImageIO.write(image, "jpg", bwFile)
}</
=={{header|Lua}}==
This solution uses functions defined at:
Line 805 ⟶ 928:
[[Basic bitmap storage#Lua]],
[[Grayscale image#Lua]].
<
local size_x, size_y = #image, #image[1]
Line 856 ⟶ 979:
bitmap = ConvertToColorImage( gray_im )
Write_PPM( "outputimage.ppm", bitmap )</
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang
=={{header|Nim}}==
<
import grayscale_image
Line 913 ⟶ 1,034:
# Save image as a PPM file.
image.writePPM("house_bw.ppm")</
=={{header|OCaml}}==
{{Trans|C}}
<
let get_histogram ~img:gray_channel =
Line 931 ⟶ 1,051:
done;
(t: histogram)
;;</
<
let from = 0 and to_ = 255 in
Line 947 ⟶ 1,067:
in
aux from to_ left right
;;</
main:
<
let img = read_ppm ~filename:"/tmp/foo.ppm" in
Line 973 ⟶ 1,093:
output_ppm ~oc:stdout ~img:res;
;;</
=={{header|Octave}}==
'''Using package''' [http://octave.sourceforge.net/image/index.html Image]
<
if ( isgray(imago) )
for j = 0:255
Line 1,028 ⟶ 1,147:
ibw( img > m ) = 255;
ibw( img <= m ) = 0;
jpgwrite("lennamed.jpg", ibw, 100);</
=={{header|Phix}}==
Requires read_ppm() from [[Bitmap/Read_a_PPM_file#Phix|Read_a_PPM_file]], write_ppm() from [[Bitmap/Write_a_PPM_file#Phix|Write_a_PPM_file]]. <br>
Uses demo\rosetta\lena.ppm, included in the distribution, results may be verified with demo\rosetta\viewppm.exw
<
include ppm.e -- black, white, read_ppm(), write_ppm() (covers above requirements)
Line 1,071 ⟶ 1,189:
sequence img = read_ppm("Lena.ppm")
img = to_bw(img)
write_ppm("LenaBW.ppm",img)</
=={{header|PHP}}==
<syntaxhighlight lang="php">
define('src_name', 'input.jpg'); // source image
define('dest_name', 'output.jpg'); // destination image
Line 1,130 ⟶ 1,247:
echo 'Image not saved! Check permission!';
}
</syntaxhighlight>
Example: <br>
<div>
Line 1,144 ⟶ 1,261:
</i>
</div>
=={{header|PicoLisp}}==
{{trans|Forth}}
<
(let H (need 256 0)
(for L Pgm
(for G L
(inc (nth H (inc G))) ) )
H ) )</
=={{header|PureBasic}}==
Also requires PureBasic solutions for [[Bitmap/Read_a_PPM_file#PureBasic|Read a PPM file]], [[Grayscale_image#PureBasic|Grayscale image]], and [[Bitmap/Write_a_PPM_file#PureBasic|Write a PPM file]].
<
Protected w = ImageWidth(image) - 1
Protected h = ImageHeight(image) - 1
Line 1,218 ⟶ 1,333:
outputFile = Left(sourceFile, Len(sourceFile) - Len(GetExtensionPart(sourceFile))) + "_bw." + GetExtensionPart(sourceFile)
SaveImageAsPPM(image, outputFile, 1)
EndIf</
=={{header|Python}}==
Makes use of the Pillow library (PIL) you can install it using pip. The code is probably not the fastest or the image I used (1960x1960) is just too big.
<
# Open the image
Line 1,263 ⟶ 1,377:
bw_image.show()
bm_image.show()</
=={{header|Racket}}==
<
(require racket/draw math/statistics racket/require
(filtered-in
Line 1,327 ⟶ 1,440:
(send (bitmap->monochrome 1/4 bm) save-file "histogram-racket-0.25.png" 'png)
(send (bitmap->monochrome 1/2 bm) save-file "histogram-racket-0.50.png" 'png) ; median
(send (bitmap->monochrome 3/4 bm xs ws) save-file "histogram-racket-0.75.png" 'png)))</
{{out}}
Line 1,336 ⟶ 1,449:
Sorry guys... I just give up on linking/displaying these images any other way!
=={{header|Raku}}==
(formerly Perl 6)
Line 1,342 ⟶ 1,454:
Uses pieces from [[Bitmap#Raku| Bitmap]], [[Bitmap/Write_a_PPM_file#Raku| Write a PPM file]] and [[Grayscale_image#Raku| Grayscale image]] tasks. Included here to make a complete, runnable program.
<syntaxhighlight lang="raku"
class Bitmap {
has UInt ($.width, $.height);
Line 1,393 ⟶ 1,505:
histogram($b);
'./Lenna-bw.pbm'.IO.open(:bin, :w).write: $b.P4;</
See [https://github.com/thundergnat/rc/blob/master/img/Lenna.png Lenna], and [https://github.com/thundergnat/rc/blob/master/img/Lenna-bw.png Lenna-bw] images. (converted to .png as .ppm format is not widely supported).
=={{header|Ruby}}==
<
def histogram
histogram = Hash.new(0)
Line 1,438 ⟶ 1,549:
end
Pixmap.open('file.ppm').save_as_blackandwhite('file_bw.ppm')</
=={{header|Rust}}==
<syntaxhighlight lang="rust">extern crate image;
use image::{DynamicImage, GenericImageView, ImageBuffer, Rgba};
/// index of the alpha channel in RGBA
const ALPHA: usize = 3;
/// Computes the luminance of a single pixel
/// Result lies within `u16::MIN..u16::MAX`
const fn luminance(rgba: Rgba<u8>) -> u16 {
let Rgba([r, g, b, _a]) = rgba;
55 * r as u16 + 183 * g as u16 + 19 * b as u16
}
/// computes the median of a given histogram
/// Result lies within `u16::MIN..u16::MAX`
fn get_median(total: usize, histogram: &[usize]) -> u16 {
let mut sum = 0;
for (index, &count) in histogram.iter().enumerate() {
sum += count;
if sum >= total / 2 {
return index as u16;
}
}
u16::MAX
}
/// computes the histogram of a given image
fn compute_histogram(img: &DynamicImage) -> Vec<usize> {
let mut histogram = vec![0; 1 << u16::BITS];
img.pixels()
.map(|(_x, _y, pixel)| luminance(pixel))
.for_each(|luminance| histogram[luminance as usize] += 1);
histogram
}
/// returns a black or white pixel with an alpha value
const fn black_white(is_white: bool, alpha: u8) -> [u8; 4] {
if is_white {
[255, 255, 255, alpha]
} else {
[0, 0, 0, alpha]
}
}
/// create a monochome compy of the given image
/// preserves alpha data
fn convert_to_monochrome(img: &DynamicImage) -> ImageBuffer<Rgba<u8>, Vec<u8>> {
let histogram = compute_histogram(img);
let (width, height) = img.dimensions();
let pixel_count = (width * height) as usize;
let median = get_median(pixel_count, &histogram);
let pixel_buffer = img.pixels()
.flat_map(|(_x, _y, pixel)| black_white(luminance(pixel) > median, pixel[ALPHA]))
.collect();
ImageBuffer::from_vec(width, height, pixel_buffer).unwrap_or_else(|| unreachable!())
}
fn main() {
let img = image::open("lena.jpg").expect("could not load image file");
let img = convert_to_monochrome(&img);
img.save("lena-mono.png").expect("could not save result image");
}
</syntaxhighlight>
=={{header|Scala}}==
See also
Line 1,446 ⟶ 1,626:
* [[Read_ppm_file#Scala|Read a PPM File]] image loading
<
def histogram(bm:RgbBitmap)={
val hist=new Array[Int](255)
Line 1,477 ⟶ 1,657:
image
}
}</
Usage:
<
val hist=BitmapOps.histogram(img)
val mid=BitmapOps.histogram_median(hist);
Line 1,490 ⟶ 1,670:
icon=new ImageIcon(BitmapOps.monochrom(img, mid).image)
}
}</
=={{header|Tcl}}==
{{libheader|Tk}}
Uses [[read ppm file#Tcl|readPPM]], [[grayscale image#Tcl|grayscale]] and [[write ppm file#Tcl|output_ppm]] from other pages.
<
package require Tk
Line 1,544 ⟶ 1,723:
}
}
}</
=={{header|Vedit macro language}}==
The input image is in edit buffer pointed by numeric register #15.
On return, #30 points to buffer containing histogram data.
The histogram data is given as ASCII decimal values, one value per line.
<
#30 = Buf_Free // #30 = buffer to store histogram data
for (#9=0; #9<256; #9++) {
Line 1,559 ⟶ 1,737:
Num_Ins(#8, FILL) // store count
}
Return</
=={{header|Wren}}==
{{libheader|DOME}}
<
import "graphics" for Canvas, Color, ImageData
class ImageHistogram {
construct new(filename, filename2) {
_image = ImageData.
Window.resize(_image.width, _image.height)
Canvas.resize(_image.width, _image.height)
Line 1,647 ⟶ 1,824:
}
var Game = ImageHistogram.new("Lenna100.jpg", "Lenna100_B&W.png")</
=={{header|zkl}}==
{{trans|C}}
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
<
hist:=List.createLong(256,0); // array[256] of zero
image.data.howza(0).pump(Void,'wrap(c){ hist[c]+=1 }); // byte by byte loop
Line 1,665 ⟶ 1,842:
}
from
}</
<
median:=histogramMedian(histogram(img));
median.println();
Line 1,675 ⟶ 1,852:
img.data.pump(bw.data.clear(),'wrap(c){ if(c>median) 0xff else 0 });
bw.write(File("foo.ppm","wb"));</
{{out}}<pre>101</pre>
See the BBC Basic entry or:
http://www.zenkinetic.com/Images/RosettaCode/lenaBW.jpg
{{omit from|AWK}}
{{omit from|PARI/GP}}
|