如何在 C# 和 .NET 3.5 中减小图像的大小?

发布于 2024-09-26 13:05:37 字数 727 浏览 5 评论 0原文

我有一个在我的移动应用程序中拍摄的屏幕截图。当以 png 形式保存在磁盘上时,屏幕截图大约需要 32 KB。

我将这些发送到中央 SQL Server,32 KB 对于我需要存储该屏幕截图的次数(每天大约 2500 次)来说太大了。

有什么技巧可以让它节省得更小吗?

这是我现在使用的代码,将其从 Bitmap 转换为字节(发送到服务器进行存储):

MemoryStream stream = new MemoryStream();
 _signatureImage.Save(stream, ImageFormat.Png);
 return stream.ToArray();

_signatureImage 是 Bitmap是有问题的屏幕截图。

这是我保存的屏幕截图的示例:

Screen Shot Image 突然

浮现在脑海中的东西(但我不知道如何做):

  1. 减少图像的实际高度和宽度(但希望以不会扭曲图像的方式)。
  2. 将其更改为黑白图像(不确定我是否会从中看到任何真正的空间节省)
  3. 进一步压缩它(我不太喜欢这个,因为这样就无法从数据库中读取它)。

请注意,这一切都必须以编程方式完成,并且不会花费很长时间,因此复杂的图像操作已经过时了。

感谢您的任何帮助。

I have a screen shot I take in my mobile app. The screen shot takes about 32 KB when saved as a png on a disk.

I am sending these to a central SQL Server and 32 KB is too big for that amount of times I will need to store that screen shot (approx 2500 times a day).

Is there any kind of trickery that I can do to get it to save smaller?

Here is the code I am using now to take it from Bitmap to bytes (to send to the server for storage):

MemoryStream stream = new MemoryStream();
 _signatureImage.Save(stream, ImageFormat.Png);
 return stream.ToArray();

_signatureImage is a Bitmap and is the screenshot in question.

Here is an example of the screen shot I am saving:

Screen Shot Image

