Click here to Skip to main content
13,407,586 members (51,920 online)
Click here to Skip to main content
Add your own
alternative version

Stats

27.4K views
1.3K downloads
28 bookmarked
Posted 19 Apr 2016

Image Binarization Using 10 Program Languages

, 3 May 2016
Rate this:
Please Sign up or sign in to vote.
A simple image binarization

Introduction

Sometimes, we need to convert color images to black and white ones. Examples include black and white fax machines and photocopiers, both of which require conversion of color images to black and white ones. For this purpose, there are several approaches such as binarization and dithering, each of which includes several variations. The former includes Japanese invented Otsu’s method for automatic thresholding and the simplest fixed thresholding method.

In this paper, we have to first learn how to process images, so the fixed thresholding method is used. The most important thing is to learn how to read into image files and process pixel data in them. We try to provide as many programming languages as possible so that different designers can understand how to process pixel data. The programming languages provided in this paper include Visual C++ 2010, C++ Builder XE5, Visual C# 2012, Visual Basic .NET 2012, Visual Basic 6.0, JAVA with NetBeans v8.1, DELPHI XE5, Android v4.1.2 with Eclipse, HTML5 + JavaScript and Matlab 2011. This author argues that learning digital image processing has nothing to do with programming languages. The most important thing is to learn the knowledge of digital image processing because programming languages are merely a type of tools that helps you achieve this goal, not a vital key. Therefore, this author has set an example by demonstrating the same algorithm in ten different ways. The purpose is to prove that digital image processing has little to do with programming languages.

To make it possible for readers to understand, all the program examples in this paper are accompanied with English comments so that readers not only can comprehend, but can also read the codes with ease. If you have these development tools, you can open the attached source codes. Whether you choose to compile or interpret them, you can run single-step debugging to check the computational process of the algorithm step by step. Or, you can set up breakpoints in the parts which are important or you do not understand so that the program will stop and wait until you have checked the saved values for all the variables. The most important thing is to become familiar with this binarization algorithm because it is a simpler algorithm among digital image processing techniques and does not contain any abstruse mathematic formulas. It requires only setting up thresholds and then comparing sizes to determine black or white. The key point is how to process pixels and calculate indices of pixels.

Using the Code

Visual C++ 2010

Visual C++ 2010

// The height of the image.
for ( int iY = 0; iY < imageA->DibInfo->bmiHeader.biHeight; iY++ )
{
    // The width of the image.
    for ( int iX = 0; iX < imageA->DibInfo->bmiHeader.biWidth; iX++ )
    {
        // The index of pixel, because we use the three depth bit to present one pixel of color.
        // Therefore, we have to multiple three.
        lIDXA = ( iX * 3 ) + ( iY * imageA->DibInfo->bmiHeader.biWidth * 3 );
        // To get the pixel depth of the blue channel.
        byteRGB_BA = imageA->DibArry[lIDXA+0];
        // To get the pixel depth of the green channel.
        byteRGB_GA = imageA->DibArry[lIDXA+1];
        // To get the pixel depth of the red channel.
        byteRGB_RA = imageA->DibArry[lIDXA+2];
        // To transform RGB to Y (gray scale).
        dobYUV_YA =  (0.299 * byteRGB_RA + 0.587 * byteRGB_GA + 0.114 * byteRGB_BA);
        // Set our thresholds, To decide which pixel become to white.
        if ( dobYUV_YA > 60 && dobYUV_YA < 160 )
        {
            lIDXB = ( iX * 3 ) + ( iY * imageB->DibInfo->bmiHeader.biWidth * 3 );
            imageB->DibArry[lIDXB+0] = 255;
            imageB->DibArry[lIDXB+1] = 255;
            imageB->DibArry[lIDXB+2] = 255;
        }
        // Otherwise, those pixels will be black.
        else
        {
            lIDXB = ( iX * 3 ) + ( iY * imageB->DibInfo->bmiHeader.biWidth * 3 );
            imageB->DibArry[lIDXB+0] = 0;
            imageB->DibArry[lIDXB+1] = 0;
            imageB->DibArry[lIDXB+2] = 0;
        }
    } // for ( int iX = 0; iX < imageA->DibInfo->bmiHeader.biWidth; iX++ )
} // for ( int iY = 0; iY < imageA->DibInfo->bmiHeader.biHeight; iY++ )

C++ Builder XE5

C++ Builder XE5

