减少图像中的颜色深度并不会减小文件大小?

我使用此代码来减少图像的深度:

public void ApplyDecreaseColourDepth(int offset) { int A, R, G, B; Color pixelColor; for (int y = 0; y < bitmapImage.Height; y++) { for (int x = 0; x < bitmapImage.Width; x++) { pixelColor = bitmapImage.GetPixel(x, y); A = pixelColor.A; R = ((pixelColor.R + (offset / 2)) - ((pixelColor.R + (offset / 2)) % offset) - 1); if (R < 0) { R = 0; } G = ((pixelColor.G + (offset / 2)) - ((pixelColor.G + (offset / 2)) % offset) - 1); if (G < 0) { G = 0; } B = ((pixelColor.B + (offset / 2)) - ((pixelColor.B + (offset / 2)) % offset) - 1); if (B < 0) { B = 0; } bitmapImage.SetPixel(x, y, Color.FromArgb(A, R, G, B)); } } } 

第一个问题是:我给函数的偏移量不是深度,是吗?

第二个是当我在减少颜色深度后尝试保存图像时,我获得与原始图像相同的大小。 我应该得到一个更小的文件,或者我错了,这是不合逻辑的。

这是我用来保存修改后的图像的代码:

 private Bitmap bitmapImage; public void SaveImage(string path) { bitmapImage.Save(path); } 

让我们从清理代码开始吧。 以下模式:

 R = ((pixelColor.R + (offset / 2)) - ((pixelColor.R + (offset / 2)) % offset) - 1); if (R < 0) { R = 0; } 

相当于:

 R = Math.Max(0, (pixelColor.R + offset / 2) / offset * offset - 1); 

因此,您可以简化您的function:

 public void ApplyDecreaseColourDepth(int offset) { for (int y = 0; y < bitmapImage.Height; y++) { for (int x = 0; x < bitmapImage.Width; x++) { int pixelColor = bitmapImage.GetPixel(x, y); int A = pixel.A; int R = Math.Max(0, (pixelColor.R + offset / 2) / offset * offset - 1); int G = Math.Max(0, (pixelColor.G + offset / 2) / offset * offset - 1); int B = Math.Max(0, (pixelColor.B + offset / 2) / offset * offset - 1); bitmapImage.SetPixel(x, y, Color.FromArgb(A, R, G, B)); } } } 

回答你的问题:

  1. 正确; 偏移量是步长函数中步长的大小。 每个颜色分量的深度是原始深度减去log 2 (偏移量)。 例如,如果原始图像的每个分量(bpc)的深度为8位,偏移量为16,则每个分量的深度为8 - log 2 (16)= 8 - 4 = 4 bpc。 但请注意,这仅表示每个输出组件可以容纳多少熵,而不是每个组件实际用于存储结果的位数。
  2. 输出文件的大小取决于存储的颜色深度和使用的压缩。 简单地减少每个组件可以具有的不同值的数量不会自动导致每个组件使用更少的位,因此除非您明确选择每个组件使用较少位的编码,否则未压缩的图像不会收缩。 如果要保存压缩格式(如PNG),您可能会看到转换后的图像有所改进,或者您可能没有; 这取决于图像的内容。 具有许多平坦无纹理区域的图像(例如线条图画)将看到可忽略不计的改进,而照片可能会从变换中显着受益(尽管以感知质量为代价)。

您只是将像素值设置为较低级别。

例如,如果一个像素由3个通道表示,每个通道16位,则将每个像素颜色值减少到每通道8位。 这将永远不会减小图像大小,因为分配的像素已经具有16位的固定深度。 尝试将新值保存到最大为8位深度的新图像。
当然,您将以字节为单位缩小图像,但不会影响整体尺寸,即图像的X,Y尺寸将保持不变。 你在做什么会降低图像质量。

首先我想问你一个简单的问题:)

int i = 10;

现在i = i–;

把它影响到我的大小? ans是不是

你正在做同样的事情

成像的索引在两个矩阵1中表示用于颜色映射和2用于图像映射

你只需更改元素的值而不删除它,这样就不会影响图像的大小

使用Get / SetPixel无法降低颜色深度。 这些方法只改变颜色。

看起来你不能轻易地将图像保存为某种像素格式,但我确实找到了一些代码来改变内存中的像素格式。 您可以尝试保存它,它可能会起作用,具体取决于您保存的格式。

从这个问题: https : //stackoverflow.com/a/2379838/785745

他给出了这个代码来改变颜色深度:

 public static Bitmap ConvertTo16bpp(Image img) { var bmp = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb555); using (var gr = Graphics.FromImage(bmp)) { gr.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height)); } return bmp; } 

您可以将代码中的PixelFormat更改为您需要的任何内容。

某个像素计数的位图图像始终大小相同,因为位图格式不应用压缩。 如果使用算法(例如JPEG)压缩图像,则“缩小”图像应该更小。

 R = ((pixelColor.R + (offset / 2)) - ((pixelColor.R + (offset / 2)) 

这不总是返回0吗?

如果要减小图像的大小,可以在调用Image.Save()时指定不同的压缩格式。

GIF文件格式可能是一个很好的选择,因为它最适用于相同颜色的连续像素(当颜色深度较低时会更频繁地发生)。

JPEG可以很好地处理照片,但是如果将24位图像转换为16位图像然后使用JPEG对其进行压缩,则不会看到明显的结果,因为算法的工作方式(最好是保存24位图片直接为JPEG)。

正如其他人所解释的那样,除非您实际将结果数据复制到另一个具有不同PixelFormat的 Bitmap对象(如Format16bppRgb555否则您的代码不会减小Image对象使用的大小。