C#代码:
... m_SrcImage = new Bitmap(imagePath); Rectangle r = new Rectangle(0,m_SrcImage.Width,m_SrcImage.Height); BitmapData bd = m_SrcImage.LockBits(r,ImageLockMode.ReadWrite,PixelFormat.Format32bppArgb); //Load Colors int[] colours = new int[m_SrcImage.Width * m_SrcImage.Height]; Marshal.copy(bd.Scan0,colours,colours.Length); m_SrcImage.UnlockBits(bd); int len = colours.Length; List<Color> result = new List<Color>(len); for (int i = 0; i < len; ++i) { uint w = ((uint)colours[i]) & 0x00FFFFFF; //Delete alpha-channel if (w != 0x00000000 && w != 0x00FFFFFF) //Check pixel is not black or white { w |= 0xFF000000; //Return alpha channel result.Add(Color.FromArgb((int)w)); } } ...
之后,我尝试通过此代码在List中find独特的颜色
result.sort((a,b) => { return aR != bR ? aR - bR : aG != bG ? aG - bG : aB != bB ? aB - bB : 0; }); List<Color> uniqueColors = new List<Color>( result.Count); Color rgbTemp = result[0]; for (int i = 0; i < len; ++i) { if (rgbTemp == result[i]) { continue; } uniqueColors.Add(rgbTemp); rgbTemp = result[i]; } uniqueColors.Add(rgbTemp);
这段代码在同一图像上的不同机器上产生不同的结果!
.NET Core / Full CLR应用程序的独立debugging
如何设置客户端时区等于服务器时区窗口应用程序.Net C#
由于SecurityException而无法读取事件日志
我有什么select使用C#在Windows Server上添加和删除IPSec策略?
例如,在这个图像上它产生:
XP SP3与.NET版本4 43198独特的颜色
.Win7 Ultimate上的43168独特颜色.NEt版本4.5
最小testing项目可以在这里下载 。 它只是打开选定的图像,并产生独特的颜色txt文件。
还有一个事实。 一些像素在不同的机器上读取的方式不同 我用记事本+ +比较txt文件,它显示一些像素有不同的RGB组件。 每个组件的差别是1,例如
Win7像素:255 200 100
WinXP像素:254 199 99
我读过这篇文章
stackoverflow.com/questions/2419598/why-might-different-computers-calculate-different-arithmetic-results-in-vb-net
(对不起,我没有足够的正常链接)。
…但没有信息如何解决它。
项目是在VS 2015 Commumity Edition中使用操作系统Windows 7的机器上为.NET 4 Client Profile进行编译的。
重新启动一个应用程序本身
关于.NET的2个基本但有趣的问题
“这个文件来自另一台计算机,可能被阻止,以保护这台计算机。” – 如何以编程方式在C#.net中删除此属性?
SetSystemTime kernel32中的奇怪行为
维基百科有这样的说明JPEG解码器的准确性要求 :
JPEG标准中的编码描述不能确定输出压缩图像所需的精度 。 然而,JPEG标准(以及类似的MPEG标准)包括解码的一些精度要求,包括解码过程的所有部分(可变长度解码,逆DCT,反量化,输出的重整化); 参考算法的输出不得超过:
每个像素分量的最大差值为一位
每个8×8像素块的均方误差较小
每个8×8像素块的平均误差非常低
整个图像的均方误差非常低
整个图像的平均误差极低
(我的重点)
简而言之,在这里播放的只有两种不同的解码器实现,并且在精确度要求(1比特=分量值的+/- 1,如您所观察的)内产生不同的图像。
因此,使用相同的(非内置的)JPEG解码器,这是可以预料的。 如果您需要具有完全相同的输出,那么您可能需要切换到不同的解码器,无论您使用的是哪个.NET版本或Windows,都将是相同的解码器。 我猜GDI +是这里的罪魁祸首,自从Windows XP以来,它经历了更大的变化。
我解决了我的问题,通过添加Libjpeg.NET项目和编写此代码:
private Bitmap JpegToBitmap(JpegImage jpeg) { int width = jpeg.Width; int height = jpeg.Height; // Read the image into the memory buffer int[] raster = new int[height * width]; for(int i = 0; i < height; ++i) { byte[] temp = jpeg.GetRow(i).ToBytes(); for (int j = 0; j < temp.Length; j += 3) { int offset = i*width + j / 3; raster[offset] = 0; raster[offset] |= (((int)temp[j+2]) << 16); raster[offset] |= (((int)temp[j+1]) << 8); raster[offset] |= (int)temp[j]; } } Bitmap bmp = new Bitmap(width,height,PixelFormat.Format24bppRgb); Rectangle rect = new Rectangle(0,bmp.Width,bmp.Height); BitmapData bmpdata = bmp.LockBits(rect,PixelFormat.Format24bppRgb); byte[] bits = new byte[bmpdata.Stride * bmpdata.Height]; for (int y = 0; y < bmp.Height; y++) { int rasterOffset = y * bmp.Width; int bitsOffset = (bmp.Height - y - 1) * bmpdata.Stride; for (int x = 0; x < bmp.Width; x++) { int rgba = raster[rasterOffset++]; bits[bitsOffset++] = (byte)((rgba >> 16) & 0xff); bits[bitsOffset++] = (byte)((rgba >> 8) & 0xff); bits[bitsOffset++] = (byte)(rgba & 0xff); } } System.Runtime.InteropServices.Marshal.copy(bits,bmpdata.Scan0,bits.Length); bmp.UnlockBits(bmpdata); return bmp; }
所以,这对我来说就够了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。