Alpha value not persisting while saving Bitmap - c#

Good morning all,
I am making an Image Steganography project for college.
While hiding data in image. I am writing the "Text Length" which is an Int32 in a pixel. As Int32 is of 4 bytes. I thought I could write it in the 4 bytes of Alpha,Red,Green,Blue, as each color is of 1 byte.
Then I save the image in bmp format.
I used single stepping and data get properly distributed and set in the pixel.
The problem arise when I read back the pixel. R,G,B have their value as i had set them. But the alpha is always 255 no matter what it was set.
Code that I am using for distributing Int32 into 4 bytes are
byte R, G, B, A;
int colorValue = messageLength;
int first = colorValue & 255;
//R contains bit 0-7 means the least significant 8 bits
R = (byte)first;
colorValue = colorValue - first;
int second = colorValue & 65535;
colorValue = colorValue - second;
second = second >> 8;
//G contains 8-15
G = (byte)second;
int third = colorValue & 16777215;
colorValue = colorValue - third;
third = third >> 16;
//B contains 16-23
B = (byte)third;
colorValue = colorValue >> 24;
//A contains 24-31
A = (byte)colorValue;
pixelColor = Color.FromArgb(A, R, G, B);
bitmap.SetPixel(location.X, location.Y, pixelColor);
Code for getting the values back is
byte R, G, B, A;
R = pixelColor.R;
G = pixelColor.G;
B = pixelColor.B;
A = pixelColor.A;
messageLength = A;
messageLength = messageLength << 8;
messageLength += B;
messageLength = messageLength << 8;
messageLength += G;
messageLength = messageLength << 8;
messageLength += R;
Is there something I am missing. Is it that BMP does not allow alpha value to persist???
Please help.
Thanks.

Sorry to say that Bitmap doesn't support an alpha value.

Related

How to get System.Windows.Media.Color From From HEX Windows 8 Application

I want to set Border background color from web color value in my windows 8 mobile application .
I found one method that convert hex to Argb but its not working for me ..
private System.Windows.Media.Color FromHex(string hex)
{
string colorcode = hex;
int argb = Int32.Parse(colorcode.Replace("#", ""), System.Globalization.NumberStyles.HexNumber);
return System.Windows.Media.Color.FromArgb((byte)((argb & -16777216) >> 0x18),
(byte)((argb & 0xff0000) >> 0x10),
(byte)((argb & 0xff00) >> 8),
(byte)(argb & 0xff));
}
I am using above method like..
Border borderCell = new Border();
var col = FromHex("#DD4AA3");
var color =new System.Windows.Media.SolidColorBrush(col);
borderCell.Background = color;
But if I pass color hex value like below
var col = FromHex("#FFEEDDCC");
its works fine but it not work on my hex color value.
Before posting this question I go thru this stack answer.
How to get Color from Hexadecimal color code using .NET?
Convert System.Drawing.Color to RGB and Hex Value
Why not simply use System.Windows.Media.ColorConverter?
Color color = (Color)System.Windows.Media.ColorConverter.ConvertFromString("#EA1515");
finally I found one method that return color from hex string
public System.Windows.Media.Color ConvertStringToColor(String hex)
{
//remove the # at the front
hex = hex.Replace("#", "");
byte a = 255;
byte r = 255;
byte g = 255;
byte b = 255;
int start = 0;
//handle ARGB strings (8 characters long)
if (hex.Length == 8)
{
a = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
start = 2;
}
//convert RGB characters to bytes
r = byte.Parse(hex.Substring(start, 2), System.Globalization.NumberStyles.HexNumber);
g = byte.Parse(hex.Substring(start + 2, 2), System.Globalization.NumberStyles.HexNumber);
b = byte.Parse(hex.Substring(start + 4, 2), System.Globalization.NumberStyles.HexNumber);
return System.Windows.Media.Color.FromArgb(a, r, g, b);
}

Moving through each pixel for 1bpp Pixel Format

I had a question related to the use of Lockbits method in C#..
I have a 1bpp Image and I'm trying to access all the pixels of the image but some are still left out.
public Bitmap Pixels(Bitmap original)
{
Rectangle rect = new Rectangle(0, 0, original.Width, original.Height);
BitmapData bimgData = original.LockBits(rect, ImageLockMode.ReadWrite, original.PixelFormat);
IntPtr ptr = bimgData.Scan0;
int bytes = bimgData.Stride * bimg.Height;
byte[] Values = new byte[bytes];
Marshal.Copy(ptr, Values, 0, bytes);
int Val;
int stride = bimgData.Stride;
for (int column = 0; column < bimgData.Height; column = column + 1)
for (int row = 0; row < bimgData.Width; row = row +1)
{
c = column;
r = row;
for (int t = 0; t < 8; t++)
{
Val = Values[((c) * stride) + ((r) / 8)] & 2 ^ t;
if (Val == 0)
Values[((c) * stride) + ((r) / 8)] = (byte)(Values[((c) * stride) + ((r) / 8)] + 2 ^ t);
}
}
Marshal.Copy(Values, 0, ptr, bytes);
original.UnlockBits(bimgData);
return original;
}
This code should turn all the pixels white
Val = Values[((c) * stride) + ((r) / 8)] & 2 ^ t;
2 ^ t doesn't do what you hope it does, that's Visual Basic syntax. In the C# language, ^ is the XOR operator. Use the << operator instead and use parentheses to take care of operator precedence. Fix:
Val = Values[((c) * stride) + ((r) / 8)] & (1 << t);
And fix it again when you set the bit.
Do note that turning the entire image to White doesn't require this kind of code at all. Just set all the bytes to 0xff.

