nimbudew
nimbudew

Reputation: 978

Lumia Imaging SDK image blending creates separation lines

I'm trying to create a tiled background using the Lumia Imaging SDK's JpegTools.BlendAsync() method. I call the method in a loop to merge all the tiled images. The approach works but the there are unwanted lines in the output image. These separation lines appear at the boundaries of the single tile image; the merging is not clean.

My code is attached. Am I doing something wrong logically or this is a bug in the SDK?

bitmapSource is the single tile, jpegSource is the empty layout which is populated by the tile, and bgSize is the size of the dimensions of the background.

async private static Task<IBuffer> CreateTile(IBuffer jpegSource, IReadableBitmap bitmapSource, Size tileSize, Size bgSize)
        {
            int outBgWidth = (int)bgSize.Width;
            int outBgHeight = (int)bgSize.Height;
            int tileWidth = (int)tileSize.Width;
            int tileHeight = (int)tileSize.Height;

            int currentBgWidth = 0;
            int currentBgHeight = 0;

            Point blendPosition = new Point(0, 0);

            while (currentBgHeight < outBgHeight)
            {
                while (currentBgWidth < outBgWidth)
                {
                    jpegSource = await JpegTools.BlendAsync(jpegSource, bitmapSource, blendPosition);
                    blendPosition.X += tileWidth;
                    currentBgWidth += tileWidth;
                }
                blendPosition.Y += tileHeight;
                currentBgHeight += tileHeight;
                currentBgWidth = 0;
                blendPosition.X = 0;
            }

            return jpegSource;
        }

Upvotes: 1

Views: 246

Answers (1)

David Božjak
David Božjak

Reputation: 17607

As discussed in the comments, I suggest an alternate way of doing this: By using a more "standard" rendering chain, instead of using JpegTools.

Some of this is based on your code sample, but I've tried making it as general as possible.

int outBgWidth = (int)bgSize.Width;
int outBgHeight = (int)bgSize.Height;
int tileWidth = (int)tileSize.Width;
int tileHeight = (int)tileSize.Height;

int currentBgWidth = 0;
int currentBgHeight = 0;

Point blendPosition = new Point(0, 0);

using (var backgroundCanvas = new ColorImageSource(new Size(outBgWidth, outBgHeight), Color.FromArgb(255, 0, 0, 0)))  //Create a black canvas with the output size.
using (var tileSource = new BitmapImageSource(bitmapSource))
using (var renderer = new JpegRenderer(backgroundCanvas))
{
    while (currentBgHeight < outBgHeight)
    {
        while (currentBgWidth < outBgWidth)
        {
            var blendEffect = new BlendEffect();
            blendEffect.BlendFunction = BlendFunction.Normal;
            blendEffect.GlobalAlpha = 1.0;

            blendEffect.Source = renderer.Source;
            blendEffect.ForegroundSource = tileSource;
            blendEffect.TargetArea = new Rect(blendPosition, new Size(0, 0));   //Since we are PreservingSize the size doesn't matter. Otherwise it must be in relative coordinate space!
            blendEffect.TargetOutputOption = OutputOption.PreserveSize;

            renderer.Source = blendEffect;

            currentBgWidth += tileWidth;
            blendPosition.X = (double)currentBgWidth / (double)outBgWidth;  //Careful, the target area is in relative coordinates
        }

        currentBgHeight += tileHeight;
        blendPosition.Y = (double)currentBgHeight / (double)outBgHeight;    //Careful, the target area is in relative coordinates
        blendPosition.X = 0.0;
        currentBgWidth = 0;
    }

    var result = await renderer.RenderAsync();   //An IBuffer containing the Jpeg file
}

I have tried this solution in a sample and I can't see any artifacts. Please do come back and report your results though!

Upvotes: 2

Related Questions