Convert color image to B&W

  • Thread starter Thread starter Scott Schluer
  • Start date Start date
S

Scott Schluer

Is there a way to use the Image class to convert a color photo (GIF or JPEG)
to a B&W photo?

Thanks,

Scott
 
hi Scott,
You can do something like this
fisrst convert the image to a bitmap and then call this function
Public Function ChangeToGreyScale(ByVal bmpImage As Bitmap) As Bitmap

Dim intX As Integer
Dim intY As Integer
Dim addRGB As Integer
Dim tmpColor As Color

' for each pixel
For intY = 3 To bmpImage.Height - 1
For intX = 3 To bmpImage.Width - 1

'average out the rgb
tmpColor = bmpImage.GetPixel(intX, intY)
addRGB = tmpColor.R
addRGB += tmpColor.G
addRGB += tmpColor.B
addRGB = addRGB / 3


' then set the values
bmpImage.SetPixel(intX, intY, Color.FromArgb(addRGB, addRGB,
addRGB))


Next
Next

''bmpImage.Save(strDestFileName,
System.Drawing.Imaging.ImageFormat.Jpeg)
Return bmpImage
End Function

HTH
srini
 
Hey thanks, that worked out pretty well. I'd like to expand on it a little
though. Here's the situation:

User uploads a color photo for an advertisement. Certain ads are black and
white, others are color. The client wants to receive ALL images in color,
however when it's displayed to the user on the Ad Confirmation screen, if
they've ordered a B&W ad, they should see it in B&W.

To me, the best way to accomplish this would just be to load the B&W image
in memory, bypassing any file system operations and then to assign the image
in memory to the ImageUrl property of the Image control. This way, the user
sees the B&W image that is loaded in memory, but the client receives the
original image in color.

I've used your function, along with another one that converts the Gif or
Jpeg image to Bitmap. Here is the other function:

Public Sub ConvertImage(ByVal Filename As String, _ ByVal DesiredFormat As
System.Drawing.Imaging.ImageFormat, _ ByVal NewFilename As String)
' Takes a filename and saves the file in a new format
Try
Dim imgFile As System.Drawing.Image = _
System.Drawing.Image.FromFile(Filename)
imgFile.Save(NewFilename, DesiredFormat)
Catch ex As Exception
Throw ex
End Try
End Sub

I have two problems with this setup:

1) I end up with 3 files for every one uploaded (the original color, the
converted BitMap, the resultant greyscale image).
2) There seems to be a lock on the original image file once this conversion
has taken place. It cannot be overwritten after these functions are run.

What would I need to change in these two functions so that I can take a
color image on the file system, convert it to BitMap and then GreyScale in
memory, then assign that image in memory to the ImageUrl property of the
Image control? I'll be researching this on my own also, but I figured I'd
ask here as well, just in case. ;-)

Thanks,

Scott
 
Hi Scott,

Dynamically-generating an image with each request is going to be far more
expensive than getting an image from a file. Your best bet would be to do a
B&W version of the image in whatever tool, and save it as a file.

--
HTH,
Kevin Spencer
..Net Developer
Microsoft MVP
I get paid good money to
solve puzzles for a living
 
I don't anticipate heavy usage here. Maybe 5-10 operations per day tops. Is
that worth it (I figured out how to do the dynamic image generation and it's
now working as I want it to).

My question I guess, if I were to use a file would be this:

I create the new B&W file and set the ImageUrl property of the Image control
to my new file. How do I delete it after the page displays? I don't want a
huge mess of B&W photos sitting on the server.

Thanks,

Scott
 
I answered my own question:

In the page that will be displaying the photo:

Select Case (Request.QueryString("id"))
Case "4", "5", "6", "7" ' If the ad is a B&W advertisement, send it to
photo.aspx for conversion to B&W
imgPhoto.ImageUrl = "photo.aspx?location=" &
Server.URLEncode(ViewState("FileName"))
Case Else ' THe ad is a color advertisement and the image can be displayed
as uploaded
imgPhoto.ImageUrl = "/adimages/" & Session.SessionID & "_" &
CStr(objCart.ProductCount() + 1 &
System.IO.Path.GetExtension(filPhoto.PostedFile.Filename))
End Select

Photo.aspx:

<%@ Page %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %>

<script language="vb" runat="server">
Public Sub Page_Load(obj As Object, e As EventArgs)
Dim img As System.Drawing.Image =
System.Drawing.Image.FromFile(Request.QueryString("location"))
Dim BMP As System.Drawing.BitMap = New System.Drawing.BitMap(img)
ChangeToGreyScale(BMP)

Dim strExtension =
System.IO.Path.GetExtension(Request.QueryString("location"))

Select Case (strExtension)
Case ".jpg", ".jpeg", "jpg", "jpeg"
Response.ContentType = "image/jpeg"
BMP.Save(Response.OutputStream, ImageFormat.Jpeg)
Case ".gif", "gif"
Response.ContentType = "image/gif"
BMP.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif)
End Select

BMP.Dispose()
img.Dispose()

BMP = Nothing
img = Nothing
GC.Collect()
End Sub

Public Sub ChangeToGreyScale(ByRef bmpImage As Bitmap)
Dim intX As Integer
Dim intY As Integer
Dim addRGB As Integer
Dim tmpColor As Color

' for each pixel
For intY = 3 To bmpImage.Height - 1
For intX = 3 To bmpImage.Width - 1

'average out the rgb
tmpColor = bmpImage.GetPixel(intX, intY)
addRGB = tmpColor.R
addRGB += tmpColor.G
addRGB += tmpColor.B
addRGB = addRGB / 3


' then set the values
bmpImage.SetPixel(intX, intY, Color.FromArgb(addRGB, addRGB,
addRGB))
Next
Next
End Sub
</script>
 
I create the new B&W file and set the ImageUrl property of the Image
control
to my new file. How do I delete it after the page displays? I don't want a
huge mess of B&W photos sitting on the server.

Well, the choice is yours, as to whether you want to use HD space or
processor and memory. My point was that, in order to convert a color image
to B&W, you STILL have to open a file (the color image), then process it and
create a B&W image on the fly, whereas if you simply stored B&W images, the
only part of that mess you'd have to support is the file IO (open the file
and display it). However, if HD space is more important to you, by all
means, it is your app.

--
HTH,
Kevin Spencer
..Net Developer
Microsoft MVP
I get paid good money to
solve puzzles for a living
 
If you really want to do this, it is very slow to change every pixel of an
image using the Bitmap.GetPixel() method. This is one of those rare
situations where a bit of unsafe code would speed things up tremendously.
You can create a pointer to the first pixel, and loop through them, setting
their values very quickly. Of course, that would require C#. But the
difference in performance is incredible.

--
HTH,
Kevin Spencer
..Net Developer
Microsoft MVP
I get paid good money to
solve puzzles for a living
 
Back
Top