C++ Builder XE5

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
// Create three points of TBitmap object
Graphics::TBitmap *TheBitmap, *TempBitmap, *OriginBitmap;
// Create a threshold.
int Threshold;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Exit1Click(TObject *Sender)
{
	// Exit the program
	Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenFile1Click(TObject *Sender)
{
	// If you got a file of the picture, you are able to load it.
	if ( OpenPictureDialog1->Execute() )
	{
		// Disable automatic resize.
		Image1->AutoSize=false;
		// Enable an automatic stretch.
		Image1->Stretch=true;
		// Loads a picture file.
		Image1->Picture->LoadFromFile(OpenPictureDialog1->FileName);
		// Set a point to the picture of loading.
		TheBitmap=Image1->Picture->Bitmap;
		// Create a new TBitmap object to keep original picture.
		OriginBitmap = new Graphics::TBitmap();
		// To keep original picture.
		OriginBitmap->Assign(TheBitmap);
		// Set up TImage object to keep original picture.
		Image1->Picture->Bitmap->Assign(TheBitmap);
		// If you open picture file successful and then set a flag.
		// The means that you have been opened a file.
		OpenFile = 1;
		// Set the threshold is 100.
		Threshold = 100;
		// Set the position of the scroll bar is 100.
		ScrollBar1->Position = Threshold;
	}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ScrollBar1Change(TObject *Sender)
{
	// If you have not opened a file, the flag will be zero, and then returns.
	if (OpenFile == 0) {
		return;
	}
	Byte *ptr, *tptr;
	// To get a counter of binarization from the scroll bar.
	Threshold = (int) ScrollBar1->Position;
	// Set up the TImage restore to the original picture.
	Image1->Picture->Bitmap->Assign(OriginBitmap);
	// To do the times of binarization
	TempBitmap = new Graphics::TBitmap();
	// To get a current bitmap.
	TempBitmap->Assign(TheBitmap);
	// To do scan line of the whole picture.
	for (int y=0; y < TheBitmap->Height; y++) {
		// Set Y position of the image point.
		ptr = (Byte*) TheBitmap->ScanLine[y];
		// Set Y position of the image point.
		tptr = (Byte*) TempBitmap->ScanLine[y];
		// To do scan X-axis of the line.
		for (int x=0; x < TheBitmap->Width; x++) {
			// if the pixel more than the threshold, it should be white.
			if (tptr[x] > Threshold) {
				ptr[x] = (Byte) 255;
			}
			// Otherwise, it should be black.
			else
			{
				ptr[x] = (Byte) 0;
			}
		} // End x
	} // End y
	// Release the temporal bitmap.
	delete TempBitmap;
	// Refresh and draw the TImage object
	Repaint();
	// Set result of binarization of the picture.
	Image1->Picture->Bitmap->Assign(TheBitmap);
}
//---------------------------------------------------------------------------

Visual C Sharp 2012

Visual C Sharp 2012

Normal

namespace Binarization_for_C_Sharp
{
    public partial class Form1 : Form
    {
        // This is a file name string.
        private string curFileName;
        // This is a bitmap object.
        private System.Drawing.Bitmap curBitmap;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Establish a open file dialog.
            OpenFileDialog openDlg = new OpenFileDialog();
            // Set a filter to arrange picture format.
            openDlg.Filter = "All format | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +
                "*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf";
            // Set the title of the open file dialog.
            openDlg.Title = "Open a picture file.";
            // if open file is successful.
            if (openDlg.ShowDialog() == DialogResult.OK)
            {
                // Get the open file name to current file name variable.
                curFileName = openDlg.FileName;
                try
                {
                    // Establish a bitmap from file through by Image object.
                    curBitmap = (Bitmap)Image.FromFile(curFileName);
                }
                // If we get a exception.
                catch (Exception exp)
                {
                    // Pop to a message.
                    MessageBox.Show(exp.Message);
                }
            }
            // Force to redraw.
            Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            // Establish a graphics object from external object
            Graphics g = e.Graphics;
            // if it is to open file successful.
            if (curBitmap != null)
            {
                // Draw the picture in the position that we set up.
                g.DrawImage(curBitmap, 140, 10, curBitmap.Width, curBitmap.Height);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // if it is to open file successful.
            if (curBitmap != null)
            {
                // Establish a color object.
                Color curColor;
                int ret;
                // The width of the image.
                for (int iX = 0; iX < curBitmap.Width; iX++)
                {
                    // The height of the image.
                    for ( int iY = 0; iY < curBitmap.Height; iY++ )
                    {
                        // Get the pixel from bitmap object.
                        curColor = curBitmap.GetPixel(iX, iY);
                        // Transform RGB to Y (gray scale)
                        ret = (int) (curColor.R * 0.299 + curColor.G * 0.578 + curColor.B * 0.114);
                        // This is our threshold, you can change it and to try what are different.
                        if (ret > 120)
                        {
                            ret = 255;
                        }
                        else
                        {
                            ret = 0;
                        }
                        // Set the pixel into the bitmap object.
                        curBitmap.SetPixel( iX, iY, Color.FromArgb ( ret, ret ,ret ) );
                    } // The closing 'The height of the image'.
                } // The closing 'The width of the image'.
                // Force to redraw.
                Invalidate();
            }
        }
    }
}

Fast

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            // Establish a graphics object from external object
            Graphics g = e.Graphics;
            // if it is to open file successful.
            if (curBitmap != null)
            {
                // Red
                int iR = 0;
                // Green
                int iG = 0;
                // Blue
                int iB = 0;

                // Lock the bitmap's bits.  
                Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
                System.Drawing.Imaging.BitmapData bmpData =
                    curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    curBitmap.PixelFormat);

                // Get the address of the first line.
                IntPtr ptr = bmpData.Scan0;

                // Declare an array to hold the bytes of the bitmap.
                int bytes = Math.Abs(bmpData.Stride) * curBitmap.Height;
                byte[] rgbValues = new byte[bytes];

                // Copy the RGB values into the array.
                System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

                // Set every third value to 255. A 24bpp bitmap will binarization.  
                for (int counter = 0; counter < rgbValues.Length; counter += 3)
                {
                    // Get the red channel
                    iR = rgbValues[counter + 2];
                    // Get the green channel
                    iG = rgbValues[counter + 1];
                    // Get the blue channel
                    iB = rgbValues[counter + 0];
                    // If the gray value more than threshold and then set a white pixel.
                    if ((iR + iG + iB) / 3 > 100)
                    {
                        // White pixel
                        rgbValues[counter + 2] = 255;
                        rgbValues[counter + 1] = 255;
                        rgbValues[counter + 0] = 255;
                    }
                    else
                    {
                        // Black pixel
                        rgbValues[counter + 2] = 0;
                        rgbValues[counter + 1] = 0;
                        rgbValues[counter + 0] = 0;
                    }
                }

                // Copy the RGB values back to the bitmap
                System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);

                // Unlock the bits.
                curBitmap.UnlockBits(bmpData);

                // Draw the modified image.
                g.DrawImage(curBitmap, 140, 10, curBitmap.Width, curBitmap.Height);
            }
        }

