C# Image转变Bitmap时候出现变异。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# Image转变Bitmap时候出现变异。相关的知识,希望对你有一定的参考价值。

private void button1_Click(object sender, EventArgs e) if (openFileDialog1.ShowDialog() == DialogResult.OK) filename = openFileDialog1.FileName; pictureBox1.Image = Image.FromFile(filename); private void button2_Click(object sender, EventArgs e) //g_bm_bitmap = (Bitmap)Image.FromFile(filename); g_bm_bitmap = new Bitmap(Image.FromFile(filename)); Bitmap second = g_bm_bitmap; pictureBox1.Image = g_bm_bitmap;从Image转换bitmap的时候显示bitmap发现和原先的不同了,黑色区域突然变出很多红色点。。。求解答。。。。
http://pan.baidu.com/s/1qY6CmVa
谢谢各位哦

我用你的代码测试了,没发现这个问题,用的图片格式是png,gif的都没问题。你把你的原图发上来我试试。追问

http://pan.baidu.com/s/1qY6CmVa

参考技术A 共享项目源码来调试。

C#如何在不使用大量内存的情况下裁剪图像? [复制]

【中文标题】C#如何在不使用大量内存的情况下裁剪图像? [复制]【英文标题】:C# How to crop an image without using lots of memory? [duplicate] 【发布时间】:2012-11-23 15:23:05 【问题描述】:

可能重复:How to crop huge image

有个问题问如何裁剪图片here

我已经阅读并使用了答案。但它们似乎都需要将图像加载到BitmapImage

这导致我出现内存问题。当我试图将 5 张图像 (8000 x 8000) 裁剪成图块时。一次一个。

如果我错了,请纠正我,但那是 8000x8000x4 字节 = 244 MB。每张图片。

我随机出现内存不足的问题。

如何从另一个图像中获取 1000x1000 的图像,同时减少内存消耗。

【问题讨论】:

您想裁剪图像而不将其加载到内存中?为什么你必须同时处理所有 5 张图像?处理一个,关闭它,然后处理另一个。 您的内存不足问题可能与您的代码有关。你能告诉我们你用来裁剪图像的代码吗? 不幸的是 .NET 没有办法只加载图像的一小部分。 这是什么平台/类?我知道一些平台(Silverlight、Unity3D)可以使用比每个像素 4 个字节更多的内存。 @Tibi。这正是我想要做的:p。以编程方式将图像拆分为图块。图像最终出现在 android 上(每像素 4 个字节,~24MB 内存余量)。问题是桌面也有/可能有内存限制。 (不要尝试使用整个位图,因为有人似乎认为重复 - 而其他裁剪图像“答案”是 10 分钟前)。 【参考方案1】:

因此,这绝对是一件非常重要的事情 - 基本上,您必须为给定的图像格式重新实现图像解码器。这不简单

对于“简单”的 Windows BMP 格式,有这些野兽要与之抗衡:

BMP File Format DIB Header Structure

也就是说,我必须在午休时试一试……这是我能想到的,用一个漂亮的 LINQPad 就绪脚本。

(注意:仅限 Windows BMP!)

