You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过流从任意文件创建图片?Image.Save内存不足异常排查

问题分析与解决

错误原因

Image.FromFile仅能加载**符合标准图像格式(如PNG、JPG、BMP等)**的文件,你传入的redo.none是任意非图像文件,GDI+无法将其解析为有效的Image对象,后续调用Save时抛出的“内存不足异常”是误导性报错——实际并非内存不足,而是图像数据无效。

正确实现思路

要将任意文件转成图片,核心是把文件的二进制数据编码到合法的图像结构中,而非直接用Image类加载非图像文件。以下是两种可行方案:

方案一:将文件数据映射为像素图像

把文件的每个字节值作为像素灰度值,生成对应尺寸的灰度图,适合可视化文件数据:

byte[] fileData = File.ReadAllBytes("redo.none");
// 计算图像尺寸,确保总像素数≥文件字节数
int width = (int)Math.Ceiling(Math.Sqrt(fileData.Length));
int height = width;

// 用LockBits提升大文件处理效率,避免SetPixel的性能问题
using (Bitmap bmp = new Bitmap(width, height))
{
    BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
    // 设置灰度调色板
    ColorPalette palette = bmp.Palette;
    for (int i = 0; i < 256; i++)
    {
        palette.Entries[i] = Color.FromArgb(i, i, i);
    }
    bmp.Palette = palette;

    // 复制文件数据到图像内存
    Marshal.Copy(fileData, 0, bmpData.Scan0, fileData.Length);
    bmp.UnlockBits(bmpData);

    bmp.Save("blyad.png");
}

方案二:将文件数据嵌入PNG元数据

如果不需要可视化,仅需把文件数据隐藏在图片中,可将其存入PNG的附加元数据块:

byte[] fileData = File.ReadAllBytes("redo.none");
using (Bitmap bmp = new Bitmap(1, 1)) // 创建最小尺寸的空白图像
{
    // 创建自定义属性存储文件数据
    PropertyItem propItem = bmp.PropertyItems[0];
    propItem.Id = 0x8000; // 自定义属性ID(避免冲突)
    propItem.Type = 1; // 字节数组类型
    propItem.Len = fileData.Length;
    propItem.Value = fileData;
    bmp.SetPropertyItem(propItem);

    bmp.Save("blyad.png");
}

大文件场景优化(结合MemoryMappedFile)

如果文件超大,避免一次性加载全部数据到内存,可使用MemoryMappedFile分块读取并处理:

using (var mmf = MemoryMappedFile.CreateFromFile("redo.none", FileMode.Open))
{
    long fileLength = new FileInfo("redo.none").Length;
    int width = (int)Math.Ceiling(Math.Sqrt(fileLength));
    int height = width;
    using (Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed))
    {
        // 设置灰度调色板
        ColorPalette palette = bmp.Palette;
        for (int i = 0; i < 256; i++)
        {
            palette.Entries[i] = Color.FromArgb(i, i, i);
        }
        bmp.Palette = palette;

        BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
        long offset = 0;
        int chunkSize = 4096; // 每次读取4KB块

        while (offset < fileLength)
        {
            int bytesToRead = (int)Math.Min(chunkSize, fileLength - offset);
            using (var stream = mmf.CreateViewStream(offset, bytesToRead))
            {
                byte[] chunk = new byte[bytesToRead];
                stream.Read(chunk, 0, bytesToRead);
                Marshal.Copy(chunk, 0, IntPtr.Add(bmpData.Scan0, (int)offset), bytesToRead);
            }
            offset += chunkSize;
        }

        bmp.UnlockBits(bmpData);
        bmp.Save("blyad.png");
    }
}

内容的提问来源于stack exchange,提问作者Jut Rut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 15:45:51