Let's say I have 2 images, one on top of the other. I want to set a portion of the top image's pixel's alpha values to zero so I get this effect illustrated below:
The brown is the top image, and the blue water is the bottom image. Ultimately what I'm going to do is have the alpha channel of the top image's pixels change to zero as the user touches the iPad screen so they can essentially draw with their fingertip and have the blue water image appear.
I have a function that can examine the image counting it's pixels whose alpha is equal to zero. I also have a function that Sets the alpha of a pixel to zero but I think it doesn't work. I can read the alpha value, and set the alpha value. Then I can re-read the alpha value to confirm that it was set. But when I set the new image I can't see a difference!
Here is a dropbox link to my example project:
https://www.dropbox.com/s/e93hzxl5ru5wnss/TestAlpha.zip
And below is the source:
Water = new UIImageView(this.Bounds);
Water_OriginalImage = UIImage.FromFile("Media/Images/Backgrounds/WaterTexture.png");
Water.Image = Water_OriginalImage;
this.AddSubview(Water);
Dirt = new UIImageView(this.Bounds);
Dirt_ModifiableImage = UIImage.FromFile("Media/Images/Backgrounds/DirtBackground.png");
Dirt.Image = null;
this.AddSubview(Dirt);
CGImage image = Dirt_ModifiableImage.CGImage;
int width = image.Width;
int height = image.Height;
CGColorSpace colorSpace = image.ColorSpace;
int bytesPerRow = image.BytesPerRow;
int bitmapByteCount = bytesPerRow * height;
int bitsPerComponent = image.BitsPerComponent;
CGImageAlphaInfo alphaInfo = image.AlphaInfo;
// Allocate memory because the BitmapData is unmanaged
IntPtr BitmapData = Marshal.AllocHGlobal(bitmapByteCount);
CGBitmapContext context = new CGBitmapContext(BitmapData, width, height, bitsPerComponent, bytesPerRow, colorSpace, alphaInfo);
context.SetBlendMode(CGBlendMode.Copy);
context.DrawImage(new RectangleF(0, 0, width, height), image);
// Console output from this function call says "alpha count = 0"
CountZeroedAlphas(BitmapData, Dirt_ModifiableImage);
RemoveSomeAlpha(BitmapData, Dirt_ModifiableImage);
// Console output from this function call says "alpha count = 2000". So it seems that I have set the alpha of 2000 pixels to zero...
CountZeroedAlphas(BitmapData, Dirt_ModifiableImage);
// Set the Dirt Image equal to the context image, but I still see all top image, I dont' see any bottom image showing through.
Dirt.Image = UIImage.FromImage (context.ToImage());
// Free memory used by the BitmapData now that we're finished
Marshal.FreeHGlobal(BitmapData);
public void CountZeroedAlphas( IntPtr bitmapData, UIImage Image )
{
int widthIndex = 0;
int heightIndex = 0;
int count = 0;
while ( widthIndex < Image.Size.Width )
{
while ( heightIndex < Image.Size.Height )
{
PointF point = new PointF(widthIndex, heightIndex);
var startByte = (int) ((point.Y * Image.Size.Width + point.X) * 4);
byte alpha = GetByte(startByte, bitmapData);
if ( alpha == 0 )
count++;
heightIndex++;
}
widthIndex++;
}
Console.WriteLine("alpha count = " + count);
}
public void RemoveSomeAlpha( IntPtr bitmapData, UIImage Image )
{
int widthIndex = 0;
int heightIndex = 0;
while ( widthIndex < Image.Size.Width )
{
while ( heightIndex < Image.Size.Height )
{
PointF point = new PointF(widthIndex, heightIndex);
var startByte = (int) ((point.Y * Image.Size.Width + point.X) * 4);
ZeroByte(startByte, bitmapData);
heightIndex++;
}
widthIndex++;
}
}
public unsafe byte GetByte(int offset, IntPtr buffer)
{
byte* bufferAsBytes = (byte*) buffer;
return bufferAsBytes[offset];
}
public unsafe void ZeroByte(int offset, IntPtr buffer)
{
byte* bufferAsBytes = (byte*) buffer;
bufferAsBytes[offset] = 0;
}