Visual Basic .NET 2012

Visual Basic .NET 2012

Public Class Form1
    ' Establish a string of the current file name
    Private curFileName As String
    ' Establish a bitmap object of current bitmap object
    Private curBitmap As Bitmap

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ' Establish a open file dialog.
        Dim openFileDialog1 As New OpenFileDialog()
        ' The initial directory displayed by the file dialog box. The default is an empty string ("").
        openFileDialog1.InitialDirectory = ".\"
        ' The file filtering options available in the dialog box.
        openFileDialog1.Filter = "All format | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +
                "*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf"
        ' A value containing the index of the filter currently selected in the file dialog box. 
        ' The default value is 1.
        openFileDialog1.FilterIndex = 1
        ' true if the dialog box restores the current directory to its original value 
        ' if the user changed
        ' the directory while searching for files; otherwise, false. The default value is false.
        openFileDialog1.RestoreDirectory = True
        ' If the open file is successful.
        If openFileDialog1.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
            Try
                ' Set the file name into current file name.
                curFileName = openFileDialog1.FileName
                ' Make sure the file is not empty.
                If (curFileName IsNot Nothing) Then
                    ' Establish a bitmap from file through by Image object.
                    Dim b As Bitmap = New Bitmap(curFileName)
                    ' Establish a bitmap object from the loaded image of bitmap object.
                    curBitmap = New Bitmap(b.Width, b.Height, _
			System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
                    ' Clone the bitmap object
                    curBitmap = b.Clone()
                End If
                ' If we have a problem, throw a exception and pop up a message.
            Catch Ex As Exception
                MessageBox.Show("Cannot read file from disk. Original error: " & Ex.Message)
            Finally
                ' Check this again, since we need to make sure we didn't throw an exception on open.
            End Try
            ' Force to redraw.
            Invalidate()
        End If
    End Sub

    Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
        ' if it is to open file successful.
        If (curBitmap IsNot Nothing) Then
            ' Draw the picture in the position that we set up.
            e.Graphics.DrawImage(curBitmap, 140, 10, curBitmap.Width, curBitmap.Height)
        End If
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        ' The height of the image.
        For y As Integer = 0 To curBitmap.Height - 1
            ' The width of the image.
            For x = 0 To curBitmap.Width - 1
                ' Get the pixel from current bitmap object.
                Dim curPixColor As Color = curBitmap.GetPixel(x, y)
                ' This is a gray variable.
                Dim ret As Integer
                ' Transform RGB color space to Y (gray scale)
                ret = (curPixColor.R * 0.299 + curPixColor.G * 0.578 + curPixColor.B * 0.114)
                ' This is our threshold, you can change it.
                If ret > 120 Then
                    curBitmap.SetPixel(x, y, Color.White)
                Else
                    curBitmap.SetPixel(x, y, Color.Black)
                End If
                ' The closing 'The width of the image'.
            Next
            ' The closing 'The height of the image'.
        Next
        ' Force to redraw.
        Invalidate()
    End Sub
End Class

Visual Basic 6.0

Visual Basic .NET 2012

' The Form loading
Private Sub Form_Load()
    ' Loading a bitmap
    Picture1.Picture = LoadPicture(App.Path & "\B_01.bmp")
    ' The variable is X-axis
    Dim lngX As Long
    ' The variable is Y-axis
    Dim lngY As Long
    ' The variable is gray
    Dim intS
    ' The variable is RGB, respectively.
    Dim intR, intG, intB
    ' Set up the scale mode is pixel.
    Picture1.ScaleMode = 3
    ' Enable the picture box autometic redraw.
    Picture1.AutoRedraw = True
    ' Set up the scale mode is pixel.
    Picture2.ScaleMode = 3
    ' Enable the picture box autometic redraw.
    Picture2.AutoRedraw = True
    ' The height of the image
    For lngY = 0 To Picture1.ScaleHeight
        ' The width of the image
        For lngX = 0 To Picture1.ScaleWidth
            ' Get the pixel of the red channel
            intR = (Picture1.Point(lngX, lngY) And &HFF)
            ' Get the pixel of the green channel
            intG = (Picture1.Point(lngX, lngY) And &HFF00&) \ 256
            ' Get the pixel of the blue channel
            intB = (Picture1.Point(lngX, lngY) And &HFF0000) \ 65536
            ' Make a gray scale pixel
            intS = (intR + intG + intB) / 3
            ' This is our threshold, if it over 120, it should be white.
            If intS > 120 Then
               intS = 255
            ' Otherwise, it should be black.
            Else
               intS = 0
            End If
            ' Set the monochromatic pixel.
            Picture2.PSet (lngX, lngY), RGB(intS, intS, intS)
        ' The closing 'The width of the image'.
        Next lngX
    ' The closing 'The height of the image'.
    Next lngY
End Sub

JAVA for NetBeans v8.0.2

JAVA for NetBeans v8.0.2

import java.awt.FileDialog;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.awt.image.DataBufferByte;

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
       FileDialog f = new FileDialog(this, "Open File", FileDialog.LOAD);
       // Set the default directory
       f.setDirectory(".");
       // Display the dialog and wait for the user's response
       f.show();
       // Remember new default directory.
       String directory = f.getDirectory();
       // Establish a full path.
       String filepath = directory+f.getFile();
       // Establish an image object from BufferedImage.
       BufferedImage img = null;
       try {
           // Read an image from the file.
           img = ImageIO.read(new File(filepath));
           // To do binarization.
           int[][] result = convertToBinarization(img);
           // Show a processed image.
           jLabel1.setIcon(new javax.swing.ImageIcon(img));
       }
       // We have a problem and then throw an exception.
       catch (IOException e) {
           System.err.println("I could not load the file \'"+directory+"'.  Sorry.");
       }
}

