4

I'm working in creating a composite image on the fly using Xamarin for iOS. I have two images, one is the base image (black and white), and the other is a alpha mask 'map' for a color filter. Then, at runtime, supply an RGB value so I can make the composite image be whatever color it should be.

I've found plenty of solutions for changing the entire image, but I'm having trouble finding a good solution for creating that color filter that only colors the area (with the alpha values) contained in the mask map:

Base Images:

enter image description here enter image description here

Resulting image (if I tell it I want red):

enter image description here

In MonoDroid, I was able to create a custom ImageView and override the OnDraw method then used a ColorMatrixColorFilter which worked like a charm, but don't know how to accomplish the same thing in MonoTouch.

This is what I did for MonoDroid:

    protected override void OnDraw(Canvas canvas)
    {
        if (_alphaMask == null)
            _alphaMask = BitmapFactory.DecodeResource(Resources, GetDrawable("star_mask"));

        if(_image == null)
            _image = BitmapFactory.DecodeResource(Resources, GetDrawable("star"));

        AdjustColor(_color, canvas, _alphaMask, _image);
    }

    private static void AdjustColor(Color color, Canvas c, Bitmap alphaMask, Bitmap image)
    {
        float R = color.R;
        float G = color.G;
        float B = color.B;
        var maskPaint = new Paint();
        var mat = new[]
        {
            0, 0, 0, 0, R, //red
            0, 0, 0, 0, G, //green
            0, 0, 0, 0, B, //blue
            0, 0, 0, 1, 0  //alpha
        };
        ColorMatrix cm = new ColorMatrix(mat);
        maskPaint.SetColorFilter(new ColorMatrixColorFilter(cm));
        c.DrawBitmap(image, 0, 0, null);
        c.DrawBitmap(alphaMask, 0, 0, maskPaint);
    }
Xinbi
  • 272
  • 1
  • 2
  • 10

2 Answers2

2

From Apple developer website: https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/CoreImaging/ci_filer_recipes/ci_filter_recipes.html

Seems like what you are looking for (CIFilter).

Xinbi
  • 272
  • 1
  • 2
  • 10
SKall
  • 5,234
  • 1
  • 16
  • 25
  • That is heading in the right direction, but my ability to translate from Objective-C to C# isn't very good. – Xinbi Jan 05 '14 at 21:14
  • Here is a quick sample of creating the CIFilter in C#: https://github.com/sami1971/SimplyMobile/blob/master/iOS/Samples/StackOverflowSamples/StackOverflowSamplesViewController.cs – SKall Jan 05 '14 at 23:01
1

Ok... Not the most elegant solution, but I created two ImageView on top of each other.

On top of the base image was the MaskView then used the following method to create the colored UIImage:

private UIImage GetColoredImage(string imageName, Color color)
    {
        UIImage image = UIImage.FromBundle(imageName);

        UIGraphics.BeginImageContext(image.Size);
        CGContext context = UIGraphics.GetCurrentContext();

        context.TranslateCTM(0, image.Size.Height);
        context.ScaleCTM(1.0f, -1.0f);

        var rect = new RectangleF(0, 0, image.Size.Width, image.Size.Height);

        // draw image, (to get transparancy mask)
        context.SetBlendMode(CGBlendMode.Normal);
        context.DrawImage(rect, image.CGImage);

        // draw the color using the sourcein blend mode so its only draw on the non-transparent pixels
        context.SetBlendMode(CGBlendMode.SourceIn);
        context.SetFillColor(color.R / 255f, color.G / 255f, color.B / 255f, 1);
        context.FillRect(rect);

        UIImage coloredImage = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();
        return coloredImage;
    }

if someone has a better solution (maybe using CIFilter) I'd love to see it.

Xinbi
  • 272
  • 1
  • 2
  • 10