Things that pop to mind (but I don't know how to do them):

  1. Reduce the actual Height and Width of the image (but hopefully in a way that will not distort it).
  2. Change it to a black and white image (not sure if I will see any real space savings from this)
  3. Compress it more (I don't like this as much because then it is not readable from the database).

Note, this all has to be done programatically, and cannot take very long, so complex image manipulations are out.

Thanks for any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

花想c 2024-10-03 13:05:37
    private static Image ResizeImage(int newSize, Image originalImage)
    {
        if (originalImage.Width <= newSize)
            newSize = originalImage.Width;

        var newHeight = originalImage.Height * newSize / originalImage.Width;

        if (newHeight > newSize)
        {
            // Resize with height instead
            newSize = originalImage.Width * newSize / originalImage.Height;
            newHeight = newSize;
        }

        return originalImage.GetThumbnailImage(newSize, newHeight, null, IntPtr.Zero);
    }

这应该适用于您的位图对象类型并调整高度或宽度的大小,具体取决于哪个适合您的图像尺寸。它还将保持规模。

编辑:

您可以创建一个新的位图对象并将原始图像的大小调整为该位图对象。

Bitmap b = new Bitmap(newWidth, newHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;

g.DrawImage(imgToResize, 0, 0, newWidth, newHeight);
g.Dispose();

return (Image)b;

我没有安装 Compact Framework,但似乎这应该适合您。

    private static Image ResizeImage(int newSize, Image originalImage)
    {
        if (originalImage.Width <= newSize)
            newSize = originalImage.Width;

        var newHeight = originalImage.Height * newSize / originalImage.Width;

        if (newHeight > newSize)
        {
            // Resize with height instead
            newSize = originalImage.Width * newSize / originalImage.Height;
            newHeight = newSize;
        }

        return originalImage.GetThumbnailImage(newSize, newHeight, null, IntPtr.Zero);
    }

This should work with your Bitmap object Type and resize the Height or Width, depending on which is appropriate for your image dimensions. It will also maintain scale.

EDIT:

You could create a new Bitmap object and resize your original image into that Bitmap object.

Bitmap b = new Bitmap(newWidth, newHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;

g.DrawImage(imgToResize, 0, 0, newWidth, newHeight);
g.Dispose();

return (Image)b;

I don't have the Compact Framework installed, but it seems that this should work for you.

酒解孤独 2024-10-03 13:05:37

如果颜色深度不是问题,您可以将其更改为黑白或 16 色模式。与 png 的 24-bpp(或带 alpha 的 32-bpp)存储要求相比,应该可以节省大量成本。另一件需要考虑的事情是将其保存为 256 色模式的 .gif 文件。

当您保存签名数据时,我认为更改图像的尺寸是一个坏主意。您还可以考虑应用无损压缩(例如 zip),但这可能比您需要的计算密集度更高。

If color depth is not an issue, you might change it to black and white, or 16 color mode. There should be a significant savings over png's 24-bpp (or 32-bpp with alpha) storage requirements. The other thing to think about is saving it as a .gif file in 256 color mode.

As you're saving signature data, I'd think changing the dimensions of the image would be a bad idea. You might also consider applying a lossless compression like zip, but that is likely more computationally intensive than you require.

表情可笑 2024-10-03 13:05:37

将调色板更改为较低的颜色深度。看看这个问题(仔细看看答案)显示转换为 1bpp。您可以使用 8bpp 而不是 1bpp,并且可以显着节省大小。转换机制与所示的相同。

编辑

跳出框框,您还可以考虑仅发送屏幕上部的数据点和签名向量,然后让服务器为您重新创建屏幕。如果尺寸确实是一个大问题,我可能会对此进行调查。

编辑 2

如果简单地调整图像大小是一个合理的解决方案(这样做显然会丢失数据),那么您可以使用 SDF 中的 Imaging 命名空间来创建缩略图,如 Alex 在此解释

Change the color palette to a lower color depth. Take a look at this question (well look at the answert really) which shows converting to 1bpp. You could go to 8bpp instead of 1bpp and have significant size savings. The mechanism for conversion will be the same as what is shown.

EDIT

Thinking out of the box, you might also consider just sending the data points from the upper part of the screen and the signature vector, and have the server recreate the screen for you. If size really is a big issue, I'd probably investigate that.

EDIT 2

If simply resizing the image is a reasonable solution (you'll obviously lose data in doing so) then you can use the Imaging namespace in the SDF to create a thumbnail as Alex explains here.

你没皮卡萌 2024-10-03 13:05:37

如果单色图像可以接受,您可以尝试 TIFF G4(无损压缩)。 TIFF G4 因在文件大小方面非常有效地存储黑白图像而闻名。不幸的是,我没有任何关于它与 PNG 比较的信息,但值得研究一下。

此处 是有关如何在 C# 中执行此操作的信息和示例

If monochrome image is acceptable, you can try TIFF G4 (lossless compression). TIFF G4 is known for being very effective in file size to store black and white image. Unfortunately I dont have any info available on how it compares to PNG, but worth investigating into it.

Here is the info and example on how to do it in C#

ぇ气 2024-10-03 13:05:37

尝试转换为纯单色位图。它们非常小,因为它们每个像素仅使用一位。

编辑:我是个骗子。刚刚在 Paint 中尝试了一下,与原来的 20k 相比,大约是 40k。我可以发誓,当我以前使用它们时,它们可以节省大量空间......

编辑编辑:好的,显然他们确实节省了大量空间。只是对于这些图像来说,PNG 可以节省更多。只是尝试了 16 色位图,结果将其大小提高到了 150k。

编辑编辑编辑:但是,单色位图压缩到 9k 字节,而 PNG 即使压缩也保持在 20k。


所以,如果你想走压缩路线,你可以先转换为单色位图,然后将图像压缩为 PNG 大小的一半左右。

您还可以从图像中删除一些信息。例如,在该屏幕上,唯一真正需要保留图像的是签名。上面和下面的条可以被撕掉,并且数字信息可以按原样发送并单独存储。

Try converting to a pure monochrome bitmap. These are extremely small, since they only use one bit per pixel.

EDIT: I'm a liar. Just tried this in Paint and it's about 40k compared to the original 20k. I could have sworn those had massive space savings when I used them before...

EDIT EDIT: OK, apparently they do have massive savings. It's just that for these images, PNG has even more massive savings. Just tried a 16-color bitmap instead and that blew it up to 150k.

EDIT EDIT EDIT: BUT, the monochrome bitmap zips to 9k bytes, while the PNG stays at 20k even zipped.


So, it looks like if you want to go the compression route, you can first convert to monochrome bitmap, then compress for images around half the size of the PNG.

You could also strip some of the information out of the image. For instance, on that screen, the only thing that really needs to remain an image is the signature. The bars above and below that could be ripped out, and the numeric information could be sent as such and stored separately.

温柔戏命师 2024-10-03 13:05:37

用照片启动 Fireworks,照片不会相同,但应该给出一个想法

66% quality JPG with no smoothing is 17.5k
PNG8 with 256 colours is 58K (down to 42 using websnap palette)
PNG8 with black and white palette is 14k

请注意,许多图像文件在屏幕截图中会更小,因为存在大量相同颜色的连续分组,对于黑色来说尤其如此和白色。它可能还取决于用于转换图像的算法,但您可能只想使用您能找到的任何内容......

Firing up Fireworks with a photo, which won't be the same but should give an idea

66% quality JPG with no smoothing is 17.5k
PNG8 with 256 colours is 58K (down to 42 using websnap palette)
PNG8 with black and white palette is 14k

Note that many image files will be smaller with a screen shot since there are large contiguous groupings of the same colour, and that may be especially true with black and white. It will probably also depend on the algorithm used to convert the image, but you may want to just go with whatever you can find...

懵少女 2024-10-03 13:05:37

FWIW 将图像物理存储在 SQL Server 中并不是最佳解决方案。如果您使用的是 Sql Server 2008,您应该查看文件流支持,它允许您将物理映像存储在磁盘上并像访问 SQL Server 内部映像一样访问它们。这很可能会减轻您对文件大小的担忧。

FWIW storing the image physically inside SQL server isn't an optimal solution. If you're using Sql Server 2008 you should look at the file stream support that will let you store the physical images on disk and access them as if they were internal to SQL Server. This would most likely alleviate your need to worry about filesize.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文