// This function is to convert RGB image binarization.
private static int[][] convertToBinarization(BufferedImage image) {
    // Get the width of the image.
    int width = image.getWidth();
    // Get the height of the image.
    int height = image.getHeight();
    // Establish a 2D array to keep image data.
    int[][] result = new int[height][width];
    // The height of the image.
    for (int row = 0; row < height; row++) {
        // The width of the image.
        for (int col = 0; col < width; col++) {
            // Acquire RGB value.
            result[row][col] = image.getRGB(row, col);
            // Acqurie integer type of RGB value.
            int iRet = result[row][col];
            // The alpha variable.
            int iA = 0;
            // The red variable.
            int iR = 0;
            // The green variable.
            int iG = 0;
            // The bule variable.
            int iB = 0;
            int iGray = 0;
            // Get the alpha of the alpha channel.
            iA = (((int) iRet & 0xff) << 24);
            // Get blue pixel of the blue channel.
            iB = ((int) iRet & 0xff);
            // Get green pixel of the green channel.
            iG = (((int) iRet & 0x00ff00) >> 8);
            // Get red pixel of the red channel.
            iR = (((int) iRet & 0xff0000) >> 16);
            // Transform RGB color space to gray scale.
            iG = ( iR + iG + iB ) / 3;
            // This is our threshold, you can change it.
            if ( iG > 120 )
            {
                // This is white pixel.
                iRet = 0xffffff;
                // Set the white pixel into the image.
                image.setRGB(row, col, iRet);
            }
            else
            {
                // Set the black pixel into the image.
                image.setRGB(row, col, 0);
            }
      }
  }
  // return result value.
  return result;
}

DELPHI XE5

DELPHI XE5

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtDlgs, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    OpenPictureDialog1: TOpenPictureDialog;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  // The string variable is a file name.
  Str : String;
implementation

{$R *.dfm}


procedure TForm1.Button2Click(Sender: TObject);
var
  PByte :PByteArray;
  Gray,x,y :Integer;
  ImageBmp :TBitmap;
