Subscribe to RSS Feed

Your source for C# and ASP.NET software developmet

Fading Images Together using C#

I recently began a project that required me to fade two images together.

When I say "fade," I mean that I want to color an image based on another. Some people call this blending, or simply layering one image on top of the other and setting the opacity/transparency of the upper image. I'm not really sure what the formal term for it is, but this is basically accomplished by averaging the pixel values between the two images where they overlap. Don't be intimidated if you're unfamiliar with images or pixels - read on. The effect produced is pretty cool.

Up until now, I hadn't used any image manipulation classes in .NET, but I had done some simple image splicing in Java (using the excellent Graphics package). So, I was excited to see what facilities were going to be provided by .NET for doing similar operations. Honestly, I didn't even know what class to use, so I set out by dropping a PictureBox control onto a Windows Forms application. One of the properties I saw in the Property Editor for this control was the Image property, which was of type System.Drawing.Image. Bingo!

I switch to my C# code and set about creating an Image instance. Now, if I know the .NET framework (and I do), I'd be willing to bet System.Drawing.Image is an abstract base class, but its a good starting point nonetheless. Indeed, creating an instance using the new keyword fails because, as expected, it is an abstract class.

Trying to create an Image instance

The next thing I generally do is check to see if there is a static Factory method within the base class that will create an instance for me. I type Image. (note the dot) and let Visual Studio's Intellisense go to work for me.

Intellisense for System.Drawing.Image

It looks like the FromFile() method will do what I want. I call this method with the filename of an existing image, and move on to the next line. Again, I will use my trusty Intellisense to find out what I can do with this Image object. To my horror, I find that the Image class does not provide me any information about the pixels (individual colored dots) in the underlying image, nor does it show the robust list of image transformations I expected to be able to perform. Hell, it doesn't even let you set the Width and Height properties. Who are you, and what have you done with .NET?

This is obviously going to take a little bit more research. You might've noticed in the first screenshot that the abstract Image class provides functionality for its descendants (as is the purpose of an abstract class), including System.Drawing.Bitmap. I was in a sporting mood, so I decided to check out the class hierarchy. Normally, this would be done using a combination of the Object Browser and the Image class summary, which gives us the hint that its descendent classes are System.Drawing.Bitmap and System.Drawing.Imaging.Metafile. However, an addin I use called Resharper allows me to right click on the Image class in my code and find all types that derive from it, like so:

Types derived from Image

This confirms that Bitmap and Metafile are the only classes that inherit from Image in the .NET framework. I refer to the Object Browser again to inspect these classes, starting with Bitmap.

Bitmap Class in the Object Browser

From this, I can see that the Bitmap class is intended to be used where it is necessary to work with pixel data, and also that it has methods for getting and setting individual pixels (as well as some of the other more complicated image manipulation behavior I expected to see in Image). This looks promising, so I can move forward from here by instantiating both of my Images as Bitmaps, and attempting to fade their pixel data together.

Given that I have two Bitmap objects that I want to fade together, aptly named image1 and image2, I can use the following code to "average" the overlapping area of the images:

            for (int i = 0; i < image1.Width &amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp; i < image2.Width; i++)
            {
                for (int j = 0; j < image1.Height &amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp; j < image2.Height; j++)
                {
                    Color image1Pixel = image1.GetPixel(i, j), image2Pixel = image2.GetPixel(i, j);
                    Color newColor = Color.FromArgb((image1Pixel.R + image2Pixel.R)/2, (image1Pixel.G + image2Pixel.G)/2, (image1Pixel.B + image2Pixel.B)/2);
                    image1.SetPixel(i, j, newColor);
                }
            }

