Sei sulla pagina 1di 12

Here is a code sample that loads a JPEG, changes any red pixels in the image to blue, and then

displays the bitmap in a picture box:


Bitmap bmp = (Bitmap)Bitmap.FromFile("image.jpg"); for (int x = 0; x < bmp.Width; x++) { for (int y = 0; y < bmp.Height; y++) { if (bmp.GetPixel(x, y) == Color.Red) { bmp.SetPixel(x, y, Color.Blue); } } } pictureBox1.Image = bmp;

Warning: GetPixel and SetPixel are incredibly slow. If your images are large and/or performance is an issue, there is a much faster way to read and write pixels in .NET, but it's a little bit more work.

Public Sub SetImageData(ByRef DstPictureBox As PictureBox, ByRef ImageData() As Byte, ByRef OldColor As Long, ByRef NewColor As Long) Dim X As Long, Y As Long For X = 0 To bm.bmHeight - 1 For Y = 0 To bm.bmHeight - 1 If OldColor = RGB(ImageData(2, X, Y), ImageData(1, X, Y), ImageData(0, X, Y)) Then RGBColor = RGBValues(NewColor) ImageData(2, X, Y) = RGBColor.Red ImageData(1, X, Y) = RGBColor.Green ImageData(0, X, Y) = RGBColor.Blue End If Next Y Next X 'Now that we've built the temporary header, we use StretchDIBits to take the data from the ImageData() array and put it into SrcPictureBox using the settings specified in 'bmi' (the StretchDIBits call should be on one continuous line) StretchDIBits DstPictureBox.hDC, 0, 0, bm.bmWidth, bm.bmHeight, 0, 0, bm.bmWidth, bm.bmHeight, ImageData(0, 0, 0), bmi, 0, vbSrcCopy 'Since this doesn't automatically initialize AutoRedraw, we have to do it manually 'Note: always keep AutoRedraw as 'True' when using DIB sections. Otherwise, you WILL get unpredictable results. If DstPictureBox.AutoRedraw = True Then DstPictureBox.Picture = DstPictureBox.Image DstPictureBox.Refresh

End If End Sub Private Function RGBValues(Color As Long) As Color 'find the rgb color values of a color Dim ReturnColor As Color With ReturnColor .Red = Fix(Color And 255) .Green = Fix((Color And 65535) / 256) .Blue = Fix(Color / 65536) End With RGBValues = ReturnColor End Function

'Routine to set an image's pixel information from an array dimensioned (rgb, x, y) Public Sub SetImageData(ByRef DstPictureBox As PictureBox, ByRef ImageData() As Byte, ByRef OldColor As Long, ByRef NewColor As Long) Dim X As Long, Y As Long RGBColor = RGBValues(NewColor) For X = 0 To bm.bmHeight - 1 For Y = 0 To bm.bmHeight - 1 If OldColor = RGB(ImageData(2, X, Y), ImageData(1, X, Y), ImageData(0, X, Y)) Then ImageData(2, X, Y) = RGBColor.Red ImageData(1, X, Y) = RGBColor.Green ImageData(0, X, Y) = RGBColor.Blue End If Next Y Next X 'Now that we've built the temporary header, we use StretchDIBits to take the data from the ImageData() array and put it into SrcPictureBox using the settings specified in 'bmi' (the StretchDIBits call should be on one continuous line) StretchDIBits DstPictureBox.hDC, 0, 0, bm.bmWidth, bm.bmHeight, 0, 0, bm.bmWidth, bm.bmHeight, ImageData(0, 0, 0), bmi, 0, vbSrcCopy 'Since this doesn't automatically initialize AutoRedraw, we have to do it manually 'Note: always keep AutoRedraw as 'True' when using DIB sections. Otherwise, you WILL get unpredictable results. If DstPictureBox.AutoRedraw = True Then DstPictureBox.Picture = DstPictureBox.Image DstPictureBox.Refresh End If End Sub