begin
  // if it is no file name and pop up a message.
  if Str = '' then
    showmessage('Can not open this file, because it is an empty.')
  // Otherwise, There is a file name.
  else
  begin
  // Establish a TBitmap object.
  ImageBmp :=TBitmap.Create;
  // Assign the Image object.
  ImageBmp.Assign(Image1.Picture.Bitmap);
  // Set pixel format is 24 bits.
  ImageBmp.PixelFormat :=pf24Bit;
  // The height of the image.
  for y:=0 to ImageBmp.Height-1 do
  begin
    // Set the point up to Y-axis.
    PByte := ImageBmp.scanline[y];
    // The width of the image.
    for x:=0 to ImageBmp.Width-1 do
    begin
      // Transform RGB color space to gray scale.
      Gray:=Round(PByte[x*3+2]*0.3+PByte[x*3+1]*0.59+PByte[x*3]*0.11);
      // This is our threshold, you can change it. What is a different?
      if Gray > 120 then
      // Set the pixel is white.
      begin
         PByte[x*3]:=255;
         PByte[x*3+1]:=255;
         PByte[x*3+2]:=255;
      end
      // Otherwise, set the pixel is black.
      else
      begin
         PByte[x*3]:=0;
         PByte[x*3+1]:=0;
         PByte[x*3+2]:=0;
      end
    end;
  end;
  // Assign a processed image.
  Image1.Picture.Bitmap.Assign(ImageBmp);
  // Release the TBitmap object.
  ImageBmp.Free;
end;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  // The string is full path.
  Path:string;
begin
  // Set the path is in the path of the execute file.
  path:=ExtractFilePath(application.ExeName);
  // Set up initial directory.
  OpenPictureDialog1.InitialDir := Path;
  // Execute the OpenPictureDialog object.
  if OpenPictureDialog1.Execute then
  begin
    // Set a file name into str variable.
    Str := OpenPictureDialog1.FileName;
    // Loading a picture from the file.
    Image1.Picture.LoadFromFile(Str);
  end;
end;

end.

Android v4.1.2 with Eclipse

Android v4.1.2 with Eclipse

package com.example.binarization.camera;

import com.example.binarization.camera.R;

import android.os.Bundle;
import android.app.Activity;
import android.view.*;
import android.widget.*;
import android.annotation.SuppressLint;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;

@SuppressLint("NewApi")
public class MainActivity extends Activity implements SurfaceHolder.Callback  {

	SurfaceView mSurfaceView ;
	Button btn_Capture;
	Camera mCamera;
	PictureCallback mPictureCB;
	AutoFocusCallback mAutoFocusCB;
	ImageView ImgView;
	TextView txtView;
	Bitmap bitmapClone;