Converting from RGB ints to Hex

What I have is R:255 G:181 B:178, and I am working in C# (for WP8, to be more specific)
I would like to convert this to a hex number to use as a color (to set the pixel color of a WriteableBitmap). What I am doing is the following:
int hex = (255 << 24) | ((byte)R << 16) | ((byte)G << 8) | ((Byte)B<<0);
But when I do this, I just get blue.
Any ideas what I am doing wrong?
Also, to undo this, to check the RGB values, I am going:
int r = ((byte)(hex >> 16)); // = 0
int g = ((byte)(hex >> 8)); // = 0
int b = ((byte)(hex >> 0)); // = 255
Try the below:
using System.Drawing;
Color myColor = Color.FromArgb(255, 181, 178);
string hex = myColor.R.ToString("X2") + myColor.G.ToString("X2") + myColor.B.ToString("X2");
Using string interpolation, this can be written as:
$"{r:X2}{g:X2}{b:X2}"
You can use a shorter string format to avoid string concatenations.
string.Format("{0:X2}{1:X2}{2:X2}", r, g, b)
You can use ColorHelper library for this:
using ColorHelper;
RGB rgb = new RGB(100, 0, 100);
HEX hex = ColorConverter.RgbToHex(rgb);
Greetings fellow humans,
//Red Value
int integerRedValue = 0;
//Green Value
int integerGreenValue = 0;
//Blue Value
int integerBlueValue = 0;
string hexValue = integerRedValue.ToString("X2") + integerGreenValue.ToString("X2") + integerBlueValue.ToString("X2");

Converting 3 bytes into signed integer in C#

I'm trying to convert 3 bytes to signed integer (Big-endian) in C#.
I've tried to use BitConverter.ToInt32 method, but my problem is what value should have the lats byte.
Can anybody suggest me how can I do it in different way?
I also need to convert 5 (or 6 or 7) bytes to signed long, is there any general rule how to do it?
Thanks in advance for any help.
As a last resort you could always shift+add yourself:
byte b1, b2, b3;
int r = b1 << 16 | b2 << 8 | b3;
Just swap b1/b2/b3 until you have the desired result.
On second thought, this will never produce negative values.
What result do you want when the msb >= 0x80 ?
Part 2, brute force sign extension:
private static int Bytes2Int(byte b1, byte b2, byte b3)
{
int r = 0;
byte b0 = 0xff;
if ((b1 & 0x80) != 0) r |= b0 << 24;
r |= b1 << 16;
r |= b2 << 8;
r |= b3;
return r;
}
I've tested this with:
byte[] bytes = BitConverter.GetBytes(p);
int r = Bytes2Int(bytes[2], bytes[1], bytes[0]);
Console.WriteLine("{0} == {1}", p, r);
for several p.
The last value should be 0 if it isn't set for a positive number, 256 for a negative.
To know what you should pass in, you can try converting it the other way:
var bytes = BitConverter.GetBytes(i);
int x = BitConverter.ToInt32(bytes, 0);
To add to the existing answers here, there's a bit of a gotcha in that Bitconverter.ToInt32() will throw an ArgumentException if the array is less than sizseof(int) (4) bytes in size;
Destination array is not long enough to copy all the items in the collection. Check array index and length.
Given an array less than sizeof(int) (4) bytes in size, you can compensate for left/right padding like so;
Right-pad
Results in positive Int32 numbers
int intByteSize = sizeof(int);
byte[] padded = new byte[intByteSize];
Array.Copy(sourceBytes, 0, padded, 0, sourceBytes.Length);
sourceBytes = padded;
Left-pad
Results in negative Int32 numbers, assuming non-zero value at byte index sourceBytes.Length - 1.
int intByteSize = sizeof(int);
byte[] padded = new byte[intByteSize];
Array.Copy(sourceBytes, 0, padded, intByteSize - sourceBytes.Length, sourceBytes.Length);
sourceBytes = padded;
Once padded, you can safely call int myValue = BitConverter.ToInt32(sourceBytes, 0);.

Alternative to BitConverter.ToInt32

I'm using BitConverter.ToInt32 to pack 3 byte values into an int, like so:
byte R = 0;
byte G = 0;
byte B = 0;
int i = BitConverter.ToInt32(new byte[] { R, G, B, 0 }, 0);
Is there a faster way to do this that doesn't involve the creation of a new int each time? Getting the bytes out of an int is easy:
int i = 34234;
byte B = (byte)(i >> 0);
byte G = (byte)(i >> 8);
byte R = (byte)(i >> 16);
Is there a simple way to reverse this process and use bit-shifting to write the RGB bytes back over an existing int?
int i = (B << 0) | (G << 8) | (R << 16);
You ought to consider the Color structure. It has R, G and B properties and FromArgb() and ToArgb() methods.

Categories

Resources