Instructions
1. 1 Create a new project by clicking "File" and "New Project." Select "Windows Form Project" from the dialog. 2. 2 Find the "PictureBox" control in the "Toolbox" panel and drag it into your project. 3. 3 Click the small arrow in the PictureBox control you just added and select "Choose Image." This will give you the standard file open dialog. Select an image file from your hard drive. 4. 4 Double-click the PictureBox to open the source code editor, and Visual Basic will automatically create an event for when the user clicks the picture. 5. 5 Paste the following code to open the image from the PictureBox:

dim bmp = new System.Drawing.Bitmap(PictureBox1.Image) 6. 6 Paste the following code to iterate through all the pixels in the image and alter them.

for x = 0 to bmp.Width - 1 for y = 0 to bmp.Height -1 dim c = bmp.getpixel(x,y)

c = Color.FromArgb(c.toArgb - 1) bmp.setPixel(x,y,c) next next

This code goes through each pixel and changes the color slightly each time the user clicks the picture, with the effect of the image getting slowly darker over time, eventually (after a few thousand clicks) fading to black.

Read more: How to Change BMP Color in Visual Basic | eHow.com http://www.ehow.com/how_7247211_change-bmp-color-visual-basic.html#ixzz16I9us1ti

Dim Shirt As Bitmap 'Holds the shirt sprite Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Shirt = New Bitmap("shirt.bmp") 'Load the shirt Shirt.MakeTransparent(Color.Black) 'Set the transparent End Sub Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint Dim Tile As New Rectangle(10, 10, 60, 60) 'Create a new rectanlge, this is used to draw the picture to the form Dim image_attr As New Imaging.ImageAttributes 'Used in changing colors Dim cm As ColorMatrix 'Also used for changing the colors cm = CreateMatrix(Color.BlueViolet) 'Create the Matrix, goes to function image_attr.SetColorMatrix(cm) 'Set the new Color matrix to the attributes

e.Graphics.DrawImage(Shirt, Tile, 0, 0, 60, 60, GraphicsUnit.Pixel, image_attr) 'Draw it to the form End Sub Private Function CreateMatrix(ByVal ToColor As Color) As ColorMatrix Dim R As Single = ToColor.R / 256 'Get the red color and convert it to a Single, (IE: 128 = 128/256 = .5) Dim G As Single = ToColor.G / 256 'Same as the red for the green Dim B As Single = ToColor.B / 256 'Same as red for the blue 'The code below creats the matrix. 'This code was found at http://vbhelper.com/howto_net_separate_rgb.html Dim cm As ColorMatrix cm = New ColorMatrix(New Single()() { _ New Single() {R, G, B, 0.0, 0.0}, New Single() {0.0, 0.0, 0.0, 0.0, New Single() {0.0, 0.0, 0.0, 0.0, New Single() {0.0, 0.0, 0.0, 1.0, New Single() {0.0, 0.0, 0.0, 0.0, Return cm End Function

_ 0.0}, _ 0.0}, _ 0.0}, _ 1.0}})

here's what the color filter code should look like from the puppy page link converted after slight readjustments.. this code doesn't seem to work too well with transparent backgrounds, but it's definately a start and should help you understand on how to modify the rest of the code, from c# to vb.net.. this should help...
temp As Bitmap = DirectCast(PictureBox1.Image, Bitmap) bmap As Bitmap = DirectCast(temp.Clone(), Bitmap) c As Color i As Integer = 0 To bmap.Width - 1 For j As Integer = 0 To bmap.Height - 1 c = bmap.GetPixel(i, j) Dim nPixelR As Integer = 0 Dim nPixelG As Integer = 0 Dim nPixelB As Integer = 0 '=========================================== 'if you want different color filters, just move the -255 to the second line, ', or the third one to the second line nPixelR = c.R - 255 nPixelG = c.G nPixelB = c.B - 255 'you can also change the numbers to your prefrences, or add numeric up/down with a max value of 255 'nPixelR = c.R - NumericUpDown1.Value Try Dim Dim Dim For

=========

'==================================================