void Main()

    // Carve out a 100x100 chunk
    var top = 100;
    var left = 100;
    var bottom = 300;
    var right = 300;

    // For BMP only - open input
    var fs = File.OpenRead(@"c:\temp\testbmp.bmp");

    // Open output
    if(File.Exists(@"c:\temp\testbmp.cropped.bmp")) File.Delete(@"c:\temp\testbmp.cropped.bmp");
    var output = File.Open(@"c:\temp\testbmp.cropped.bmp", FileMode.CreateNew);
    var bw = new BinaryWriter(output);

    // Read out the BMP header fields
    var br = new BinaryReader(fs);
    var headerField = br.ReadInt16();
    var bmpSize = br.ReadInt32();
    var reserved1 = br.ReadInt16();
    var reserved2 = br.ReadInt16();
    var startOfData = br.ReadInt32();   

    // Read out the BMP DIB header
    var header = new BITMAPV5Header();  
    var headerBlob = br.ReadBytes(Marshal.SizeOf(header));
    var tempMemory = Marshal.AllocHGlobal(Marshal.SizeOf(header));
    Marshal.Copy(headerBlob, 0, tempMemory, headerBlob.Length);
    header = (BITMAPV5Header)Marshal.PtrToStructure(tempMemory, typeof(BITMAPV5Header));
    Marshal.FreeHGlobal(tempMemory);

    // This file is a 24bpp rgb bmp, 
    var format = PixelFormats.Bgr24;
    var bytesPerPixel = (int)(format.BitsPerPixel / 8);
    Console.WriteLine("Bytes/pixel:0", bytesPerPixel);

    // And now I know its dimensions
    var imageWidth = header.ImageWidth;
    var imageHeight = header.ImageHeight;
    Console.WriteLine("Input image is:0x1", imageWidth, imageHeight);

    var fromX = left;
    var toX = right;
    var fromY = imageHeight - top;
    var toY = imageHeight - bottom;

    // How "long" a horizontal line is
    var strideInBytes = imageWidth * bytesPerPixel;
    Console.WriteLine("Stride size is:0x0:x", strideInBytes);

    // new size
    var newWidth = Math.Abs(toX - fromX);
    var newHeight = Math.Abs(toY - fromY);
    Console.WriteLine("New slice dimensions:0x1", newWidth, newHeight);

    // Write out headers to output file 
    
        // header = "BM" = "Windows Bitmap"
        bw.Write(Encoding.ASCII.GetBytes("BM"));    
        var newSize = 14 + Marshal.SizeOf(header) + (newWidth * newHeight * bytesPerPixel);
        Console.WriteLine("New File size: 0x0:x bytes", newSize);
        bw.Write((uint)newSize);    
        // 2 reserved shorts
        bw.Write((ushort)0);    
        bw.Write((ushort)0);            
        // offset to "data"
        bw.Write(header.HeaderSize + 14);

        // Tweak size in header to cropped size
        header.ImageWidth = newWidth;
        header.ImageHeight = newHeight;

        // Write updated DIB header to output
        tempMemory = Marshal.AllocHGlobal(Marshal.SizeOf(header));
        Marshal.StructureToPtr(header, tempMemory, true);
        byte[] asBytes = new byte[Marshal.SizeOf(header)];
        Marshal.Copy(tempMemory, asBytes, 0, asBytes.Length);
        Marshal.FreeHGlobal(tempMemory);
        bw.Write(asBytes);
        asBytes.Dump();
    

    // Jump to where the pixel data is located (on input side)
    Console.WriteLine("seeking to position: 0x0:x", startOfData);
    fs.Seek(startOfData, SeekOrigin.Begin);

    var sY = Math.Min(fromY, toY);
    var eY = Math.Max(fromY, toY);
    for(int currY = sY; currY < eY; currY++)
    
        long offset =  startOfData + ((currY * strideInBytes) + (fromX * bytesPerPixel));
        fs.Seek(offset, SeekOrigin.Begin);      

        // Blast in each horizontal line of our chunk
        var lineBuffer = new byte[newWidth * bytesPerPixel];
        int bytesRead = fs.Read(lineBuffer, 0, lineBuffer.Length);
        output.Write(lineBuffer, 0, lineBuffer.Length);
    

    fs.Close();
    output.Close();


[StructLayout(LayoutKind.Sequential, Pack=0)]
public struct BITMAPV5Header 

    public uint HeaderSize;
    public int ImageWidth;
    public int ImageHeight;
    public ushort Planes;
    public ushort BitCount;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst=36)]
    public byte[] DontCare;

【讨论】:

+1 只是为了展示它的复杂程度,仅适用于单个文件类型。不幸的是,我需要使用一些文件类型。

以上是关于C# Image转变Bitmap时候出现变异。的主要内容,如果未能解决你的问题,请参考以下文章

在C#中图像识别的时候出现内存不足的原因

C# bitmap保存时GDI+出现一般性错误?

java将base64转换成图片并保存在指定路径下ImageIO.write(bi1,"png",w2)提示image==null

玩游戏出现bitmap image is not valid如何解决

将C#的bitmap格式转换为Halcon的图像格式

变异简介