MWNumericArray(或字节[,])转换为Format1bppIndexed图像

时间:2018-09-04 09:34:15

标签: c# image matlab bitmap

我正在尝试将Matlab MWNumericArray转换为黑白图片(不是灰度)。最初,我尝试将2D字节数组转换为1D字节数组,然后将其复制到BitmapData对象并在Bitmap中进行转换,但是没有用,因为尝试操作此数据时我必须犯一些错误。

有效的方法是将我从其他答案和在线文档中获得的代码混合在一起。以下是有效的方法和无效的方法。

问题: 是否有一种简单的方法,可以从byte[,]数组开始,而不使用GetPixelClone方法,将8bpp位图转换为1bpp,一次或一个字节地复制?允许使用不安全的代码。

我尝试过的方法(有效):

// Most of this code is based on a Jon Skeet's answer.
// resultOut[0] is a 2D 356x356 MWArray
var numArray = (MWNumericArray)resultOut[0];
var data = numArray.ToArray(MWArrayComponent.Real) as byte[,];

var w = data.GetLength(0);
var h = data.GetLength(1);

unsafe
{
    fixed (byte* ptr = data)
    {
        var scan0 = new IntPtr(ptr);

        var bpm1 = new Bitmap(
            w, h, // image size
            w,    // scan size
            PixelFormat.Format8bppIndexed, scan0);

        // works but is grayscale, not B&W
        var palette = bpm1.Palette;
        palette.Entries[0] = Color.Black;
        for (var i = 1; i < 256; i++)
        {
            palette.Entries[i] = Color.FromArgb((i * 7) % 256, (i * 7) % 256, 255);
        }
        bpm1.Palette = palette;
        bpm1.Save("output.grayscale.png");

        // works but with additional helper method call 
        // based on a Hans Passant answer
        var bpm2 = BitmapTo1Bpp(bpm1);
        bpm2.Save("output.helper.png");

        // works but uses Clone
        var bpm3 = bpm1.Clone(new Rectangle(0, 0, bpm1.Width, bpm1.Height), PixelFormat.Format1bppIndexed);
        bpm3.Save("output.clone.png");
    }
}

我尝试过的方法(没有用):

if (numArray.ToArray(MWArrayComponent.Real) is byte[,] data)
{
    // Convert to 1D byte array
    var h = data.GetLength(1);
    var w = data.GetLength(0);
    var byteArray1D = new byte[h * w];
    for (var i = 0; i < h; i++)
    {
        for (var j = 0; j < w; j++)
        {
          byteArray1D[i + j] = data[i, j];
        }
    }

    // Create Bitmap object
    var bmp = new Bitmap(w, h, PixelFormat.Format8bppIndexed);

    //// Set palette
    // var cp = bmp.Palette;
    // for (var i = 0; i < 256; ++i)
    // {
    //     cp.Entries[i] = Color.FromArgb(255, i, i, i);
    // }
    // bmp.Palette = cp;

    var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
        ImageLockMode.WriteOnly,
        bmp.PixelFormat);

    Marshal.Copy(byteArray1D,
        0,
        bmpData.Scan0,
        byteArray1D.Length);
    bmp.UnlockBits(bmpData);

    // Does not work: graphic object cannot be created from an image that has an indexed pixel format
    using (var g = Graphics.FromImage(bmp))
    {
      g.Clear(Color.White);
    }

    // Does not work: saves all black image
    bmp.Save("output.raw.png");

    using (var ms = new MemoryStream())
    {
        ms.Write(byteArray1D, 0, byteArray1D.Length);
        ms.Seek(0, SeekOrigin.Begin); // ms.Position = 0;

        // Does not work: parameter is not valid exception
        var bm = new Bitmap(ms);
        bm.Save("output.ms.png");

        // Does not work: parameter is not valid exception
        var newImage = Image.FromStream(ms);
        newImage.Save("output.fromstream.png");
    }
}

0 个答案:

没有答案