nPixelR = Math.Max(nPixelR, 0) nPixelR = Math.Min(255, nPixelR) nPixelG = Math.Max(nPixelG, 0) nPixelG = Math.Min(255, nPixelG) nPixelB = Math.Max(nPixelB, 0) nPixelB = Math.Min(255, nPixelB) bmap.SetPixel(i, j, Color.FromArgb(CByte(nPixelR), CByte(nPixelG), CByte(nPixelB))) Next Next PictureBox1.Image = DirectCast(bmap.Clone(), Bitmap) Catch ex As Exception End Try

Code for entering and displaying an RGB color:


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim reply As String, R, G, B As Integer reply = InputBox("Enter value for Red") Integer.TryParse(reply, R) If R > 255 Then R = 255 reply = InputBox("Enter value for Green") Integer.TryParse(reply, G) If G > 255 Then G = 255 reply = InputBox("Enter value for Blue") Integer.TryParse(reply, B) If B > 255 Then B = 255 Button1.BackColor = Color.FromArgb(R, G, B) End Sub

Converting an RGB image to 1 bit-perpixel monochrome.


This article has been revised to use high-speed LockBits processing on both sides of the conversion and updated to include code in VB.NET.

One bit per pixel images are essentially an indexed format image having two entries in the colour palette. Unlike a GIF or other 256 colour indexed format which uses a single byte to access one of up-to 256 colours in the palette, the one bit per pixel format uses only a single bit to select colour A or colour B from the palette. Often used in Fax formats, one bit per pixel images are very compact with one byte of information representing eight pixels. Very often, a more complex RGB image can be used for the basic rawimage that is used to define the 1 bpp array but this operation in GDI+ and .NET systems is a little more complex than one would hope because you cannot simply get the Graphics object for an indexed image and draw on it. In order to do this conversion, you must manipulate the individual bits of the image by locking it's byte array and selecting the correct bit for the desired pixel. The LockBits method can be used to obtain a BitmapData object which contains the address of the bitmap in memory, the dimensions and particularly, the stride of the image. All images are stored in an array that fills memory to a four-byte boundary so the stride is used to calculate where each successive line begins in the array. A specific line may be addressed by the formula LineAddress=stride*linenumber and NOT LineAddress = pixeldepth*imagewidth*linenumber as many people assume. For our single bit per pixel image, the pixel indexing is further complicated by the need to select a specific bit in a byte that contains up to 8 pixels (it may have less than 8 pixels because it may be on the end of a scan-line). To perform this selection, a bit mask is used and

rotated into position so that the correct bit may be set or reset as desired. The simple application shown in listing 1 enables you to load any image into a PictureBox control situated on the left of the form. Once loaded, the image is scanned pixel by pixel to check the brightness of the colours contained in the image. If a pixel is darker than 50% brightness, a black pixel is set in the corresponding pixel of a black and white, single bit per pixel image stored in the rightmost PictureBox on the form. Between the two PictureBox controls, a Splitter enables you to see more or less of the original image for comparison with the converted one. Note in particular how the single bit per pixel image is created in the pictureBox1_Click handler and how the SetIndexedPixel method is used to access the individual pixel bits in the monochrome image.
using using using using using using using using using System; System.Drawing; System.Drawing.Drawing2D; System.Drawing.Imaging; System.Collections; System.ComponentModel; System.Windows.Forms; System.Data; System.Runtime.InteropServices;

