1

1 つの 1bpp インデックス付き画像から新しい画像にカット アンド ペーストしています。

開始ピクセルが 8 の除数になるまで、すべてがうまく機能します。以下のコードでは、ストライドは、バイト境界に到達するまで、長方形の幅に相対的な値に等しくなります。次に、ストライドはページ全体の幅に等しくなります。

var croppedRect = new Rectangle((int)left, (int)top, (int)width, (int)height);
BitmapData croppedSource = _bitmapImage.LockBits(croppedRect, ImageLockMode.ReadWrite, BitmapImage.PixelFormat);
int stride = croppedSource.Stride;

マーシャルは、選択した領域を新しい画像に貼り付けるのではなく、ページの幅全体の断面、選択した領域の高さをコピーするため、これは問題です。

int numBytes = stride * (int)height;
var srcData = new byte[numBytes];

Marshal.Copy(croppedSource.Scan0, srcData, 0, numBytes);
Marshal.Copy(srcData, 0, croppedDest.Scan0, numBytes);
destBmp.UnlockBits(croppedDest);
4

1 に答える 1

5

これが興味のある人のための私のコードです。より最適な解決策があるかもしれませんが、これは機能します。ページ全体を白で作成し、新しいページを通過するときに、選択した領域を複製しています。SetIndexedPixelルーチンを提供してくれたBobPowellに感謝します。

protected int GetIndexedPixel(int x, int y, BitmapData bmd)
{
    var index = y * bmd.Stride + (x >> 3);
    var p = Marshal.ReadByte(bmd.Scan0, index);
    var mask = (byte)(0x80 >> (x & 0x7));
    return p &= mask;
}

protected void SetIndexedPixel(int x, int y, BitmapData bmd, bool pixel)
{
    int index = y * bmd.Stride + (x >> 3);
    byte p = Marshal.ReadByte(bmd.Scan0, index);
    byte mask = (byte)(0x80 >> (x & 0x7));
    if (pixel)
        p &= (byte)(mask ^ 0xff);
    else
        p |= mask;
    Marshal.WriteByte(bmd.Scan0, index, p);
}

public DocAppImage CutToNew(int left, int top, int width, int height, int pageWidth, int pageHeight)
{
    var destBmp = new Bitmap(pageWidth, pageHeight, BitmapImage.PixelFormat);
    var pageRect = new Rectangle(0, 0, pageWidth, pageHeight);

    var pageData = destBmp.LockBits(pageRect, ImageLockMode.WriteOnly, BitmapImage.PixelFormat);
    var croppedRect = new Rectangle(left, top, width, height);
    var croppedSource = BitmapImage.LockBits(croppedRect, ImageLockMode.ReadWrite, BitmapImage.PixelFormat);

    for (var y = 0; y < pageHeight; y++)
        for (var x = 0; x < pageWidth; x++)
        {
            if (y >= top && y <= top + height && x >= left && x <= width + left)
            {
                SetIndexedPixel(x, y, pageData,
                                GetIndexedPixel(x - left, y - top, croppedSource) == 0 ? true : false);
                SetIndexedPixel(x - left, y - top, croppedSource, false); //Blank area in original
            }
            else
                SetIndexedPixel(x, y, pageData, false);  //Fill the remainder of the page with white.
        }

    destBmp.UnlockBits(pageData);

    var retVal = new DocAppImage { BitmapImage = destBmp };
    destBmp.Dispose();

    BitmapImage.UnlockBits(croppedSource);
    SaveBitmapToFileImage(BitmapImage);

    return retVal;
}
于 2012-04-12T14:08:00.633 に答える