Adjust the contrast of an image in C# efficiently
solution for above question is not working in vb 2005
i need solution in vb2005
this is c# code below
public static Bitmap AdjustContrast(Bitmap Image, float Value)
{
Value = (100.0f + Value) / 100.0f;
Value *= Value;
Bitmap NewBitmap = (Bitmap)Image.Clone();
BitmapData data = NewBitmap.LockBits(
new Rectangle(0, 0, NewBitmap.Width, NewBitmap.Height),
ImageLockMode.ReadWrite,
NewBitmap.PixelFormat);
unsafe
{
for (int y = 0; y < NewBitmap.Height; ++y)
{
byte* row = (byte*)data.Scan0 + (y * data.Stride);
int columnOffset = 0;
for (int x = 0; x < NewBitmap.Width; ++x)
{
byte B = row[columnOffset];
byte G = row[columnOffset + 1];
byte R = row[columnOffset + 2];
float Red = R / 255.0f;
float Green = G / 255.0f;
float Blue = B / 255.0f;
Red = (((Red - 0.5f) * Value) + 0.5f) * 255.0f;
Green = (((Green - 0.5f) * Value) + 0.5f) * 255.0f;
Blue = (((Blue - 0.5f) * Value) + 0.5f) * 255.0f;
int iR = (int)Red;
iR = iR > 255 ? 255 : iR;
iR = iR < 0 ? 0 : iR;
int iG = (int)Green;
iG = iG > 255 ? 255 : iG;
iG = iG < 0 ? 0 : iG;
int iB = (int)Blue;
iB = iB > 255 ? 255 : iB;
iB = iB < 0 ? 0 : iB;
row[columnOffset] = (byte)iB;
row[columnOffset + 1] = (byte)iG;
row[columnOffset + 2] = (byte)iR;
columnOffset += 4;
}
}
}
NewBitmap.UnlockBits(data);
return NewBitmap;
}
& here is vb2005 code
Public Shared Function AdjustContrast(Image As Bitmap, Value As Single) As Bitmap
Value = (100F + Value) / 100F
Value *= Value
Dim NewBitmap As Bitmap = DirectCast(Image.Clone(), Bitmap)
Dim data As BitmapData = NewBitmap.LockBits(New Rectangle(0, 0, NewBitmap.Width, NewBitmap.Height), ImageLockMode.ReadWrite, NewBitmap.PixelFormat)
For y As Integer = 0 To NewBitmap.Height - 1
Dim row As Pointer(Of Byte) = CType(data.Scan0, Pointer(Of Byte)) + (y * data.Stride)
Dim columnOffset As Integer = 0
For x As Integer = 0 To NewBitmap.Width - 1
Dim B As Byte = row(columnOffset)
Dim G As Byte = row(columnOffset + 1)
Dim R As Byte = row(columnOffset + 2)
Dim Red As Single = R / 255F
Dim Green As Single = G / 255F
Dim Blue As Single = B / 255F
Red = (((Red - 0.5F) * Value) + 0.5F) * 255F
Green = (((Green - 0.5F) * Value) + 0.5F) * 255F
Blue = (((Blue - 0.5F) * Value) + 0.5F) * 255F
Dim iR As Integer = CInt(Red)
iR = If(iR > 255, 255, iR)
iR = If(iR < 0, 0, iR)
Dim iG As Integer = CInt(Green)
iG = If(iG > 255, 255, iG)
iG = If(iG < 0, 0, iG)
Dim iB As Integer = CInt(Blue)
iB = If(iB > 255, 255, iB)
iB = If(iB < 0, 0, iB)
row(columnOffset) = CByte(iB)
row(columnOffset + 1) = CByte(iG)
row(columnOffset + 2) = CByte(iR)
columnOffset += 4
Next
Next
NewBitmap.UnlockBits(data)
Return NewBitmap
End Function
Dim row As Pointer(Of Byte) = CType(data.Scan0, Pointer(Of Byte)) + (y * data.Stride)
above line gives error since vb does not support
Dim row As Pointer(Of Byte)
Here's my attempt at the conversion. I'm using the IntPtr data structure to handle holding the unmanged pointer and to do the pointer addition to get an IntPtr for each row. Then as it goes through the row, I'm using the Marshal.ReadByte and Marshal.WriteByte methods to handle reading and writing the unmanaged data. I tested and it seems to work.
value = (100.0F + value) / 100.0F
value *= value
Dim NewBitmap As Bitmap = DirectCast(Image.Clone(), Bitmap)
Dim data As BitmapData = NewBitmap.LockBits(New Rectangle(0, 0, NewBitmap.Width, NewBitmap.Height), ImageLockMode.ReadWrite, NewBitmap.PixelFormat)
For y As Integer = 0 To NewBitmap.Height - 1
Dim RowPtr = IntPtr.Add(data.Scan0, y * data.Stride)
Dim columnOffset As Integer = 0
For x As Integer = 0 To NewBitmap.Width - 1
Dim B As Byte = System.Runtime.InteropServices.Marshal.ReadByte(RowPtr, columnOffset)
Dim G As Byte = System.Runtime.InteropServices.Marshal.ReadByte(RowPtr, columnOffset + 1)
Dim R As Byte = System.Runtime.InteropServices.Marshal.ReadByte(RowPtr, columnOffset + 2)
Dim Red As Single = R / 255.0F
Dim Green As Single = G / 255.0F
Dim Blue As Single = B / 255.0F
Red = (((Red - 0.5F) * value) + 0.5F) * 255.0F
Green = (((Green - 0.5F) * value) + 0.5F) * 255.0F
Blue = (((Blue - 0.5F) * value) + 0.5F) * 255.0F
Dim iR As Integer = CInt(Red)
iR = If(iR > 255, 255, iR)
iR = If(iR < 0, 0, iR)
Dim iG As Integer = CInt(Green)
iG = If(iG > 255, 255, iG)
iG = If(iG < 0, 0, iG)
Dim iB As Integer = CInt(Blue)
iB = If(iB > 255, 255, iB)
iB = If(iB < 0, 0, iB)
System.Runtime.InteropServices.Marshal.WriteByte(RowPtr, columnOffset, CByte(iB))
System.Runtime.InteropServices.Marshal.WriteByte(RowPtr, columnOffset + 1, CByte(iG))
System.Runtime.InteropServices.Marshal.WriteByte(RowPtr, columnOffset + 2, CByte(iR))
columnOffset += 4
Next
Next
NewBitmap.UnlockBits(data)
Related
I want to change the red pixels to blue. The image is 24 bits .bmp. I am using lockbits because it is faster but the code doesnt find the red pixels!
Code:
Dim bmp As Bitmap = New Bitmap("path")
Dim pos As Integer
Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits _
(rect, Drawing.Imaging.ImageLockMode.ReadWrite,
bmp.PixelFormat)
Dim ptr As IntPtr = bmpData.Scan0
Dim bytes As Integer = Math.Abs(bmpData.Stride) * bmp.Height
Dim rgbValues(bytes - 1) As Byte
Marshal.Copy(ptr, rgbValues, 0, bytes)
For y = 0 To bmp.Height - 1
For x = 0 To bmp.Width - 1
pos = y * bmp.Width * 3 + x * 3
If rgbValues(pos) = 255 And rgbValues(pos + 1) = 0 And rgbValues(pos + 2) = 0 Then
rgbValues(pos + 2) = 255
rgbValues(pos) = 0
End If
Next
Next
Marshal.Copy(rgbValues, 0, ptr, bytes)
bmp.UnlockBits(bmpData)
bmp.Save("new path")
Thank you!
The values that are stored in rgbValues are not in this order
R G B R G B.....
but
B G R B G R.....
so the correct code in your loop is:
' B G R
If rgbValues(pos) = 0 And rgbValues(pos + 1) = 0 And rgbValues(pos + 2) = 255 Then
rgbValues(pos + 2) = 0 'R
rgbValues(pos) = 255 'B
End If
Im looking for a way to detect the center of grid squares when VB.net is feed an image
I want to start with an image of a grid with blue squares like this:
Grid
and i want the program to make an array of points in the center of each square like this (points aren't centered in picture)
Grid with Red points
i dont want to modify the image, i just want to get the points. I've tried getpixel for x and y but that just returns the same point
Dim search_color As Color = Color.FromArgb(255, 64, 128, 192)
Dim background_color As Color = Color.FromArgb(255, 240, 240, 240)
Dim grid_color As Color = Color.FromArgb(255, 144, 144, 144)
Dim pix As Color
Dim liney = 0, linex = 0
Dim loc, sloc, gloc As Point
For ch As Integer = 1 To 64
For y As Integer = liney To Bmp.Height - 1
For x As Integer = linex To Bmp.Width - 1
If Bmp.GetPixel(x, y) = search_color Then
sloc = New Point(x, y)
linex = x
liney = y
x = Bmp.Width - 1
y = Bmp.Height - 1
End If
Next
Next
Dim xloc = 0
For x As Integer = sloc.X To Bmp.Width - 1
If Bmp.GetPixel(x, sloc.Y) = grid_color Then
xloc = x - 1
End If
If Bmp.GetPixel(x, sloc.Y) = background_color Then
xloc = x - 1
End If
Next
For y As Integer = sloc.Y To Bmp.Height - 1
If Bmp.GetPixel(xloc, y) = grid_color Or Bmp.GetPixel(xloc, y) = background_color Then
gloc = New Point(xloc, y - 1)
End If
Next
loc = New Point((gloc.X + sloc.X) / 2, (gloc.Y + sloc.Y) / 2)
liney = gloc.Y
linex = gloc.X + 20
ListBox1.Items.Add(loc.ToString)
Next
Try this:
I added the following controls to a form to test the code:
pbImageToScan (PictureBox) - btnAnalyzeIMG (Button) - lbResult (ListBox)
Public Class Form1
Dim arrCenters() As Point
Dim bmpToAnalyze As Bitmap
Dim search_color As Color = Color.FromArgb(255, 64, 128, 192)
Dim background_color As Color = Color.FromArgb(255, 240, 240, 240)
Dim grid_color As Color = Color.FromArgb(255, 144, 144, 144)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
bmpToAnalyze = New Bitmap(Application.StartupPath & "\Image.bmp")
pbImageToScan.Image = Image.FromFile(Application.StartupPath & "\Image.bmp")
End Sub
Private Sub btnAnalyzeIMG_Click(sender As Object, e As EventArgs) Handles btnAnalyzeIMG.Click
FindCenters()
End Sub
Private Sub FindCenters()
bmpToAnalyze = New Bitmap(Application.StartupPath & "\Image.bmp")
pbImageToScan.Image = Image.FromFile(Application.StartupPath & "\Image.bmp")
'arrCenters is the array who will contains all centers data
ReDim arrCenters(0)
'arrCenters already starts with an element; this boolean is used to handle the first point insertion
Dim bFirstElementAddedToArray As Boolean
lbResult.Items.Clear()
Dim iIMGWidth As Integer = bmpToAnalyze.Width
Dim iIMGHeight As Integer = bmpToAnalyze.Height
'X, Y coordinates used for iterations
Dim iX As Integer = 0
Dim iY As Integer = 0
'Bitmap limits reached
Dim bExit As Boolean
'Used to skip a great part of Ys, if a match has been found along the current examinated line
Dim iDeltaYMax As Integer = 0
'Main cycle
Do While Not bExit
Dim colCurrentColor As Color = bmpToAnalyze.GetPixel(iX, iY)
If colCurrentColor = search_color Then
Dim iXStart As Integer = iX
Dim iYStart As Integer = iY
Dim iXEnd As Integer
Dim iYEnd As Integer
'Width of the Blue square
For iXEnd = iX + 1 To iIMGWidth - 1
Dim colColorSearchX As Color = bmpToAnalyze.GetPixel(iXEnd, iY)
If (colColorSearchX = background_color) Or (colColorSearchX = grid_color) Then
iXEnd -= 1
Exit For
End If
Next
'Height of the Blue square
For iYEnd = iY + 1 To iIMGHeight - 1
Dim colColorSearchY As Color = bmpToAnalyze.GetPixel(iXEnd, iYEnd)
If (colColorSearchY = background_color) Or (colColorSearchY = grid_color) Then
iYEnd -= 1
Exit For
End If
Next
iDeltaYMax = iYEnd - iYStart
'Blue square center coordinates
Dim pCenter As New Point((iXStart + iXEnd) / 2, (iYStart + iYEnd) / 2)
Dim iArrLenght As Integer = 0
If Not bFirstElementAddedToArray Then
bFirstElementAddedToArray = True
Else
iArrLenght = arrCenters.GetLength(0)
ReDim Preserve arrCenters(iArrLenght)
End If
arrCenters(iArrLenght) = pCenter
lbResult.Items.Add(pCenter.ToString)
iX = iXEnd
'Checks if the Width limit of the bitmap has been reached
If iX = (iIMGWidth - 1) Then
iX = 0
iY += iDeltaYMax + 1
iDeltaYMax = 0
Else
iX += 1
End If
Else
'Checks if the Width limit of the bitmap has been reached
If iX = (iIMGWidth - 1) Then
iX = 0
iY += iDeltaYMax + 1
iDeltaYMax = 0
Else
iX += 1
End If
End If
'Width and Height limit of the bitmap have been reached
If (iX = iIMGWidth - 1) And (iY = iIMGHeight - 1) Then
bExit = True
End If
Loop
'Draws a Red point on every center found
For Each P As Point In arrCenters
bmpToAnalyze.SetPixel(P.X, P.Y, Color.Red)
Next
pbImageToScan.Image = bmpToAnalyze
End Sub
End Class
I'm Using Visual studio 10.i want to convert colored image into a black and white?
i have tried to do following code it gets success but it takes lots of time to convert. can i do convert it without using anyloop in vb.net.
Thanks In Advance
Try
Dim img As Bitmap = New Bitmap((Image.FromFile("D:\\imgnam.jpg")))
Dim c As Color
Dim i As Integer = 0
Do While (i < img.Width)
Dim j As Integer = 0
Do While (j < img.Height)
c = img.GetPixel(i, j)
Dim r As Integer = 0
r = Convert.ToInt16(c.R)
Dim g As Integer = 0
g = Convert.ToInt16(c.G)
Dim b As Integer = 0
b = Convert.ToInt16(c.B)
Dim ans As Integer = ((r _
+ (g + b)) _
/ 3)
If (ans > 128) Then
r = 255
g = 255
b = 255
Else
r = 0
g = 0
b = 0
End If
c = Color.FromArgb(r, g, b)
img.SetPixel(i, j, c)
j = (j + 1)
Loop
i = (i + 1)
Loop
img.Save("D:\\imgnamNew.jpg")
Dim Bmp1 As New Image(Of Bgr, [Byte])("D:\\imgnamNew.jpg")
ImageFrame = Bmp1
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
How would I go about reducing the latency of grabbing an image from Picturebox then emboss that image and return you picturebox as this is a camera handle and will need to capture/emboss at least 16 fps but i'm getting like 1 every 2.5 seconds
SwitchImageSave = 1
Button1.Enabled = False
StCam.StopTransfer(m_hCamera)
Dim nReval As Integer
Dim nLastErrorNo As Integer
Dim nBufferSize As Integer
Dim dwWidth As Integer
Dim dwHeight As Integer
Dim dwLinePitch As Integer
nReval = StCam.GetPreviewDataSize(m_hCamera, nBufferSize, dwWidth, dwHeight, dwLinePitch)
Dim dwPreviewPixelFormat As Integer
nReval = StCam.GetPreviewPixelFormat(m_hCamera, dwPreviewPixelFormat)
Dim pixelFormat As Imaging.PixelFormat = Imaging.PixelFormat.Format8bppIndexed
Select Case dwPreviewPixelFormat
Case StCam.STCAM_PIXEL_FORMAT_24_BGR
pixelFormat = Imaging.PixelFormat.Format24bppRgb
Case StCam.STCAM_PIXEL_FORMAT_32_BGR
pixelFormat = Imaging.PixelFormat.Format32bppRgb
End Select
Dim pbyteImageBuffer(nBufferSize) As Byte
Dim dwNumberOfByteTrans As Integer = 0
Dim pdwFrameNo(1) As Integer
Dim dwMilliseconds As Integer = 100
Dim gch As System.Runtime.InteropServices.GCHandle = System.Runtime.InteropServices.GCHandle.Alloc(pbyteImageBuffer, System.Runtime.InteropServices.GCHandleType.Pinned)
Dim ptr As IntPtr = gch.AddrOfPinnedObject()
nReval = StCam.TakePreviewSnapShot(m_hCamera, ptr, nBufferSize, dwNumberOfByteTrans, pdwFrameNo, dwMilliseconds)
gch.Free()
Dim bitmap As Bitmap = New Bitmap(dwWidth, dwHeight, pixelFormat)
Select Case pixelFormat
Case Imaging.PixelFormat.Format8bppIndexed
Dim colorPalette As System.Drawing.Imaging.ColorPalette = bitmap.Palette
For pixelValue As Integer = 0 To 255
colorPalette.Entries(pixelValue) = Color.FromArgb(pixelValue, pixelValue, pixelValue)
Next
bitmap.Palette = colorPalette
End Select
Dim bitmapData As Imaging.BitmapData = bitmap.LockBits(New Rectangle(0, 0, dwWidth, dwHeight), Imaging.ImageLockMode.WriteOnly, pixelFormat)
Runtime.InteropServices.Marshal.Copy(pbyteImageBuffer, 0, bitmapData.Scan0(), nBufferSize)
bitmap.UnlockBits(bitmapData)
Dim bmap As Bitmap
bmap = New Bitmap(bitmap)
PictureBox2.Image = bmap
' PictureBox2.Image = bmap
Dim tempbmp As New Bitmap(bmap)
Dim i, j As Integer
Dim DispX As Integer = 1, DispY As Integer = 1
Dim red, green, blue As Integer
With tempbmp
For i = 0 To .Height - 2
For j = 0 To .Width - 2
Dim pixel1, pixel2 As System.Drawing.Color
pixel1 = .GetPixel(j, i)
pixel2 = .GetPixel(j + DispX, i + DispY)
red = Math.Min(Math.Abs(CInt(pixel1.R) - CInt(pixel2.R)) + 128, 255)
green = Math.Min(Math.Abs(CInt(pixel1.G) - CInt(pixel2.G)) + 128, 255)
blue = Math.Min(Math.Abs(CInt(pixel1.B) - CInt(pixel2.B)) + 128, 255)
bmap.SetPixel(j, i, Color.FromArgb(red, green, blue))
Next
Next
End With
PictureBox2.Image = bmap
PictureBox2.Refresh()
PictureBox2.BringToFront()
Dim bitmapData As Imaging.BitmapData = bitmap.LockBits(New Rectangle(0, 0, dwWidth, dwHeight), Imaging.ImageLockMode.WriteOnly, pixelFormat)
Runtime.InteropServices.Marshal.Copy(pbyteImageBuffer, 0, bitmapData.Scan0(), nBufferSize)
bitmap.UnlockBits(bitmapData)
PictureBox2.Image = bitmap
Dim temp As Bitmap = PictureBox2.Image
Dim raz As Integer = temp.Height / 4
Dim height As Integer = temp.Height
Dim width As Integer = temp.Width
Dim rect As New Rectangle(Point.Empty, temp.Size)
Dim bmpData As BitmapData = temp.LockBits(rect, ImageLockMode.[ReadOnly], temp.PixelFormat)
Dim bpp As Integer = If((temp.PixelFormat = PixelFormat.Format32bppArgb), 4, 3)
Dim size As Integer = bmpData.Stride * bmpData.Height
Dim data As Byte() = New Byte(size - 1) {}
'byte[] newdata = new byte[size];
System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, data, 0, size)
'System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, newdata, 0, size);
Dim options = New ParallelOptions()
Dim maxCore As Integer = Environment.ProcessorCount - 1
options.MaxDegreeOfParallelism = If(maxCore > 0, maxCore, 1)
For y As Integer = 0 To height - 4
For x As Integer = 0 To width - 4
If True Then
Dim index As Integer = y * bmpData.Stride + x * bpp
'Blue
data(index) = CByte(Math.Min(Math.Abs(CInt(data(index)) - CInt(data(index + bpp + bmpData.Stride))) + 128, 255))
'Green
data(index + 1) = CByte(Math.Min(Math.Abs(CInt(data(index + 1)) - CInt(data(index + bpp + 1 + bmpData.Stride))) + 128, 255))
'Red
data(index + 2) = CByte(Math.Min(Math.Abs(CInt(data(index + 2)) - CInt(data(index + bpp + 2 + bmpData.Stride))) + 128, 255))
End If
Next
Next
I'm having problems with sliding a variable sized window over a 2D array in vb.net. my porblem is when I take the first element of the array at 0,0 what ever the size of the window is it needs to be smaller because the element in question has to be the center of the sliding window. ex: arrar size(40,43) window size 5x5 ( window size is NxN N=3 wins size is 3x3) so array(0,0) with win size 5 so 2 col and 2 rows need to be cout out and a new window size of 3x3. any help would be great.`
Public Function getPIXELSinWINDOW(ByVal Wsize As Integer, ByVal x As Integer, ByVal y As Integer)
Dim tempARRAY As New ArrayList()
Dim Xwidth As Integer = Wsize
Dim Yheight As Integer = Wsize
Dim Xvalue As Integer = x - Wsize / 2
Dim Yvalue As Integer = y - Wsize / 2
Dim imgHEIGHT As Integer = Me.mysize.Height
Dim imgWIDTH As Integer = Me.mysize.Width
Dim i, j As Integer
While Xvalue < 0
Xvalue += 1
Xwidth -= 1
End While
While Xvalue > imgWIDTH
Xvalue -= 1
Xwidth -= 1
End While
While Xwidth >= imgWIDTH
Xwidth -= 1
End While
While Xvalue + Xwidth > imgWIDTH
Xwidth -= 1
End While
While Yvalue < 0
Yvalue += 1
Yheight -= 1
End While
While Yvalue > imgHEIGHT
Yvalue -= 1
Yheight -= 1
End While
While Yheight >= imgHEIGHT
Yheight -= 1
End While
While Yvalue + Yheight > imgHEIGHT
Yheight -= 1
End While
For i = Xvalue To Xvalue + Xwidth
For j = Yvalue To Yvalue + Yheight
tempARRAY.Add(pixels(j, i))
Next
Next
Return tempARRAY
End Function
the var pixels is the 2d array
Something like this?
public class MainClass
{
public static void Main (string[] args)
{
MainClass mc = new MainClass();
List<int> pix = mc.GetPixelsInWindow(5, 40, 43);
}
private int[,] data = new int[40, 43];
public List<int> GetPixelsInWindow(int windowSize, int xPoint, int yPoint)
{
// As we are dealing with integers, this will result in a truncated value,
// so a windowSize of 5 will yield a windowDelta of 2.
int windowDelta = windowSize / 2;
List<int> pixels = new List<int>();
int xMin = Math.Max(0, xPoint - windowDelta);
int xMax = Math.Min(data.GetLength(0) - 1, xPoint + windowDelta);
int yMin = Math.Max(0, yPoint - windowDelta);
int yMax = Math.Min(data.GetLength(1) - 1, yPoint + windowDelta);
for (int x = xMin; x <= xMax; x++)
{
for (int y = yMin; y <= yMax; y++)
{
Console.WriteLine("Getting pixel (" + x.ToString() + ", " + y.ToString() + ")...");
pixels.Add(data[x, y]);
}
}
return pixels;
}
}