private static Bitmap ProcessImagePixels(Image sourceImage, QuantizedPalette palette) { var result = new Bitmap(sourceImage.Width, sourceImage.Height, PixelFormat.Format8bppIndexed); var newPalette = result.Palette; for (var index = 0; index < palette.Colors.Count; index++) { newPalette.Entries[index] = palette.Colors[index]; } result.Palette = newPalette; BitmapData targetData = null; try { targetData = result.LockBits(Rectangle.FromLTRB(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, result.PixelFormat); const byte targetBitDepth = 8; var targetByteLength = targetData.Stride < 0 ? -targetData.Stride : targetData.Stride; var targetByteCount = Math.Max(1, targetBitDepth >> 3); var targetSize = targetByteLength * result.Height; var targetOffset = 0; var targetBuffer = new byte[targetSize]; var targetValue = new byte[targetByteCount]; var pixelIndex = 0; for (var y = 0; y < result.Height; y++) { var targetIndex = 0; for (var x = 0; x < result.Width; x++) { var targetIndexOffset = targetIndex >> 3; targetValue[0] = (byte)(palette.PixelIndex[pixelIndex] == -1 ? palette.Colors.Count - 1 : palette.PixelIndex[pixelIndex]); pixelIndex++; for (var valueIndex = 0; valueIndex < targetByteCount; valueIndex++) { targetBuffer[targetOffset + valueIndex + targetIndexOffset] = targetValue[valueIndex]; } targetIndex += targetBitDepth; } targetOffset += targetByteLength; } Marshal.Copy(targetBuffer, 0, targetData.Scan0, targetSize); } finally { if (targetData != null) { result.UnlockBits(targetData); } } return(result); }
public Image QuantizeImage(Bitmap image, int alphaThreshold, int alphaFader) { var colorCount = MaxColor; var data = BuildHistogram(image, alphaThreshold, alphaFader); data = CalculateMoments(data); var cubes = SplitData(ref colorCount, data); Palette = GetQuantizedPalette(colorCount, data, cubes, alphaThreshold); return ProcessImagePixels(image, Palette); }
public Image QuantizeImage(Bitmap image, int alphaThreshold, int alphaFader) { var colorCount = MaxColor; var data = BuildHistogram(image, alphaThreshold, alphaFader); data = CalculateMoments(data); var cubes = SplitData(ref colorCount, data); Palette = GetQuantizedPalette(colorCount, data, cubes, alphaThreshold); return(ProcessImagePixels(image, Palette)); }
public Image QuantizeImage(Bitmap image) { var colorCount = MaxColor; var data = BuildHistogram(image); data = CalculateMoments(data); var cubes = SplitData(ref colorCount, data); palette = GetQuantizedPalette(colorCount, data, cubes); //var palette = GetQuantizedPalette(colorCount, data, cubes); return(ProcessImagePixels(image, palette)); }
private static Bitmap ProcessImagePixels(Image sourceImage, QuantizedPalette palette) { var result = new Bitmap(sourceImage.Width, sourceImage.Height, PixelFormat.Format8bppIndexed); var newPalette = result.Palette; for (var index = 0; index < palette.Colors.Count; index++) newPalette.Entries[index] = palette.Colors[index]; result.Palette = newPalette; BitmapData targetData = null; try { targetData = result.LockBits(Rectangle.FromLTRB(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, result.PixelFormat); const byte targetBitDepth = 8; var targetByteLength = targetData.Stride < 0 ? -targetData.Stride : targetData.Stride; var targetByteCount = Math.Max(1, targetBitDepth >> 3); var targetSize = targetByteLength * result.Height; var targetOffset = 0; var targetBuffer = new byte[targetSize]; var targetValue = new byte[targetByteCount]; var pixelIndex = 0; for (var y = 0; y < result.Height; y++) { var targetIndex = 0; for (var x = 0; x < result.Width; x++) { var targetIndexOffset = targetIndex >> 3; targetValue[0] = (byte)(palette.PixelIndex[pixelIndex] == -1 ? palette.Colors.Count - 1 : palette.PixelIndex[pixelIndex]); pixelIndex++; for (var valueIndex = 0; valueIndex < targetByteCount; valueIndex++) targetBuffer[targetOffset + valueIndex + targetIndexOffset] = targetValue[valueIndex]; targetIndex += targetBitDepth; } targetOffset += targetByteLength; } Marshal.Copy(targetBuffer, 0, targetData.Scan0, targetSize); } finally { if(targetData != null) result.UnlockBits(targetData); } return result; }
protected override QuantizedPalette GetQuantizedPalette(int colorCount, ColorData data, IEnumerable <Box> cubes, int alphaThreshold) { 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, int> cachedMaches = new Dictionary <int, int>(); for (int pixelIndex = 0; pixelIndex < pixelsCount; pixelIndex++) { Pixel pixel = pixels[pixelIndex]; palette.PixelIndex[pixelIndex] = -1; if (pixel.Alpha <= alphaThreshold) { continue; } int bestMatch; int argb = pixel.Argb; if (!cachedMaches.TryGetValue(argb, out bestMatch)) { int match = quantizedPixels[pixelIndex]; bestMatch = 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; int distance = deltaAlpha * deltaAlpha + deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue; if (distance >= bestDistance) { continue; } bestDistance = distance; bestMatch = lookupIndex; } cachedMaches[argb] = bestMatch; } alphas[bestMatch] += pixel.Alpha; reds[bestMatch] += pixel.Red; greens[bestMatch] += pixel.Green; blues[bestMatch] += pixel.Blue; sums[bestMatch]++; palette.PixelIndex[pixelIndex] = bestMatch; } 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); }
private static QuantizedPalette GetQuantizedPalette(int colorCount, ColorData data, IEnumerable <Box> cubes) { var imageSize = data.Pixels.Count; var lookups = BuildLookups(cubes, data); for (var index = 0; index < imageSize; ++index) { var indexParts = BitConverter.GetBytes(data.QuantizedPixels[index]); data.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); var index2 = -1; foreach (var pixel in data.Pixels) { palette.PixelIndex[++index2] = -1; if (pixel.Alpha <= AlphaThreshold) { continue; } var match = data.QuantizedPixels[index2]; var bestMatch = match; var bestDistance = 100000000; var index = -1; foreach (var lookup in lookups.Lookups) { ++index; var deltaAlpha = pixel.Alpha - lookup.Alpha; var deltaRed = pixel.Red - lookup.Red; var deltaGreen = pixel.Green - lookup.Green; var deltaBlue = pixel.Blue - lookup.Blue; var distance = deltaAlpha * deltaAlpha + deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue; if (distance >= bestDistance) { continue; } bestDistance = distance; bestMatch = index; } alphas[bestMatch] += pixel.Alpha; reds[bestMatch] += pixel.Red; greens[bestMatch] += pixel.Green; blues[bestMatch] += pixel.Blue; sums[bestMatch]++; palette.PixelIndex[index2] = bestMatch; } 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); }
private void button_ReadImage_Click(object sender, EventArgs e) { 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; 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)) { QuantizedPalette palette = quantizer.palette; //quantized.Save(targetPath, ImageFormat.Png); inputimage = new Bitmap(quantized); scale_width = Convert.ToDouble(bmDraw.Width) / inputimage.Width; scale_height = Convert.ToDouble(bmDraw.Height) / inputimage.Height; scale = scale_width; if (scale_width > scale_height) { scale = scale_height; } centerx = bmDraw.Width / 2; centery = bmDraw.Height / 2; newWidth = Convert.ToInt32(inputimage.Width * scale / 2); newHeight = Convert.ToInt32(inputimage.Height * scale / 2); rg = new Rectangle(centerx - newWidth, centery - newHeight, newWidth * 2, newHeight * 2); //将bm内rg所指定的区域绘制到bm1 g.DrawImage(inputimage, rg); this.pictureBox_Image.Image = bmDraw; } } } // } } } }
protected override QuantizedPalette GetQuantizedPalette(int colorCount, ColorData data, IEnumerable<Box> cubes, int alphaThreshold) { 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, int> cachedMaches = new Dictionary<int, int>(); for (int pixelIndex = 0; pixelIndex < pixelsCount; pixelIndex++) { Pixel pixel = pixels[pixelIndex]; palette.PixelIndex[pixelIndex] = -1; if (pixel.Alpha <= alphaThreshold) continue; int bestMatch; int argb = pixel.Argb; if (!cachedMaches.TryGetValue(argb, out bestMatch)) { int match = quantizedPixels[pixelIndex]; bestMatch = 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; int distance = deltaAlpha*deltaAlpha + deltaRed*deltaRed + deltaGreen*deltaGreen + deltaBlue*deltaBlue; if (distance >= bestDistance) continue; bestDistance = distance; bestMatch = lookupIndex; } cachedMaches[argb] = bestMatch; } alphas[bestMatch] += pixel.Alpha; reds[bestMatch] += pixel.Red; greens[bestMatch] += pixel.Green; blues[bestMatch] += pixel.Blue; sums[bestMatch]++; palette.PixelIndex[pixelIndex] = bestMatch; } 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; }
private static QuantizedPalette GetQuantizedPalette(int colorCount, ColorData data, IEnumerable<Box> cubes) { var imageSize = data.Pixels.Count; var lookups = BuildLookups(cubes, data); for(var index = 0; index < imageSize; ++index) { var indexParts = BitConverter.GetBytes(data.QuantizedPixels[index]); data.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); var index2 = -1; foreach (var pixel in data.Pixels) { palette.PixelIndex[++index2] = -1; if(pixel.Alpha <= AlphaThreshold) continue; var match = data.QuantizedPixels[index2]; var bestMatch = match; var bestDistance = 100000000; var index = -1; foreach (var lookup in lookups.Lookups) { ++index; var deltaAlpha = pixel.Alpha - lookup.Alpha; var deltaRed = pixel.Red - lookup.Red; var deltaGreen = pixel.Green - lookup.Green; var deltaBlue = pixel.Blue - lookup.Blue; var distance = deltaAlpha * deltaAlpha + deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue; if (distance >= bestDistance) continue; bestDistance = distance; bestMatch = index; } alphas[bestMatch] += pixel.Alpha; reds[bestMatch] += pixel.Red; greens[bestMatch] += pixel.Green; blues[bestMatch] += pixel.Blue; sums[bestMatch]++; palette.PixelIndex[index2] = bestMatch; } 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; }