How to effectively crop * indexed * Bitmap and get * indexed * result?

If you are here because of the name, you probably just skip the question and go to the answers. Turns out I had a simple error in my code.

I try to work exclusively with indexed images, because the bulk of my project involves sharing palettes. I tried the following few lines of code as part of a larger process:

        Bitmap raw = ((Bitmap)i).Clone(region, PixelFormat.Format8bppIndexed);
        byte transparent = (byte)(Array.FindIndex(raw.Palette.Entries, x => x.A < 128));
        // Scan the bitmap for the first opaque pixel on each side
        BitmapData bd = raw.LockBits(region, ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);

Basically, I wanted to crop the specified regioninput, and then perform manipulations at the lower level on this part of the image.

The listing succeeds (and I can verify that it is an indexed bitmap at this point, but it is stored in the control, hence the loss of type information). It seems that the clone call succeeds. Debugging shows that PixelFormatof is rawvalid PixelFormat.Format8bppIndexedas well as meaning (Bitmap)i. Calculating the index of a transparent palette works fine. But then it raw.LockBitsfails, complaining of an invalid parameter.

Even a stranger raw.LockBitswill succeed if I delete the call .Clone(but the rest of the code will do the wrong thing because the source has not been trimmed).

Per , , Clone - , , LockBits - . ? Graphics.DrawImage , , .

RGB, ? - ?

+4
1

@Peter Duniho ​​ , . : .Clone() :

Bitmap cropped = original.Clone(region, PixelFormat.Format8bppIndexed);

,

Bitmap cropped = original.Clone(region, original.PixelFormat);

region - Rectangle. , LockBits, region - , , Rectangle, (0, 0) X Y.

, :

  • region, Bitmap, .. X Y , X + Width Bitmap Width, Y + Height Bitmap Height - Bitmap, . .

  • region Bitmap.LockBits , , System.ArgumentException. " ". , , .

  • region Bitmap.Clone , System.ArgumentException, . , , System.OutOfMemoryException. , 0 , - .

, , , :

// Create a cropped `region` of the `original` Bitmap as a new bitmap,
// preserving the original pixel format. If negative Width or Height
// are provided for the clip region and `flipNegative` is set, the result
// is flipped accordingly.
public Bitmap crop(Bitmap original, Rectangle region, bool flipNegative) {
    Rectangle bounds = new Rectangle(new Point(0, 0), original.Size);
    if (region.Width == 0 || region.Height == 0) { return null; }

    // Normalize width and height parameters,
    // and track whether we might need to flip.
    bool flipHorizontal = region.Width < 0;
    bool flipVertical = region.Height < 0;
    if (flipHorizontal)
    {
        region.X += region.Width;
        region.Width = -region.Width;
    }
    if (flipVertical)
    {
        region.Y += region.Height;
        region.Height = -region.Height;
    }

    // Ensure we have a valid clipping rectangle, and make the GDI call.
    if (!region.IntersectsWith(bounds)) { return null; }
    region.Intersect(bounds);
    Bitmap result = original.Clone(region, original.PixelFormat);

    // Flip the result as appropriate.
    if (flipHorizontal && flipNegative)
    {
        result.RotateFlip(RotateFlipType.RotateNoneFlipX);
    }
    if (flipVertical && flipNegative)
    {
        result.RotateFlip(RotateFlipType.RotateNoneFlipY);
    }
    return result;
}

( flipNegative, , , .)

LockBits, , - .

+2

Source: https://habr.com/ru/post/1568575/


All Articles