/// <summary> /// 根据图片生成图片的ASCII 十六进制 /// </summary> /// <param name="sourceBmp">原始图片</param> /// <param name="totalBytes">总共字节数</param> /// <param name="rowBytes">每行的字节数</param> /// <returns>ASCII 十六进制</returns> public static string BitmapToHex(Image sourceBmp, out int totalBytes, out int rowBytes) { // 转成单色图 Bitmap grayBmp = ConvertToGrayscale(sourceBmp as Bitmap); // 锁定位图数据 Rectangle rect = new Rectangle(0, 0, grayBmp.Width, grayBmp.Height); System.Drawing.Imaging.BitmapData bmpData = grayBmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, grayBmp.PixelFormat); // 获取位图数据第一行的起始地址 IntPtr ptr = bmpData.Scan0; // 定义数组以存放位图的字节流数据 // 处理像素宽对应的字节数,如不为8的倍数,则对最后一个字节补0 int width = (int)Math.Ceiling(grayBmp.Width / 8.0); // 获取位图实际的字节宽,这个值因为要考虑4的倍数关系,可能大于width int stride = Math.Abs(bmpData.Stride); // 计算位图数据实际所占的字节数,并定义数组 int bitmapDataLength = stride * grayBmp.Height; byte[] ImgData = new byte[bitmapDataLength]; // 从位图文件复制图像数据到数组,从实际图像数据的第一行开始;因ptr指针而无需再考虑行倒序存储的处理 System.Runtime.InteropServices.Marshal.Copy(ptr, ImgData, 0, bitmapDataLength); // 计算异或操作数,以处理包含图像数据但又有补0操作的那个字节 byte mask = 0xFF; // 计算这个字节补0的个数 //int offset = 8 * width - grayBmp.Width; int offset = 8 - (grayBmp.Width % 8); //offset %= 8; offset = offset % 8; // 按补0个数对0xFF做相应位数的左移位操作 mask <<= (byte)offset; // 图像反色处理 for (int j = 0; j < grayBmp.Height; j++) { for (int i = 0; i < stride; i++) { if (i < width - 1) //无补0的图像数据 { ImgData[j * stride + i] ^= 0xFF; } else if (i == width - 1) //有像素的最后一个字节,可能有补0 { ImgData[j * stride + i] ^= mask; } else //为满足行字节宽为4的倍数而最后补的字节 { //ImgData[j * stride + i] = 0x00; ImgData[j * stride + i] ^= 0x00; } } } // 将位图数据转换为16进制的ASCII字符 string zplString = BitConverter.ToString(ImgData); zplString = CompressLZ77(zplString.Replace("-", string.Empty)); totalBytes = bitmapDataLength; rowBytes = stride; return zplString; }
时间: 2024-12-21 21:19:56