【问题标题】:Cutting an image with c#, memorystream, graphics and image用c#、memorystream、图形和图像切割图像
【发布时间】:2012-10-04 15:27:12
【问题描述】:

我在剪切图像时遇到问题。

我想要做的是,在一些切片中切割图像,主要是二次的。 该代码尚未针对边界值进行细化,不应将整个图像切割成适当的大小,但这目前不是问题。

我的问题是,被剪切的第一张图像实际上是原始图像的一部分,但第二张图像(或之后的所有图像)只有黑色。我只是在死胡同,我不知道问题是什么。

            var sourceImg = System.Drawing.Image.FromFile(args[numcount]);

                int cutsizeHeight = sourceImg.Height < cutsize ? sourceImg.Height : cutsize;
                int cutsizeWidht = sourceImg.Width < cutsize ? sourceImg.Width : cutsize;

                int cutPassesHeight = (int)(sourceImg.Height / cutsize) == 0 ? 1 : (int)(sourceImg.Height / cutsize);
                int cutPassesWidth = (int)(sourceImg.Width / cutsize) == 0 ? 1 : (int)(sourceImg.Width / cutsize);

                for (int i = 0; i < cutPassesHeight; i++)
                {
                    for (int j = 0; j < cutPassesWidth; j++)
                    {
                        var mem = new MemoryStream();
                        var sourcePositionX = i * cutsizeHeight;
                        var sourcePositionY = j * cutsizeWidht;
                        var cutRectangle = new System.Drawing.Rectangle(0, 0, cutsizeWidht, cutsizeHeight);

                        var newImage = new Bitmap(cutRectangle.Width, cutRectangle.Height);
                        Graphics g = Graphics.FromImage(newImage);
                        g.DrawImage(sourceImg, cutRectangle, sourcePositionX, sourcePositionY, cutsizeWidht, cutsizeHeight, GraphicsUnit.Pixel);
                        newImage.Save(mem, ImageFormat.Png);

                        var saveImage = System.Drawing.Image.FromStream(mem);
                        var fileName = System.IO.Path.GetFileName(args[numcount]);
                        var pureName = fileName.Split('.');
                        fileName = pureName[0] + i.ToString() + "_" + j.ToString() + ".png";
                        saveImage.Save(@"C:\usr\test\" + fileName);
                    }
                }

这是我的代码 sn-p。 目前我正在使用图像大小 5906 * 1773 对其进行测试。每个切割图像的切片尺寸应为 2096 * 1773。因此上面的代码忽略了宽度中 1714 的其余部分(2096 * 2 = 4192,其余 5906 - 4192 = 1714 )。不过没关系。

问题是,第二个不是图像,而是黑色的。

【问题讨论】:

    标签: c# image memory graphics


    【解决方案1】:

    问题在于您将绘制的图像向右和向下移动,而不是向左和向上移动。您将在新图像之外完全绘制源图像:

    First image:  Second image:     Third image:
    +---+----+    +---+--------+    +---+    +--------+
    | d |    |    | d |        |    | d |    |        |
    +---+    |    +---+    s   |    +---+    |    s   |
    |     s  |        |        |             |        |
    +--------+        +--------+             +--------+
    

    使用负坐标:

    var sourcePositionX = -i * cutsizeHeight;
    var sourcePositionY = -j * cutsizeWidht;
    

    附带说明;您将图像保存到内存流中,然后从内存流中加载它并将其保存到文件中。直接保存到文件即可。

    【讨论】:

    • 这没有成功,第二张图片在这里仍然是黑色的。我怀疑矩形或 g.DrawImage 有问题;我明天会调查。在您的侧节点上发表评论:如果我直接保存 i,c# 会引发内存不足异常。这个内存流可以提升性能并且可以处理更大的文件。
    • @TonyB:我明白了,您还使用了DrawImage 的重载来缩放图像。改用这个重载,它只获取图像和目标坐标:msdn.microsoft.com/en-us/library/558kfzex.aspx
    • 还是不行。现在图像将被缩放,第二张图像将再次变黑。
    • @TonyB:我使用负坐标和不缩放图像的重载测试了代码,效果很好。
    • @TonyB:使用int cutPassesHeight = (sourceImg.Height+cutsize) / cutsize; 计算覆盖所有图像的片段数。另外,你把i 和j 搞混了; i 是垂直计数器,但它是用来计算水平坐标的。
    【解决方案2】:

    好的,解决方法是:使用原始代码但这是错误的,所以不要使用:

    var sourcePositionX = i * cutsizeHeight;
    var sourcePositionY = j * cutsizeWidht;
    

    使用正确:

    var sourcePositionY = i * cutsizeHeight;
    var sourcePositionX = j * cutsizeWidht;
    

    坐标系中的X代表宽度,我只是在这里犯了一个小X/Y错误。现在可以了。

    【讨论】:

      猜你喜欢
      • 2015-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-18
      • 2019-09-18
      • 2011-10-04
      相关资源
      最近更新 更多