	@SuppressWarnings("deprecation")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Set the format of window, as per the PixelFormat types.
		// This overrides the default format that is selected by
		// the Window based on its window decorations.
		// System chooses a format that supports translucency (many alpha bits).
		getWindow().setFormat(PixelFormat.TRANSLUCENT);
		// Enable extended window features.
		// Flag for the "no title" feature, turning off the title at the top of the screen.
	   	requestWindowFeature(Window.FEATURE_NO_TITLE);
	   	// Set the flags of the window, as per the WindowManager.LayoutParams flags.
	   	// Window flag: Hide all screen decorations (e.g. status bar).
	   	// while this window is displayed. This allows the window to use
	   	// the entire display space for itself -- the status bar will be
	   	// hidden when an app window with this flag set is on the top layer.
	   	getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
	   	WindowManager.LayoutParams.FLAG_FULLSCREEN);
        // Set the activity content from a layout resource.
	   	// The resource will be inflated, adding all top-level views to the activity.
	   	setContentView(R.layout.activity_main);
		// Change the desired orientation of this activity.
	   	// If the activity is currently in the foreground or
	   	// otherwise impacting the screen orientation,
	   	// the screen will immediately be changed
	   	// (possibly causing the activity to be restarted).
	   	// Otherwise, this will be used the next time the activity is visible.
        // Constant corresponding to portrait in the android.R.attr.screenOrientation attribute.
   	 	this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
   	 	// -- (Start)
   	 	ImgView = (ImageView)this.findViewById(R.id.ImgView);
   	 	txtView = (TextView)this.findViewById(R.id.txtView);
   	 	btn_Capture = (Button)this.findViewById(R.id.btn_Capture);
   	 	mSurfaceView  = (SurfaceView)this.findViewById(R.id.surView_Camera);
   	 	// -- (End)
   	 	// Set and get SurfaceHolder
   	 	// Abstract interface to someone holding a display surface.
   	 	// Allows you to control the surface size and format,
   	 	// edit the pixels in the surface, and monitor changes to the surface.
   	 	// This interface is typically available through the SurfaceView class.
        // When using this interface from a thread other than the one running
   	 	// its SurfaceView, you will want to carefully read the methods
   	 	// lockCanvas and Callback.surfaceCreated().
   	 	SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
   	 	mSurfaceHolder.addCallback(this);
   	 	mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        // To establish Camera.takePicture callback function.
   	    mPictureCB = new PictureCallback(){
        // Image processing.
   	    // Overwrite onPictureTake function.
   	    @Override
   		public void onPictureTaken(byte[] data, Camera camera){
   	   	    // We use the BitmapFactory to decode become raw data to bitmap format.
   			Bitmap mBitmap = BitmapFactory.decodeByteArray(data, 0 , data.length);
   			bitmapClone = Bitmap.createBitmap(mBitmap.getWidth(), 
					mBitmap.getHeight(), mBitmap.getConfig());
   			bitmapClone.copy(mBitmap.getConfig(), true);
			int iY = 0;
			int iX = 0;
			int iPixel = 0;
			int iRed = 0;
			int iGreen = 0;
			int iBlue = 0;
			int iRGBAvg = 0;
			// Gray of image processing.
			// The height of the image
   			for ( iY = 0; iY < bitmapClone.getHeight(); iY++ )
   			{
   				// The width of the image
   				for ( iX = 0; iX < bitmapClone.getWidth(); iX++ )
   				{
   					// To get pixel.
   					iPixel = mBitmap.getPixel(iX, iY);
   					// To get value of the red channel.
   					iRed = Color.red(iPixel);
   					// To get value of the green channel.
   					iGreen = Color.green(iPixel);
   					// To get value of the blue channel.
   					iBlue = Color.blue(iPixel);
   					// Compute value of gray.
   					iRGBAvg = ( iRed + iGreen + iBlue ) / 3;
   					// This is our threshold, you can change it.
   					if ( iRGBAvg > 120 )
   					{
   	   					// Set pixel to white.
   						bitmapClone.setPixel(iX, iY, Color.rgb(255, 255, 255));
   					}
   					else
   					{
   	   					// Set pixel to black.
   						bitmapClone.setPixel(iX, iY, Color.rgb(0, 0, 0));
   					}
   				}
   			}

   			// Set processed image to display.
   			ImgView.setImageBitmap(bitmapClone);
   			// Show the height of the image.
   			//String strInfo = "";
   			//strInfo = String.valueOf(mBitmap.getHeight());
   			//txtView.setText(strInfo);
			// Restart camera to preview.
			camera.startPreview();
			// To disable auto focus of callback function.
			camera.autoFocus(null);
   		}
   	 };

   	 // To establish Camera.AutoFocusCallback
   	 mAutoFocusCB = new AutoFocusCallback(){
    		@Override
    		public void onAutoFocus(boolean success, Camera camera){
    			// When auto focus is done and then we will take a picture.
    			if ( success == true )
    			{
					// Into take a picture of callback function.
					camera.takePicture(null, null, mPictureCB);
    			}
    		}
   	 };

   	 // While a user press the take a picture button, when it starts auto focus.
   	 btn_Capture.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				try{
					// To make sure the camera is open.
					if(mCamera != null){
						// Create a thread.
						new Thread(new Runnable() {
						    public void run() {
						    	// To execute the auto focus.
							    mCamera.autoFocus(mAutoFocusCB);
						    }
						  }).start();
					}
				}catch(Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub
    	// Get parameters of the camera.
    	Camera.Parameters parameters = mCamera.getParameters();
		// Set size of the picture.
    	parameters.setPictureSize(640, 480);
    	// Set size of preview.
    	parameters.setPreviewSize(width, height);
    	// Set auto focus.
    	parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
    	// Set parameters of the camera.
		mCamera.setParameters(parameters);
		// Start preview.
		mCamera.startPreview();
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
    	// If the camera is initially successful and then to open camera.
    	if ( mCamera == null )
    	{
    		mCamera = Camera.open();
    	}
    	try {
    		// Set SurfaceHolder.
    		mCamera.setPreviewDisplay(holder);
    	}catch(Exception e) {
    		e.printStackTrace();
    	}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub
    	// Stop preview.
    	mCamera.stopPreview();
    	// Release Camera.
    	mCamera.release();
	}
}

HTML5 + Javascript

