GDI+无法保存PNG文件(C#)

4

编辑:

看起来这是一个文件大小的问题。我正在处理的文件大小为10600 x 700像素。这最终成为了一个约280 MB的位图。我已经尝试将明显小得多的文件大小(10x10)保存为PNG格式,它们能够正确保存。是否存在GDI+所达到的大小限制?

几乎完整的代码:

class Converter
{
    /* Each PNG below is 50x50 */
    private static readonly int BLOCK_SIZE = 50;

    private static Dictionary<char, Bitmap> BlockLookup => new Dictionary<char, Bitmap>
    {
        {'R', new Bitmap("Content/Map/Blocks/RedBlock.png")},
        {'G', new Bitmap("Content/Map/Blocks/GreenBlock.png")},
        {'B', new Bitmap("Content/Map/Blocks/BlueBlock.png")},
        {'P', new Bitmap("Content/Map/Blocks/PurpleBlock.png")},
        {'Y', new Bitmap("Content/Map/Blocks/YellowBlock.png")},
        {'O', new Bitmap("Content/Map/Blocks/OrangeBlock.png")}
    };

    public void Convert(string textFilePath, string outputDirectory)
    {
        List<string> fileContents = new List<string>();
        /* Irrelevant loading code snipped, loads text file into fileContents */
        int width = fileContents.Max(line => line.Length) * BLOCK_SIZE; // 10600
        int height = fileContents.Count * BLOCK_SIZE; // 700

        /* Try to convert our text-file-as-image into a real image, mapping chars to their blocks */
        using (Bitmap bitmap = new Bitmap(width, height))
        {
            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                graphics.Clear(Color.WhiteSmoke);
                graphics.SmoothingMode = SmoothingMode.AntiAlias;

                for (int y = 0; y < fileContents.Count; ++y)
                {
                    for (int x = 0; x < fileContents[y].Length; ++x)
                    {
                        char currentCharacter = fileContents[y][x];
                        if (!blockLookup.ContainsKey(currentCharacter))
                        {
                            continue;
                        }
                        Bitmap mapBlock = blockLookup[currentCharacter];
                        var mapX = x * BLOCK_SIZE;
                        var mapY = y * BLOCK_SIZE;
                        graphics.DrawImage(mapBlock, new Point(mapX, mapY));
                    }
                }
                graphics.Flush(FlushIntention.Sync);
                graphics.Save();
            }
            if (!Directory.Exists(outputDirectory))
            {
                Directory.CreateDirectory(outputDirectory);
            }
            bitmap.Save(outputDirectory + mapName, ImageFormat.Png);
        }

    }
}

我有以下代码:
using (Bitmap bitmap = new Bitmap(width, height))
{
    using (Graphics graphics = Graphics.FromImage(bitmap))
    {
        graphics.Clear(Color.WhiteSmoke);
        /* SNIP, a bunch of image manipulation here */
        graphics.Flush();
    }

    if (!Directory.Exists(outputDirectory))
    {
        Directory.CreateDirectory(outputDirectory);
    }
    bitmap.Save(outputDirectory + imageName, ImageFormat.Bmp);
}

这段代码工作得很好。但是,如果我将ImageFormat从ImageFormat.Bmp更改为ImageFormat.Png,就会收到“在GDI+中发生通用错误”的错误消息。我在stackoverflow和谷歌上搜寻过了。文件不存在,路径存在。我已经删除了所有输出文件。我尝试了64位和32位构建。即使像复制Bitmap并写入内存流这样的操作也失败了(下面的代码不起作用):

using (Bitmap bitmap = new Bitmap(width, height))
{
    using (Graphics graphics = Graphics.FromImage(bitmap))
    {
        graphics.Clear(Color.WhiteSmoke);
        /* SNIP, a bunch of image manipulation here */
        graphics.Flush();
    }

    if (!Directory.Exists(outputDirectory))
    {
        Directory.CreateDirectory(outputDirectory);
    }
    using (MemoryStream memoryStream = new MemoryStream())
    {
        Bitmap temp = new Bitmap(bitmap);
        temp.Save(memoryStream, ImageFormat.Png);
    }
}

我希望能够输出PNG文件。然而,我不知道我的GDI版本与PNG文件是否存在某些问题。有没有什么方法可以使我得到PNG输出?


在第一个示例中更改图像名称和图像格式应该可以。你能读取PNG文件吗?这些图片有多大? - TaW
很遗憾,将名称更改为$whatever.png和ImageFormat并不起作用。我可以完美地读取PNG文件(我加载一些文件以在图形对象内进行一些图像操作,它们都在触发保存之前关闭)。图像大小为10600 x 700像素。 - wallstop
你能发布一下你剪贴的图像操作吗? - thomasb
2个回答

2
抱歉,但是您的代码运行得非常好 - 我在Windows Server 2012 R2上使用VS 2013 Express for Win Desktop测试过了 - 没有任何问题。 < p > 测试1:

private int width = 10600;
private int height = 700;
using (Bitmap bitmap = new Bitmap(width, height))
        {
            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                graphics.Clear(Color.Black);
                /* SNIP, a bunch of image manipulation here */
                graphics.Flush();

            }
            bitmap.Save("image.png", ImageFormat.Png);

        }
    }

测试2:

private int width = 10600;
private int height = 700;
using (Bitmap bitmap = new Bitmap(width, height))
        {
            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                graphics.Clear(Color.Black);
                /* SNIP, a bunch of image manipulation here */
                //I read a little around - maybe your graphics operations are out of sync?
                graphics.Flush(FlushIntention.Sync);
                graphics.Save();


            }

            using (MemoryStream memoryStream = new MemoryStream())
            {
                Bitmap temp = new Bitmap(bitmap);
                //temp.Save("image.png", ImageFormat.Png); //this worked obviously
                temp.Save(memoryStream, ImageFormat.Png);

                pictureBox1.Image = Image.FromStream(memoryStream); //a huge black box appears - everything is working fine
            }
        }
    }

也许您的系统存在问题? 我本来想发表评论,但声望不够 =,(

感谢您尝试我的代码!问题可能确实存在于程序的范围之外,我正在运行Win7Ultimatex64和Visual Studio 2015 RC。这可能是一个大小问题——我正在处理的图像大小为10600x700像素(可以说很大,但远未达到GB级别)。在提交问题后,我测试了一些较小的PNG文件(10x10),它们能够保存。我将在问题中添加此信息。 - wallstop
哦,我用你提供的值初始化了宽度和高度 - 没问题! - Juergen

1
也许这不值得作为一个答案,应该作为一个评论。但如果你想移动它的话我可以帮你 :)
确实,Windows 7 在处理大图片方面存在一些问题,不确定是与 GDI+ 相关还是更深层次的核心问题。但是我曾经编写了一款用于大学的照片编辑软件,并注意到,我无法加载和/或格式化大于 ~180MB 的图片。我通过将其导入数组并进行切片来找到了一种解决方法。但我不知道你是否能使用它。如果我找到那段代码,我会更新这篇文章。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接