private unsafe byte[] BitmapToRawIndexed(Bitmap source, int maxColors, out byte[][] palette) { Bitmap img = source; byte[] destination = new byte[img.Width * img.Height]; // If this is not a 32-bit ARGB bitmap, convert it to one if (img.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppArgb) { Bitmap newImage = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(newImage)) { g.DrawImage(img, 0, 0, img.Width, img.Height); } img = newImage; } // Quantize the image WuQuantizer quantizer = new WuQuantizer(); m_palette = quantizer.CreatePalette(img, maxColors); img = (Bitmap)quantizer.QuantizeImage(img, m_palette); // Copy over the data to the destination. We need to use Stride in this case, as it may not // always be equal to Width. BitmapData bitmapData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadOnly, img.PixelFormat); byte *pointer = (byte *)bitmapData.Scan0; for (int y = 0; y < bitmapData.Height; y++) { for (int x = 0; x < bitmapData.Width; x++) { destination[(y * img.Width) + x] = pointer[(y * bitmapData.Stride) + x]; } } img.UnlockBits(bitmapData); // Copy over the palette palette = new byte[maxColors][]; for (int i = 0; i < maxColors; i++) { palette[i] = new byte[4]; palette[i][3] = img.Palette.Entries[i].A; palette[i][2] = img.Palette.Entries[i].R; palette[i][1] = img.Palette.Entries[i].G; palette[i][0] = img.Palette.Entries[i].B; } return(destination); }
public RSImage(string filename, out Exception ex) { try { Bitmap bmp = new Bitmap(filename, true); if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppArgb) { bmp.MakeTransparent(Color.Transparent); //force bmp to be 32-bit } WuQuantizer q = new WuQuantizer(); bmp = new Bitmap(q.QuantizeImage(bmp)); QuantizedPalette p = q.Palette; Palette = new Color[p.Colors.Count]; for (int i = 0; i < p.Colors.Count; i++) { Palette[i] = p.Colors[i]; } Pixels = new Color[bmp.Width * bmp.Height]; for (int i = 0; i < bmp.Width * bmp.Height; i++) { Pixels[i] = bmp.GetPixel(i % bmp.Width, i / bmp.Width); } WholeWidth = Width = bmp.Width; WholeHeight = Height = bmp.Height; XOffset = 0; YOffset = 0; ex = null; } catch (Exception e) { ex = e; Pixels = null; } }
protected unsafe byte[] BitmapToRawIndexedResized(Bitmap source, int size, int minSize, QuantizedPalette palette) { if (size > minSize) { minSize = size; } byte[] destination = new byte[minSize * minSize * 4]; // Resize the image Bitmap img = new Bitmap(minSize, minSize, System.Drawing.Imaging.PixelFormat.Format32bppArgb); using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(img)) { using (ImageAttributes attr = new ImageAttributes()) { attr.SetWrapMode(WrapMode.TileFlipXY); g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.DrawImage(source, new Rectangle(0, 0, size, size), 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, attr); } } // Quantize the image WQuantizer.WuQuantizer quantizer = new WQuantizer.WuQuantizer(); img = (Bitmap)quantizer.QuantizeImage(img, palette); // Copy over the data to the destination. We need to use Stride in this case, as it may not // always be equal to Width. BitmapData bitmapData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadOnly, img.PixelFormat); byte *pointer = (byte *)bitmapData.Scan0; for (int y = 0; y < bitmapData.Height; y++) { for (int x = 0; x < bitmapData.Width; x++) { destination[(y * img.Width) + x] = pointer[(y * bitmapData.Stride) + x]; } } img.UnlockBits(bitmapData); return(destination); }
private void button_ReadImage_Click(object sender, EventArgs e) { dataGridView_Color.Rows.Clear(); button_ColorOutput.Enabled = false; button_ColorPalette.Enabled = false; OpenFileDialog dlg = new OpenFileDialog(); //创建事例 string dir = Environment.GetFolderPath(Environment.SpecialFolder.Templates); //指定初始目录 dlg.InitialDirectory = dir; //指定初始目录 dlg.Title = "图表对话框"; dlg.ShowReadOnly = true; //以只读方式打开 dlg.ShowHelp = true; //显示帮助按钮 /////// dlg.Filter = "图表.jpg|*.jpg|图表.tif|*.tif|图表.bmp|*.bmp|所有文件|*.*"; //文件过滤器,指定打开文件类型 //dlg.ShowDialog();//打开对话框 //BMP 文件(*.bmp) | *.bmp | JPEG 文件(*.jpg, *.jpeg) | *.jpg, *.jpeg | PNG 文件(*.png) | *.png | GIF 文件(*.gif) | *.gif | TIFF 文件(*.tiff, *.tif) | *.tiff //MessageBox.Show(dlg.Title);//打开消息 //dlg.Multiselect = true;//是否允许一次打开多个文件 dlg.Multiselect = false; //是否允许一次打开多个文件 // if (dlg.ShowDialog() == DialogResult.OK) //{ if (dlg.CheckPathExists) //检查路径是否存在 { if (dlg.CheckFileExists) //检查文件是否存在 { // if (dlg.ValidateNames)//检查是否有效Win32文件名 // { if (dlg.ShowDialog() == DialogResult.OK) { string s = dlg.FileNames[0]; // foreach (string s in dlg.FileNames) //{ //string fileName = dlg.FileName; //MessageBox.Show("打开文件:" + s);//打开消息对话框 bmDraw = new Bitmap(this.pictureBox_Image.Width, this.pictureBox_Image.Height); Bitmap inputimage = (Bitmap)Image.FromFile(s); System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmDraw); double scale_width = Convert.ToDouble(bmDraw.Width) / inputimage.Width; double scale_height = Convert.ToDouble(bmDraw.Height) / inputimage.Height; double scale = scale_width; if (scale_width > scale_height) { scale = scale_height; } int centerx = bmDraw.Width / 2; int centery = bmDraw.Height / 2; int newWidth = Convert.ToInt32(inputimage.Width * scale / 2); int newHeight = Convert.ToInt32(inputimage.Height * scale / 2); Rectangle rg = new Rectangle(centerx - newWidth, centery - newHeight, newWidth * 2, newHeight * 2); //将bm内rg所指定的区域绘制到bm1 g.DrawImage(inputimage, rg); this.pictureBox_Image.Image = bmDraw; //Step 1: Convert the Image to Use an 8-bit Palette var sourcePath = s; if (!File.Exists(sourcePath)) { Console.WriteLine("The source file you specified does not exist."); Environment.Exit(1); } var lastDot = sourcePath.LastIndexOf('.'); var targetPath = sourcePath.Insert(lastDot, "-quant"); //if(args.Length > 1) // targetPath = args[1]; var quantizer = new WuQuantizer(); // QuantizedPalette ColorPalette = new QuantizedPalette(); var bitmap0 = new Bitmap(sourcePath); Bitmap bitmap1 = ConvertTo32bpp(bitmap0); using (var bitmap = bitmap1) //using (var bitmap = new Bitmap(sourcePath)) { using (var quantized = quantizer.QuantizeImage(bitmap)) Orignialimage = new Bitmap(quantized); palette = quantizer.palette; //quantized.Save(targetPath, ImageFormat.Png); button_ColorPalette.Enabled = true; } } } // } } }
protected override QuantizedPalette GetQuantizedPalette(int colorCount, ColorData data, IEnumerable <Box> cubes, int alphaThreshold) { if (_targetColorCount > 0) { colorCount = _targetColorCount; } int imageSize = data.PixelsCount; LookupData lookups = BuildLookups(cubes, data); IList <int> quantizedPixels = data.QuantizedPixels; for (var index = 0; index < imageSize; ++index) { var indexParts = BitConverter.GetBytes(quantizedPixels[index]); quantizedPixels[index] = lookups.Tags[indexParts[Alpha], indexParts[Red], indexParts[Green], indexParts[Blue]]; } var alphas = new int[colorCount + 1]; var reds = new int[colorCount + 1]; var greens = new int[colorCount + 1]; var blues = new int[colorCount + 1]; var sums = new int[colorCount + 1]; var palette = new QuantizedPalette(imageSize); IList <Pixel> pixels = data.Pixels; int pixelsCount = data.PixelsCount; IList <Lookup> lookupsList = lookups.Lookups; int lookupsCount = lookupsList.Count; Dictionary <int, MappedError> cachedMatches = new Dictionary <int, MappedError>(); for (int pixelIndex = 0; pixelIndex < pixelsCount; pixelIndex++) { Pixel pixel = pixels[pixelIndex]; palette.PixelIndex[pixelIndex] = -1; if (pixel.Alpha <= alphaThreshold) { continue; } var x = pixelIndex % _width; var y = (pixelIndex - x) / _width; if (pixel.Alpha > 1 && _ditherAmount > 0) { // Get bayer dithering. var ov = _adjustedPattern[x % 8 + y % 8 * 8] * _ditherAmount; // Check for semi transparent areas if (pixel.Alpha < _ditherThreshold) { ov *= 1.5; // Apply dithering with a magnitude of 2 to the alpha pixel = new Pixel(Fit(pixel.Alpha + ov), pixel.Red, pixel.Green, pixel.Blue); } else { var l = (pixel.Red * _luminance_r + pixel.Blue * _luminance_b + pixel.Green * _luminance_g) * _byteInverted; if (l > 0.05 && l < 0.95) { if (_debug) { // Draw fuchsia on solid dither area pixel = new Pixel(255, 255, 0, 128); } else { // Apply dithering to the color layer pixel = new Pixel(pixel.Alpha, Fit(pixel.Red + ov), Fit(pixel.Green + ov), Fit(pixel.Blue + ov)); } } } } MappedError bestMatch; int argb = pixel.Argb; if (!cachedMatches.TryGetValue(argb, out bestMatch)) { int match = quantizedPixels[pixelIndex]; bestMatch = new MappedError { Index = match }; int bestDistance = int.MaxValue; for (int lookupIndex = 0; lookupIndex < lookupsCount; lookupIndex++) { Lookup lookup = lookupsList[lookupIndex]; var deltaAlpha = pixel.Alpha - lookup.Alpha; var deltaRed = pixel.Red - lookup.Red; var deltaGreen = pixel.Green - lookup.Green; var deltaBlue = pixel.Blue - lookup.Blue; // Take luminance into account when calculating color distance (green is always the most percievable, blue is the least). var distance = (int) ((double)deltaAlpha * deltaAlpha * _luminance_a + (double)deltaRed * deltaRed * _luminance_r + (double)deltaGreen * deltaGreen * _luminance_g + (double)deltaBlue * deltaBlue * _luminance_b); if (distance >= bestDistance) { continue; } bestDistance = distance; bestMatch.AlphaError = deltaAlpha; bestMatch.Index = lookupIndex; } cachedMatches[argb] = bestMatch; } alphas[bestMatch.Index] += pixel.Alpha; reds[bestMatch.Index] += pixel.Red; greens[bestMatch.Index] += pixel.Green; blues[bestMatch.Index] += pixel.Blue; sums[bestMatch.Index]++; palette.PixelIndex[pixelIndex] = bestMatch.Index; } for (var paletteIndex = 0; paletteIndex < colorCount; paletteIndex++) { if (sums[paletteIndex] > 0) { alphas[paletteIndex] /= sums[paletteIndex]; reds[paletteIndex] /= sums[paletteIndex]; greens[paletteIndex] /= sums[paletteIndex]; blues[paletteIndex] /= sums[paletteIndex]; } var color = Color.FromArgb(alphas[paletteIndex], reds[paletteIndex], greens[paletteIndex], blues[paletteIndex]); palette.Colors.Add(color); } palette.Colors.Add(Color.FromArgb(0, 0, 0, 0)); return(palette); }