1

2 つの画像があり、一方が他方の上にあるとしましょう。一番上の画像のピクセルのアルファ値の一部をゼロに設定したいので、この効果を以下に示します。

茶色が上の画像、青い水が下の画像です。最終的に私がやろうとしているのは、ユーザーが iPad の画面に触れると、上の画像のピクセルのアルファ チャネルをゼロに変更して、基本的に指先で描画して青い水の画像を表示できるようにすることです。

アルファがゼロに等しいピクセルをカウントして画像を調べることができる関数があります。ピクセルのアルファをゼロに設定する機能もありますが、機能しないと思います。 アルファ値を読み取り、アルファ値を設定できます。次に、アルファ値を再読み取りして、設定されていることを確認します。しかし、新しい画像を設定すると、違いがわかりません!

サンプル プロジェクトへのドロップボックス リンクは次のとおりです。

https://www.dropbox.com/s/e93hzxl5ru5wnss/TestAlpha.zip

そして以下がソースです。

        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;
    }
4

1 に答える 1

1

うまくいきました!問題が正確に何であるかはわかりませんが(偶然か何かで間違ったバイトにアクセスしていたと仮定して)、動作するコードがあります。

これは非常に便利でした:

        // Create layers of matter on the battlefield.  Example:  Grass, dirt, water
        Water = new UIImageView(UIScreen.MainScreen.Bounds);
        Water_OriginalImage = UIImage.FromFile("WaterTexture.png");
        Water.Image = Water_OriginalImage;
        this.View.AddSubview(Water);

        Dirt = new UIImageView(UIScreen.MainScreen.Bounds);
        Dirt_ModifiableImage = UIImage.FromFile("DirtBackground.png");
        Dirt.Image = null;
        this.View.AddSubview(Dirt);



        CGImage image = Dirt_ModifiableImage.CGImage;
        int width = image.Width;
        int height = image.Height;
        CGColorSpace colorSpace = image.ColorSpace;
        int bytesPerRow = image.BytesPerRow;
        // int bytesPerPixel = 4;
        int bytesPerPixel = bytesPerRow / width;
        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);

        int tempX = 0;

        while ( tempX < Dirt_ModifiableImage.Size.Width )
        {
            int tempY = 0;
            while ( tempY < Dirt_ModifiableImage.Size.Height )
            {
                int byteIndex = (bytesPerRow * tempY) + tempX * bytesPerPixel;


                ZeroByte(byteIndex+3, BitmapData);

                byte red = GetByte(byteIndex, BitmapData);
                byte green = GetByte(byteIndex+1, BitmapData);
                byte blue = GetByte(byteIndex+2, BitmapData);
                byte alpha = GetByte(byteIndex+3, BitmapData);


                //Console.WriteLine("red = " + red + " green = " + green + " blue = " + blue + " alpha = " + alpha);

                tempY++;
            }
            tempX++;
        }


            NSData newImageData = NSData.FromBytes(BitmapData, (uint)(bitmapByteCount));
            Dirt.Image = UIImage.LoadFromData(newImageData);
于 2013-03-19T14:29:52.727 に答える