namespace _1bitmap { /// <summary> /// Summary description for Form1. /// </summary> public class Form1 : System.Windows.Forms.Form { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // SetStyle(ControlStyles.ResizeRedraw,true);

/// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.splitter1 = new System.Windows.Forms.Splitter(); this.pictureBox2 = new System.Windows.Forms.PictureBox(); this.SuspendLayout(); // // pictureBox1 // this.pictureBox1.BackColor = System.Drawing.Color.White; this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Left; this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.Size = new System.Drawing.Size(100, 397); this.pictureBox1.TabIndex = 0; this.pictureBox1.TabStop = false; this.pictureBox1.Click += new System.EventHandler(this.pictureBox1_Click); // // splitter1 // this.splitter1.Location = new System.Drawing.Point(100, 0); this.splitter1.Name = "splitter1"; this.splitter1.Size = new System.Drawing.Size(3, 397); this.splitter1.TabIndex = 1; this.splitter1.TabStop = false; // // pictureBox2 // this.pictureBox2.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(128)), ((System.Byte) (255)), ((System.Byte)(255))); this.pictureBox2.Dock = System.Windows.Forms.DockStyle.Fill; this.pictureBox2.Location = new System.Drawing.Point(103, 0); this.pictureBox2.Name = "pictureBox2"; this.pictureBox2.Size = new System.Drawing.Size(473, 397); this.pictureBox2.TabIndex = 2; this.pictureBox2.TabStop = false;

// // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(576, 397); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.pictureBox2, this.splitter1, this.pictureBox1}); this.Name = "Form1"; this.Text = "Form1"; this.Load += new System.EventHandler(this.Form1_Load); this.ResumeLayout(false); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new Form1()); } protected void SetIndexedPixel(int x,int y,BitmapData bmd, bool pixel) { int index=y*bmd.Stride+(x>>3); byte p=Marshal.ReadByte(bmd.Scan0,index); byte mask=(byte)(0x80>>(x&0x7)); if(pixel) p |=mask; else p &=(byte)(mask^0xff); Marshal.WriteByte(bmd.Scan0,index,p); } private System.Windows.Forms.PictureBox pictureBox1; private System.Windows.Forms.Splitter splitter1; private System.Windows.Forms.PictureBox pictureBox2; Bitmap bm; private void Form1_Load(object sender, System.EventArgs e) { } private void pictureBox1_Click(object sender, System.EventArgs e) { //Load a file OpenFileDialog dlg = new OpenFileDialog(); dlg.Filter="Image files|*.bmp;*.gif;*.jpg"; if(dlg.ShowDialog()==DialogResult.OK) { Bitmap img = (Bitmap)Image.FromFile(dlg.FileName);

//Ensure that it's a 32 bit per pixel file if(img.PixelFormat!=PixelFormat.Format32bppPArgb) { Bitmap temp=new Bitmap(img.Width,img.Height,PixelFormat.Format32bppPArgb); Graphics g=Graphics.FromImage(temp); g.DrawImage(img, new Rectangle(0,0,img.Width,img.Height),0,0,img.Width,img.Height,GraphicsUn it.Pixel); img.Dispose(); g.Dispose(); img=temp; } this.pictureBox1.Image=img; //lock the bits of the original bitmap BitmapData bmdo=img.LockBits(new Rectangle(0,0,img.Width,img.Height),ImageLockMode.ReadOnly,img.PixelFor mat); //and the new 1bpp bitmap bm=new Bitmap(this.pictureBox1.Image.Width,this.pictureBox1.Image.Height,Pixel Format.Format1bppIndexed); BitmapData bmdn=bm.LockBits(new Rectangle(0,0,bm.Width,bm.Height),ImageLockMode.ReadWrite,PixelFormat.F ormat1bppIndexed); //for diagnostics DateTime dt=DateTime.Now; //scan through the pixels Y by X int x,y; for(y=0;y<img.Height;y++) { for(x=0;x<img.Width;x++) { //generate the address of the colour pixel int index=y*bmdo.Stride+(x*4); //check its brightness if(Color.FromArgb(Marshal.ReadByte(bmdo.Scan0,index+2), Marshal.ReadByte(bmdo.Scan0,index+1), ness()>0.5f) bright. } } Marshal.ReadByte(bmdo.Scan0,index)).GetBright this.SetIndexedPixel(x,y,bmdn,true); //set it if its

//tidy up bm.UnlockBits(bmdn); img.UnlockBits(bmdo); //show the time taken to do the conversion TimeSpan ts=dt-DateTime.Now; System.Diagnostics.Trace.WriteLine("Conversion time was:"+ts.ToString());

//display the 1bpp image. this.pictureBox2.Image=bm; } } } }

Figure 1 shows the application in action.

Return to the GDI+ FAQ.

Potrebbero piacerti anche