Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitmap.LockBits error "Parameter is not valid" when bitmap is a certain size?

I have create a method where I want to take an image mask and apply it to another image. If you have a look at this post, you will see a frame image. The frame image in that post is the maskingImage and the background image is the imageToMask. The masking image is really an image with a hot pink center. This is the process the method goes through:

  1. The masking image is a PNG and the image to mask is a JPG.
  2. The method traces the masking image and draws the image to mask over it. This helps keep the outer transparency intact.
  3. The output form that is then drawn underneath the masking image and we make the hot pink color transparent.

The line var bitsimageToMask = imageToMask.LockBits... is where I get my error. If the width or height of the image to mask is smaller than the masking image, I get the "Parameter is not valid" error. I am a newbie when it comes to working with bitmaps.

public Bitmap RenderMaskedImage(Bitmap maksingImage, Bitmap imageToMask, Point imageToMaskOffset, ImageFormat imageFormat)
{
    using (var newImageToMaskGraphic = Graphics.FromImage(imageToMask))
    {
    newImageToMaskGraphic.DrawImage(imageToMask, imageToMaskOffset);
    }

    var output = new Bitmap(maksingImage.Width, maksingImage.Height, PixelFormat.Format32bppArgb);
    var rect = new Rectangle(0, 0, maksingImage.Width, maksingImage.Height);
    var bitsMask = maksingImage.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    var bitsimageToMask = imageToMask.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    var bitsOutput = output.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

    unsafe
    {
        for (int y = 0; y < maksingImage.Height; y++)
        {
            var ptrMask = (byte*)bitsMask.Scan0 + y * bitsMask.Stride;
            var ptrimageToMask = (byte*)bitsimageToMask.Scan0 + y * bitsimageToMask.Stride;
            var ptrOutput = (byte*)bitsOutput.Scan0 + y * bitsOutput.Stride;
            for (int x = 0; x < maksingImage.Width; x++)
            {
                ptrOutput[4 * x] = ptrimageToMask[4 * x];           // blue
                ptrOutput[4 * x + 1] = ptrimageToMask[4 * x + 1];   // green
                ptrOutput[4 * x + 2] = ptrimageToMask[4 * x + 2];   // red
                ptrOutput[4 * x + 3] = ptrMask[4 * x + 3];        // alpha 
            }
        }
    }

    maksingImage.UnlockBits(bitsMask);
    imageToMask.UnlockBits(bitsimageToMask);
    output.UnlockBits(bitsOutput);

    using (var outputGraphic = Graphics.FromImage(output))
    {
        outputGraphic.DrawImage(maksingImage.ToTransparentColor(255,0,192), 0, 0);
    }

    return output;
}
like image 823
DDiVita Avatar asked Dec 14 '12 18:12

DDiVita


1 Answers

The reason is the rect you are using on the imageToMask is bigger then the bitmap itself.

var rect = new Rectangle(0, 0, maksingImage.Width, maksingImage.Height);
var bitsimageToMask = imageToMask.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

The rect is used to specify the area of the bitmap which needs to be locked. This rect can be the same size or smaller than the bitmap but can not be bigger. In your case because you use the rect based on your maskingImage the rect becomes bigger than the bitmap you are using it on which gives you that error.

like image 81
Rutix Avatar answered Oct 04 '22 21:10

Rutix