HTML5 + Javascript

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function imageLoaded(ev) {
    element = document.getElementById("cancan");
    c = element.getContext("2d");

	// The image, assumed to be 512x512
    im = ev.target;

    // Read the width and height of the canvas
    width = element.width;
    height = element.height;

    // Stamp the image on the left of the canvas.
    c.drawImage(im, 0, 0);

    // Get all canvas pixel data
    imageData = c.getImageData(0, 0, width, height);

	// The width index is output position.
    w2 = width / 2;

    // Run through the image.
	// The height of the image.
    for (y = 0; y < height; y++) {
		// *4 for 4 ints per pixel.
		// This is an input index.
        inpos = y * width * 4;
		// This is an output index.
        outpos = inpos + w2 * 4
		// The width of the image.
        for (x = 0; x < w2; x++) {
			// Get the pixel of the red channel.
            r = imageData.data[inpos++]
			// Get the pixel of the green channel.
            g = imageData.data[inpos++]
			// Get the pixel of the blue channel.
            b = imageData.data[inpos++]
			// Get the pixel of the alpha channel.
            a = imageData.data[inpos++]
            // Transform RGB color space to gray scale.
			gray =  (0.299 * r + 0.587 * g + 0.114 * b)
            // This is our threshold. You can change it.
            if ( gray > 120 )
			{
				// Set the pixel is white.
	            imageData.data[outpos++] = 255;
    	        imageData.data[outpos++] = 255;
        	    imageData.data[outpos++] = 255;
            	imageData.data[outpos++] = a;
			}
			else
			{
				// Set the pixel is black.
            	imageData.data[outpos++] = 0;
            	imageData.data[outpos++] = 0;
	            imageData.data[outpos++] = 0;
    	        imageData.data[outpos++] = a;
			}
        } // The closing "The width of the image".
    } // The closing "The height of the image".

    // Put pixel data on canvas.
    c.putImageData(imageData, 0, 0);
}

// Establish an image object.
im = new Image();
// Load the javascript function.
im.onload = imageLoaded;
// Code assumes this image is 512x512.
im.src = "B_01.jpg";
</script>
</head>

<body>
<!-- Create a canvas -->
<canvas id="cancan" width="1024", height="512">Canvas</canvas>
</body>
</html>

Matlab

Matlab

% Load image
x=imread('B_01.bmp');
% Transform RGB color space to gray scale
gray=rgb2gray(x);
% Binarization
BW=im2bw(x);
% Show the image
imshow(BW);

Exception

Visual C++ 2010

  1. There is a notice, if your bit depth of bitmap file is not 24 bits, you should change your bitmap files to adapt this program, or you could rewrite this source code to fit your bitmap format.
  2. You have to install Microsoft SDK v7.1, because I include windowscodes.lib. #pragma comment(lib, "windowscodecs.lib")

C++ Builder XE5

  1. You should also uncheck Build with runtime packages under: Project-> Options-> Packages-> Runtime Packages-> Link with runtime packages Make sure to uncheck the three items ("Link with runtime packages", "Link with Dynamic RTL" and "Link with Delphi Runtime Library") under the build configuration you are using ('release' / 'debug').

JAVA for NetBeans v8.0.2

  1. This is another fast way to acquire RGB values method. It is suitable for huge image.
private static int[][] convertTo2DWithoutUsingGetRGB(BufferedImage image) {

  final byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
  final int width = image.getWidth();
  final int height = image.getHeight();
  final boolean hasAlphaChannel = image.getAlphaRaster() != null;
  int[][] result = new int[height][width];
  if (hasAlphaChannel) {
     final int pixelLength = 4;
     for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += pixelLength) {
        int argb = 0;
        argb += (((int) pixels[pixel] & 0xff) << 24); // alpha
        argb += ((int) pixels[pixel + 1] & 0xff); // blue
        argb += (((int) pixels[pixel + 2] & 0xff) << 8); // green
        argb += (((int) pixels[pixel + 3] & 0xff) << 16); // red
        result[row][col] = argb;
        col++;
        if (col == width) {
           col = 0;
           row++;
        }
     }
  } else {
     final int pixelLength = 3;
     for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += pixelLength) {
        int argb = 0;
        argb += -16777216; // 255 alpha
        argb += ((int) pixels[pixel] & 0xff); // blue
        argb += (((int) pixels[pixel + 1] & 0xff) << 8); // green
        argb += (((int) pixels[pixel + 2] & 0xff) << 16); // red
        result[row][col] = argb;
        col++;
        if (col == width) {
           col = 0;
           row++;
        }
     }
  }
  return result;
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Lai Tai Yu
Software Developer (Senior) Aquas Inc.
Taiwan Taiwan
Dr. Lai Tai-Yu received the Ph.D. from National Taipei University of Technology in 2016. He is the co-author of 1 journal, 21 conference papers, 6 books, 9 articles in the codeproject.com, and 2 patent inventions. He was awarded the Certificate of Chinese Teaching as Second Language(TCSOL) in 2016. His research interests lie in the areas of digital image processing. He has been a senior software consultant.  

