473,473 Members | 1,899 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Accessing a bitmap's color channels

HaLo2FrEeEk
404 Contributor
I'd like to create a simple program to generate 3D stereo anaglyph images using a left and right image. I've so far got the program to load the 2 images into Bitmap objects, but from there I can't figure out how to combine the two image's color channels to get the desired result.

For a red/cyan anaglyph you disable the red channel on the left image and the green and blue channels on the right image, that gives you a red/cyan anaglyph. I've googled it but I can't really find anything that describes anything similar to what I'm looking for.

Anyone here able to help me out with this?
Jun 23 '10 #1
6 7116
Plater
7,872 Recognized Expert Expert
Well I can think of a long way to do it.
Make a third empty bitmap. Then examine the pixel data of each point on the left& right images. Do your disabling/combining of the colors and draw the pixel on the new image.

So for every pixel in the left/right images:
Expand|Select|Wrap|Line Numbers
  1.  
  2. Color LeftColor = LeftImage.GetPixel(x, y);
  3. Color RightColor = RightImage.GetPixel(x, y);
  4. int Alpha = 0;//todo: Do something here to deal with the alpha
  5. Color NewColor = Color.FromArgb(Alpha,RightColor.R, LeftColor.G, LeftColor.B);
  6. NewImage.SetPixel(x, y, NewColor);
  7.  
  8.  
Jun 23 '10 #2
HaLo2FrEeEk
404 Contributor
Ok, that works...but it takes forEVER. My source images are 1920x1080, so I'm effectively getting the value from each image's pixel and setting 2,073,600 pixels in the result image. It does work though.

However, I found another method that's a lot faster, and uses a ColorMatrix to extract the color channels. I managed to combine the right red/green/blue channels to also give me cyan/yellow/magenta. The problem is...I still need to combine them. I've got a graphics object with the red channel and another with green/blue (cyan) channels. How do I combine those 2 images together into a single, 1920x1080 image with only the red channel showing from the right image and only the green/blue channels showing from the left image?
Jun 24 '10 #3
GaryTexmo
1,501 Recognized Expert Top Contributor
I have no idea how you could do this other than processing every pixel in the image as you'd have to read from the two source and write to the destination.

Well, there was an old trick I used to use when copying or clearing a buffer... the image data was a byte array but if I processed it as an integer array I could do my operations 4 bytes at a time, which gave significant speed improvements.

However, your image data here is a full integer anyway... four bytes for red, green, blue, and alpha. I don't know how you could "cheat" and process it more quickly.

A couple of optimizations you can do though...
* The less loops the better -- a single control loop is often better than a nested loop as there are less condition checks per iteration.
* Avoid conditionals in your loop if possible -- condition checks take time away from your calculations, use switch over if.
* Do not create/destroy objects in your loop -- C# memory management is expensive and needless in a loop.
* Avoid a foreach loop if you can -- Sometimes foreach loops create extra variables but for the most part they're actually ok. Just a precaution here.

For example... instead of:
Expand|Select|Wrap|Line Numbers
  1. Color[,] data = new Color[200,200];
  2.  
  3. for (int i = 0; i < 200; i++)
  4. {
  5.   for (int j = 0; i < 200; j++)
  6.   {
  7.     Color c = data[i,j];
  8.     if (c.R > 200) { ... }
  9.     else if (c.R ...) { ... }
  10.     else { ... }
  11.   }
  12. }
Do this...
Expand|Select|Wrap|Line Numbers
  1. Color[] data = new Color[200 * 200];
  2.  
  3. Color c;
  4. for (int i = 0; i < 200 * 200; i++)
  5. {
  6.   c = data[i];
  7.   switch (c.R)
  8.   {
  9.     case 200: ...
  10.     ...
  11.   }
  12. }
If you need the x & y coordinate of the pixel, you can calculate it fairly easily... the y value is the counter divided by the width and the x value is the remainder of that (mod).

If you need to do range checks, you're probably stuck with the if, but them's the breaks ;)
Jun 24 '10 #4
HaLo2FrEeEk
404 Contributor
What I ended up doing was something like this:

Expand|Select|Wrap|Line Numbers
  1. int width = imgLeft.Width;
  2. int height = imgLeft.Height;
  3. int x = 0;
  4. int y = 0;
  5. while(x < width) {
  6.   while(y < height) {
  7.     // get the color for pixel (x, y), generate a new color from the proper channels, and set the pixel in a result bitmap.
  8.     y++;
  9.     }
  10.   y = 0;
  11.   x++;
  12.   }
That worked, but like I said it's God-awful slow, so I won't be using it. I guess this project is a lost cause.
Jun 24 '10 #5
GaryTexmo
1,501 Recognized Expert Top Contributor
There might be another way to do it, I just don't know what it is. The biggest problem here is that the array access isn't contiguous... you need to copy 1/3 of the data from one source and 2/3's of the data from another source, so I just don't see any way to do any tricks.

That doesn't mean there isn't a faster way, it just means I don't know it :D I'd be interested in a fast array data processing routine as much as anybody!
Jun 24 '10 #6
GaryTexmo
1,501 Recognized Expert Top Contributor
Take a read through this. I think the problem is C# and the access it provides, not the fact that you're looping through the whole image. It'll still take a bit, but perhaps you can speed it up :)

http://www.codeproject.com/KB/GDI-pl...filters11.aspx
Jun 24 '10 #7

Sign in to post your reply or Sign up for a free account.

Similar topics

4
by: Carl | last post by:
In the application I'm writing, I'm modifying a windows bitmap using the circle and line methods. Once the changes have been made, I would like to save the bitmap with the changes. My problem is,...
5
by: Erwin | last post by:
At the moment I'm using a report which contains an indicator to show if a Service group of the company isn't working well or is working perfectly. This indicator is a "*" which looks like a traffic...
3
by: RicercatoreSbadato | last post by:
=========== INTRODUCTION: =========== I'd like to take only a part of a Bitmap. I'm workin in unsafe mode with the pointers: unsafe { byte * p_init = (byte *)(void *)Scan0; byte * p_I =...
7
by: Peter Oliphant | last post by:
Using MakeTransparent one can supposedly turn a color used in a Bitmap to transparent. But, it looks to me like all it does it set these pixels to the color BackColor of the Control it's attached...
5
by: Lance | last post by:
I need to create a Drawing.Bitmap from an array of integer values. My current technique creates a bitmap that eventually becomes corrupt (i.e., the bitmap's pixels change to a different color...
3
by: mark | last post by:
I want plot points on a cartesian surface with single pixels. I have been unable to find a graphics member which draws points. (Is there one?) I would like to create a bitmap one element wide and...
1
by: tsteinke | last post by:
I am in the process of creating a System.Drawing.Bitmap from a block of memory containing a DIB Bitmap. I can think of about a half dozen ways to do this. For perfomance reasons I don't want to be...
3
by: Sebastor | last post by:
Hi I create bitmap array : Graphics::TBitmap ***bitmap; bitmap = new Graphics::TBitmap**; for (int s=0;s<x;s++) { bitmap = new Graphics::TBitmap*;
12
by: active | last post by:
I've been looking on the Internet for a way to convert a DIB to a Bitmap without success. Now I'm wondering if that is the approach I should be taking. All I want to do is display the DIB or...
3
by: Samuel | last post by:
I need to read a tiff Image and change it slightly. Currently I create a bitmap then I draw the original image and do the changes. Since the tiff is very large in size the bitmap takes a huge...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.