Let me walk you through what's going on here. Each Bitmap is essentially a two-dimensional array of pixels (represented in your code by a System.Drawing.Color object). Thus, we use a nested loop to iterate through them. Note that our for loop will only proceed while both i and j are within the bounds of both images. This will make our code look a little nice by not requiring us to check if each pixel we extract is within its image's bounds (the code can be easily extended to handle non-overlapping areas, if required). Anyway, within our loops, we extract the pixels present in both images at our current position to Color objects by calling GetPixel(i,j) on each image. Then, we construct a new Color object using the Color.Argb() factory method. The overload of the Argb() method I used takes in three integer parameters: a red, a green, and a blue, to determine the overall color of the pixel. These are given by the R, G, and B integer properties of the two Color objects we created, so we simply average them, respectively. Finally, we set the pixel value at that location with this new Color object (I arbitrarily chose to do so in image1 here, overwriting its contents).

Simply enough, yes? This will give us a nice overall average for the two images, or what I'm calling the "fade" effect. Since this worked out so nicely, what if we got a little bit deeper? The project I'm doing actually requires my "fade" effect to be weighted heavily in favor of one of the images, which is the same as giving less transparency to the image that is laid on top of the other. I know that my idea of averaging the two pixel values worked out just fine, so I should be able to calculate a weighted average just as easily, given some parameter to tell me how strongly to do so.

I extracted this code to a static method in another class. It could've been done simply with a helper method, or by subclassing Bitmap, but I prefer to have this helper class present in case I decide to add any further functionality. I specify that I'll take two Bitmap objects and an integer parameter, which will represent how heavily to weight the first image over the second. I have also changed the code to be slightly more "proper," in that I create a new Bitmap object instead of changing image1's data. Finally, you'll see that I compute the new RGB values using a weighted average algorithm, where the original values are multiplied by their weights and their sum is divided by the total weight.

I thought for a moment here about whether or not I could get an integer overflow here. However, it turns out that image file formats store, at most, 32-bits of information per pixel. Since these 32-bits are divided up across the red, green, and blue components of the pixel, we are usually going to be working with 8-bit integers (which range from 0-255). The int data type is 32-bit, so we should never run into this problem.

The updated code looks like this:

        public static Bitmap Fade(Bitmap image1, Bitmap image2, int opacity)
        {
            Bitmap newBmp = new Bitmap(Math.Min(image1.Width,image2.Width), Math.Min(image1.Height,image2.Height));
            for (int i = 0; i < image1.Width &amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp; i < image2.Width; i++)
            {
                for (int j = 0; j < image1.Height &amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp; j < image2.Height; j++)
                {
                    Color image1Pixel = image1.GetPixel(i, j), image2Pixel = image2.GetPixel(i, j);
                    Color newColor = Color.FromArgb( (image1Pixel.R * opacity + image2Pixel.R * (100 - opacity) ) / 100, (image1Pixel.G * opacity + image2Pixel.G * (100 - opacity) ) / 100, (image1Pixel.B * opacity + image2Pixel.B * (100 - opacity) ) / 100);
                    newBmp.SetPixel(i, j, newColor);
                }
            }
            return newBmp;
        }

One thing to note in the code that will call this method is that you no longer need to use the Image.FromFile() method. If you do, you'll have to cast that Image instance down to Bitmap, like so:

            pictureBox1.Image = ImageFader.Fade((Bitmap) Image.FromFile(label1.Text), (Bitmap) Image.FromFile(label2.Text), trackBar1.Value);

Instead, you can use the more natural Bitmap constructor:

            pictureBox1.Image = ImageFader.Fade(new Bitmap(label1.Text), new Bitmap(label2.Text), trackBar1.Value);

Well, that about wraps it up. I didn't touch the rather robust GDI+ Graphics class (which is what I was familiar with from Java), and it certainly isn't the fastest code I've ever written. However, for a first stab at the problem, I am pretty happy to have such a simple solution. I'll look more into using a Graphics object to speed up execution in the future, but for now, if anyone has any suggestions on improving this code, I'm all ears (eyes?) Here's a screenshot of the Windows Forms application I built to test this algorithm out:

Image Fader Windows Forms app

Download

The source code and Windows binary for this project can be downloaded here: Image Fader Windows Forms Project

Links

Since the .NET framework is closed source, check out the Microsoft Developer's Network for class documentation and examples:

  • Share/Save/Bookmark

Comments

  • Raúl Roa said:

    I'm curious. Where you asked to watermark an image? I'm having trouble thinking of another scenario for this, maybe a collage?

  • Josh Jordan (Author) said:

    No, not watermarking exactly. This project was very similar to a collage. After assembling images into a collage, I wanted to select a group of them and color them like another image. This was something that was inspired by Silverlight's Deep Zoom, but with an emphasis on finding new images as you zoom in further.

Trackbacks



Recent Archives
  • 2007 austin texas gourd festival
  • acmi ogden
  • challenge gifted magazine
  • clara.co.uk
  • 1.5 volt dc musical circuts
  • dkny g-string
  • cecil b demille download
  • chemo mouth sores
  • millerweldingsupply.com
  • aimated scooby doo plush
  • ruble-enterprises.com
  • headboards for flatbed trailers
  • current scenario of myanmar
  • could not perform end of disc-at-once
  • kaiser permanente antioch
  • dj milky myspace
  • cedant arma in hac vince
  • chronological reading plan
  • placer chamber of comerce
  • crawford insurance adjusters
  • critical analysis my last duchess
  • crack tis 2007
  • lwcky.com
  • guadalupe bass south llano state park
  • sex-3d.com
  • former wayland academy faculty
  • charteristics five kingdoms
  • backover injuries fatalities child childern toddler
  • bran cereal gluten
  • 1990 ford ranger coolant temperature sensor
  • bonnie l hays
  • air pollution issues harford county
  • rickey a kempter
  • 1992 camry etc button
  • assessing lectures
  • cristian baha
  • housequake.com
  • almighty lating king nation
  • advertisements archives
  • 100th day of school clipart
  • breaking voodoo spells
  • 08 accord release date
  • dickson city resturaunts
  • brea lynn mpegs
  • bhp magnetite sales
  • b16 jdm engine
  • apple computer specials
  • dirty toons coloring sheets
  • incline plane problem
  • bilingual back to school
  • black panthers connecticut
  • dotnet nuke photo gallery
  • floor tiling northants
  • ford explorer rusty seat
  • incandescent heat lamp
  • angela from runs house
  • driver dell poweredge 2600
  • chessiemoore.com
  • aurora borealis location
  • acer travelmate 2480 2943 review
  • oasisinet.com
  • andres celsius
  • emanuel gallego
  • 60s black athletes
  • ann lay apostalate
  • bonnie wanted to die with clyde
  • albertsons escondido
  • albuquerque kellys
  • crescent silverware mfg co
  • climate denial
  • 410 sprint racing west
  • basel ii policy and procedures
  • box to steal tv channels
  • emerald lake lanier tri results
  • how old is lois lowry today
  • angela denise davis
  • eyshila playback
  • 10000 clean room
  • ald transplant nathan
  • car wholesaler perth
  • chain saw sharpening wheels
  • decrease and conquer fake coin algorithm
  • mayweather dela hoya fight blog
  • antique doll appraisals
  • john frano msu
  • how to hit salvia
  • bloom time bulbs planting daffodils hole
  • 1880 illinois census
  • female kickboxing champion
  • 240z fenders
  • added touch profesional dj
  • carah cate caleb
  • anythingcrafts.com
  • 120 gb external hdd
  • 73 pesticides groundwater
  • broker reciprocity
  • greerlodgeaz.com
  • 28 sport boat retractable keel
  • gel electrophoresis and analyse dna
  • apparitions.org
  • airports near lynchburg
  • daves and busters
  • uploading files using classic asp
  • anne fillmore
  • control of wild violets
  • adventure quest lizard lock chest answer
  • algonquin indians and christianity
  • copper sulfate test for proteins
  • chicksandtoys.com
  • 3 ponds cabin
  • quark binding particle
  • ponte verdra beach sawgrass course
  • fybush.com
  • running suicides
  • bio for rafael nadal
  • hydraulics of sewers flowing partially full
  • aquarius constellation
  • atlantic iowa hollis
  • catherine wier slippery rock obituary
  • howto verify email address
  • cream cheese and jalapeno pepper spread
  • dunlop heli talk box
  • valleycoin.com
  • crafts orb
  • convergenceinsufficiency.org
  • hebt aandacht en zorg stage voor
  • a message from god aldo mcpherson
  • explicitlesbians.com
  • liteon dvd recorder lvc-9016g firmware
  • msn.com.cn
  • donald goodwill
  • dino run escape extinction cheats
  • sba addresses
  • aurora jays ontario
  • herb-doc.com
  • b woodland associates
  • survey-scam.com
  • eustis vacation rental
  • 1987 corvette sevice engine light
  • bill meier
  • definisi puisi melayu moden
  • 3d shooting women games online
  • icc ada
  • circuit court wexford ireland
  • mexicoledger.com
  • brass telescoping pointer
  • 1922 red mountain union member card
  • benedict arnold saratoga
  • aircraft galley floor mat
  • a level certificates
  • coloredhorses.com
  • 4 3 lens corp
  • classes hand dyeing fabric
  • car brand stereotypes humour
  • hotel moulin de mougins
  • prehomecheck.com
  • consultation jacket
  • allegro viewer
  • numark turntables
  • card modelling faq
  • free sheet music alto saxaphone
  • aussies feral rabbits
  • checkers board game rules
  • arkansas workforce education
  • american harvest bread classic ii manual
  • furniture seashore beach
  • disassemble hp officejet 5510
  • dental hygienist pay
  • elegant affair lake tahoe
  • mrski.com
  • alfa romeo 2600
  • viewsonic company
  • caravans for hie
  • close encounters movie song title
  • growmark.com
  • 2007 sportster sundowner seat
  • yogiberra.com
  • burlesque costuming
  • aids in argentina
  • download mortal kombat 4 for pc
  • dymatize.com
  • pounds and inches by dr simeon
  • almond tilapia worsteshire cumin lemon juice
  • apple cider vinegar and acidophilus
  • keystone 2008 nrg 260fs
  • brewers and maltsters local 6
  • bernie beadroller
  • bank robbery brigham city utah 2008
  • anacortes island homes for sale
  • clayhouse in kissimmee
  • atheist san leandro
  • teenparents.org
  • barney burke port townsend
  • capcom snk 2 marquee
  • downingtown pa wayne newton resort
  • glocalgeneration.com
  • ecole de commerce
  • bank of new york inform software
  • boston proper girls
  • portbb.com
  • food handlers course denton county
  • replacementchina.com
  • 2006 album sales
  • woodsidehotels.com
  • advantages of composites
  • morries.com
  • fred myer jewlers
  • thenewpress.com
  • masa seti
  • african american health initiative md
  • hotelseasy.com
  • bethany college board of trustees
  • lindy garcia
  • parktowne condo jonesville rd simpsonville sc
  • chilling effects clearinghouse search the database
  • 2001 gmc 3500 marker lights
  • biddy hurlbut obituary peruvian connection
  • aaa boobs stuffed to dd
  • cyndi helen eurovision 2007
  • 12v 15amp power supply for computer
  • eric diaz in hermitage tn
  • bong of destiny
  • iroquois canoes
  • demonstrations california
  • hair extentions in kwazulu natal
  • celtic magicians
  • being tired of this house
  • aqua caliente tribe
  • chorionic gonadotropin causes cramping in uterus
  • brick facade removal
  • drilling oil wells ephraim utah
  • danido.com
  • citing uk gro sources
  • apache mfg creep self feeders norfolk
  • www.cat
  • healthy salads
  • khaled hosseini war afghanistan
  • all weather sailing boots
  • baseball pitching definitions
  • laconia historical
  • 19 ge refrigerator thermostat
  • brazos county property tax records
  • 0.85 champ connector
  • informatica pmcmd fetch
  • battlestaions midway demo on file shack
  • antigone cliff notes
  • pra.org
  • conserving our coral reefs
  • 3d online deer hunting game
  • mmc 1911 sights
  • 1978 prom catalog ads
  • bacardi logo