Dr Taiyu Lai. Stopień doktora, uzyskał w 2016 roku i objął stanowisko adiunkta na Wydziale. Ponadto jest autorem i współautorem: 1 publikacji artykułu w czasopiśmie naukowym, 21 artykułów opublikowanych w materiałach konferencyjnych, 6 książek, 9 eseje w monografiach codeproject.com, i posiada dwa patenty. Tytuł nauczyciel uzyskał w 2016 r. certyfikat nauczania chińskiego jako drugiego języka(TCSOL). Zainteresowania naukowe: przetwarzania obrazów. Jest starszym konsultantem ds. rozwoju oprogramowania.  

赖岱佑在2016年取得台北科技大学资讯工程博士学位,有1篇期刊、21篇会议论文、6本书籍、9篇文章在 codeproject.com 、2项专利。2016年,从台北科技大学华语文中心获得国际汉语教学(TCSOL)认证。研究方向:数字图像处理。职称是资深软件技术顾问。

賴岱佑在2016年取得台北科技大學資訊工程博士學位,有1篇期刊、21篇會議論文、6本書籍、9篇文章在 codeproject.com 、2項專利。2016年,從台北科技大學華語文中心獲得國際漢語教學(TCSOL)認證。研究方向:數位影像處理。職稱是資深軟體技術顧問。

You may also be interested in...

Pro
Pro

Comments and Discussions

 
QuestionMessage Closed Pin
19-Jan-18 7:33
memberseo mians19-Jan-18 7:33 
QuestionFast - and faster? Pin
KarstenK28-May-17 8:42
memberKarstenK28-May-17 8:42 
GeneralMy vote of 5 Pin
Franc Morales1-Jul-16 1:26
memberFranc Morales1-Jul-16 1:26 
GeneralRe: My vote of 5 Pin
Mr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)3-Jul-16 23:23
professionalMr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)3-Jul-16 23:23 
AnswerExcellent, My vote of 5 Pin
Liju Sankar13-May-16 12:06
professionalLiju Sankar13-May-16 12:06 
GeneralRe: Excellent, My vote of 5 Pin
Mr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)15-May-16 17:47
professionalMr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)15-May-16 17:47 
GeneralMy vote of 5 Pin
Alexander Navalov7-May-16 1:45
professionalAlexander Navalov7-May-16 1:45 
GeneralRe: My vote of 5 Pin
Mr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)7-May-16 22:55
professionalMr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)7-May-16 22:55 
GeneralHere's another language / implementation using ANKHOR FlowSheet Pin
Alexander Golde5-May-16 23:52
memberAlexander Golde5-May-16 23:52 
GeneralRe: Here's another language / implementation using ANKHOR FlowSheet Pin
Mr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)6-May-16 1:04
professionalMr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)6-May-16 1:04 
QuestionSource code is available Pin
eslipak4-May-16 6:24
professionaleslipak4-May-16 6:24 
QuestionSource code is not available Pin
eslipak3-May-16 13:37
professionaleslipak3-May-16 13:37 
AnswerRe: Source code is not available Pin
Mr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)3-May-16 17:25
professionalMr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)3-May-16 17:25 
GeneralMy vote of 5 Pin
eslipak3-May-16 13:32
professionaleslipak3-May-16 13:32 
GeneralRe: My vote of 5 Pin
Mr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)3-May-16 17:27
professionalMr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)3-May-16 17:27 
SuggestionFast version of VB.NET using Pointer Pin
Mr. xieguigang 谢桂纲25-Apr-16 15:51
professionalMr. xieguigang 谢桂纲25-Apr-16 15:51 
GeneralRe: Fast version of VB.NET using Pointer Pin
Mr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)25-Apr-16 22:32
professionalMr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)25-Apr-16 22:32 
SuggestionYou can speed up your c# code Pin
napuzba25-Apr-16 5:46
membernapuzba25-Apr-16 5:46 
GeneralRe: You can speed up your c# code Pin
Mr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)25-Apr-16 7:34
professionalMr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)25-Apr-16 7:34 
GeneralMy vote of 1 Pin
ma_ma21-Apr-16 17:58
memberma_ma21-Apr-16 17:58 
GeneralRe: My vote of 1 Pin
CHill6024-Apr-16 4:18
protectorCHill6024-Apr-16 4:18 
GeneralRe: My vote of 1 Pin
ma_ma24-Apr-16 4:48
memberma_ma24-Apr-16 4:48 
GeneralRe: My vote of 1 Pin
CHill6024-Apr-16 5:07
protectorCHill6024-Apr-16 5:07 
GeneralRe: My vote of 1 Pin
ma_ma24-Apr-16 7:12
memberma_ma24-Apr-16 7:12 
GeneralRe: My vote of 1 Pin
Mr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)24-Apr-16 9:51
professionalMr. Lai Tai-Yu (Averill, Lai) (赖岱佑) (賴岱佑)24-Apr-16 9:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01-2016 | 2.8.180212.1 | Last Updated 4 May 2016
Article Copyright 2016 by Lai Tai Yu
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid