public static PNM Copy(PNM image) { PNM newImage = new PNM(image.Width, image.Height); Buffer.BlockCopy(image.raster, 0, newImage.raster, 0, image.raster.Length); return(newImage); }
internal static void Pad(PNM image, int padding) { image.raster = PadWithZeros(image.raster, image.Width * 3, image.Height, padding * 3, padding); image.Width += 2 * padding; image.Height += 2 * padding; PadCorners(image, padding); PadBorders(image, padding); }
public static PNM ApplyPixelFunction(this PNM image, int matrixLength, Func <PNM, int, Pixel> func) { PNM newImage = PNM.Copy(image); int padding = matrixLength / 2; Pad(newImage, padding); newImage = ApplyConvolutionFunctionCore(newImage, matrixLength, func); Trim(newImage, padding); return(newImage); }
internal void ReplaceImage(string path) { Stream stream = File.Open(path, FileMode.Open); Tuple <PNM, PNMFormat> payload = PNM.LoadFileWithFormat(stream); Image = payload.Item1; Format = payload.Item2; undoList.Clear(); Path = path; }
internal static void SaveFile(PNM bitmap, FileStream stream) { bitmap.WriteLongHeader("P5", stream); for (int i = 0; i < bitmap.Height * bitmap.Width; i++) { byte r, g, b; bitmap.GetPixel(i, out r, out g, out b); byte pixel = RGBToLuminosity(r, g, b); stream.WriteByte(pixel); } }
internal static void SaveFile(PNM bitmap, FileStream stream) { bitmap.WriteShortHeader("P4", stream); for (int i = 0; i < bitmap.Height; i++) { for (int j = 0; j < bitmap.Width; j += 8) { stream.WriteByte(PackBytes(bitmap, i * bitmap.Width + j, UnpackedBits(j, bitmap.Width))); } } }
internal static void SaveFile(PNM bitmap, FileStream stream) { bitmap.WriteShortHeader("P4", stream); for (int i = 0; i < bitmap.Height; i++) { for (int j = 0; j < bitmap.Width; j += 8) { stream.WriteByte(PackBytes(bitmap, i * bitmap.Width + j,UnpackedBits(j, bitmap.Width))); } } }
internal static void SaveFile(PNM bitmap, FileStream stream) { bitmap.WriteLongHeader("P5", stream); for (int i = 0; i < bitmap.Height * bitmap.Width; i++) { byte r,g,b; bitmap.GetPixel(i, out r, out g, out b); byte pixel = RGBToLuminosity(r, g, b); stream.WriteByte(pixel); } }
internal static byte PackBytes(PNM bitmap, int start, int amount) { int result = 0; byte r,g,b; for(int i = 0; i< amount; i++) { bitmap.GetPixel(start + i, out r,out g,out b); if (ColorToBlack(r, g, b)) result |= (128 >> i); } return (byte)result; }
internal static void SaveFile(PNM bitmap, FileStream stream) { bitmap.WriteLongHeader("P6", stream); for (int i = 0; i < bitmap.Height * bitmap.Width; i++) { byte r, g, b; bitmap.GetPixel(i, out r, out g, out b); stream.WriteByte(r); stream.WriteByte(g); stream.WriteByte(b); } }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { PNM pnm = value as PNM; if (pnm == null) { return(null); } var bitmap = new WriteableBitmap(pnm.Width, pnm.Height, 96, 96, PixelFormats.Cmyk32, null); bitmap.WritePixels(new Int32Rect(0, 0, pnm.Width, pnm.Height), pnm.GetCMYK(), pnm.Width * 4, 0); return(bitmap); }
public static PNM ApplyPointProcessing(this PNM oldImage, Func <byte, byte, byte, Pixel> filter) { PNM newImage = new PNM(oldImage.Width, oldImage.Height); byte r, g, b; int size = oldImage.Width * oldImage.Height; for (int i = 0; i < size; i++) { oldImage.GetPixel(i, out r, out g, out b); Pixel pixel = filter(r, g, b); newImage.SetPixel(i, pixel.Red, pixel.Green, pixel.Blue); } ; return(newImage); }
internal static byte PackBytes(PNM bitmap, int start, int amount) { int result = 0; byte r, g, b; for (int i = 0; i < amount; i++) { bitmap.GetPixel(start + i, out r, out g, out b); if (ColorToBlack(r, g, b)) { result |= (128 >> i); } } return((byte)result); }
public static PNM ApplyConvolutionMatrix(this PNM image, float[] matrix, float weight, float shift) { int length = (int)Math.Sqrt(matrix.Length); if (Math.Pow(length, 2) != matrix.Length || (length / 2) * 2 == length) { throw new ArgumentException("matrix"); } PNM newImage = PNM.Copy(image); int padding = length / 2; Pad(newImage, padding); newImage = ApplyConvolutionMatrixCore(newImage, matrix, length, weight, shift); Trim(newImage, padding); return(newImage); }
// poor man's pixel shader private static PNM ApplyConvolutionFunctionCore(PNM image, int matrixLength, Func <PNM, int, Pixel> func) { PNM newImage = new PNM(image.Width, image.Height); int padding = matrixLength / 2; int maxHeight = newImage.Height - padding; int maxWidth = newImage.Width - padding; int width = newImage.Width; Parallel.For(padding, maxHeight, i => { for (int j = padding; j < maxWidth; j++) { // current index position int position = i * width + j; newImage.SetPixel(position, func(image, position)); } }); return(newImage); }
private static PNM ApplyHeightMapFunctionCore(int imgWidth, int imgHeight, float[] heightmap, int matrixLength, Func <int, int, float[], int, Pixel> func) { PNM newImage = new PNM(imgWidth, imgHeight); int padding = matrixLength / 2; int maxHeight = imgHeight - padding; int maxWidth = imgWidth - padding; int width = imgWidth; Parallel.For(padding, maxHeight, i => { for (int j = padding; j < maxWidth; j++) { // current index position int position = i * width + j; newImage.SetPixel(position, func(imgWidth, imgHeight, heightmap, position)); } }); return(newImage); }
public static void SaveFile(PNM bitmap, string path, PNMFormat format) { using (FileStream stream = File.Open(path, FileMode.Create, FileAccess.Write)) { switch (format) { case PNMFormat.PBM: RawPBM.SaveFile(bitmap, stream); break; case PNMFormat.PGM: RawPGM.SaveFile(bitmap, stream); break; case PNMFormat.PPM: RawPPM.SaveFile(bitmap, stream); break; default: throw new ArgumentException("format"); } } }
public static PNM ApplyHeightMapFunction(this PNM image, int matrixLength, Func <int, int, float[], int, Pixel> func) { PNM newImage = PNM.Copy(image); int padding = matrixLength / 2; Pad(newImage, padding); int newImageSize = newImage.Width * newImage.Height; float[] heightmap = new float[newImageSize]; byte r, g, b; for (int i = 0; i < newImageSize; i++) { newImage.GetPixel(i, out r, out g, out b); heightmap[i] = PNM.RGBToLuminosity(r, g, b) / 255f; } newImage = ApplyHeightMapFunctionCore(newImage.Width, newImage.Height, heightmap, matrixLength, func); Trim(newImage, padding); return(newImage); }
private static void PadCorners(PNM image, int padding) { byte r, g, b; // pad top left image.GetPixel(padding, padding, out r, out g, out b); for (int i = 0; i < padding; i++) { for (int j = 0; j < padding; j++) { image.SetPixel(i, j, r, g, b); } } // pad top right image.GetPixel(image.Width - padding - 1, padding, out r, out g, out b); for (int i = image.Width - padding; i < image.Width; i++) { for (int j = 0; j < padding; j++) { image.SetPixel(i, j, r, g, b); } } // pad bottom left image.GetPixel(padding, image.Height - padding - 1, out r, out g, out b); for (int i = 0; i < padding; i++) { for (int j = image.Height - padding; j < image.Height; j++) { image.SetPixel(i, j, r, g, b); } } // pad bottom right image.GetPixel(image.Width - padding - 1, image.Height - padding - 1, out r, out g, out b); for (int i = image.Width - padding; i < image.Width; i++) { for (int j = image.Height - padding; j < image.Height; j++) { image.SetPixel(i, j, r, g, b); } } }
internal static Tuple <float[], float[], float[]> ApplyConvolutionUnbound(PNM image, float[] matrix, int matrixLength) { int padding = matrixLength / 2; int oldHeight = image.Height - (padding * 2); int oldWidth = image.Width - (padding * 2); Tuple <float[], float[], float[]> rasters = Tuple.Create(new float[oldHeight * oldWidth], new float[oldHeight * oldWidth], new float[oldHeight * oldWidth]); int maxHeight = image.Height - padding; int maxWidth = image.Width - padding; Parallel.For(padding, maxHeight, i => { int index = (i - padding) * oldWidth; for (int j = padding; j < maxWidth; j++) { float sumR = 0; float sumG = 0; float sumB = 0; // current index position int position = i * image.Width + j; for (int m = 0; m < matrixLength; m++) { for (int n = 0; n < matrixLength; n++) { byte r, g, b; image.GetPixel(position - ((padding - m) * image.Width) - (padding - n), out r, out g, out b); float coeff = matrix[(m * matrixLength) + n]; sumR += r * coeff; sumG += g * coeff; sumB += b * coeff; } } rasters.Item1[index] = sumR; rasters.Item2[index] = sumG; rasters.Item3[index] = sumB; index++; } }); return(rasters); }
private static void MarkPixel(PNM image, int index) { int x = index % image.Width; int y = index / image.Width; for (int x0 = -1; x0 <= 1; x0++) { for (int y0 = -1; y0 <= 1; y0++) { if (x0 == 0 && y0 == 0) { continue; } int currentY = y + y0; int currentX = x + x0; if (currentX < 0 || currentX >= image.Width || currentY < 0 || currentY >= image.Height) { continue; } image.SetPixel(x + x0, y + y0, 0, 255, 0); } } }
//this should be rewritten to ApplyConvolutionFunction public static PNM ApplyGradientEdgesDetection(this PNM image) { PNM workImage = PNM.Copy(image); Pad(workImage, 1); Tuple <float[], float[], float[]> xraster = ApplyConvolutionUnbound(workImage, new float[] { -1, 0, 1, -1, 0, 1, -1, 0, 1 }, 3); Tuple <float[], float[], float[]> yraster = ApplyConvolutionUnbound(workImage, new float[] { 1, 1, 1, 0, 0, 0, -1, -1, -1 }, 3); PNM newImage = new PNM(image.Width, image.Height); int size = image.Width * image.Height; Parallel.For(0, size, i => { byte r = Coerce(Math.Sqrt(Math.Pow(xraster.Item1[i], 2) + Math.Pow(yraster.Item1[i], 2))); byte g = Coerce(Math.Sqrt(Math.Pow(xraster.Item2[i], 2) + Math.Pow(yraster.Item2[i], 2))); byte b = Coerce(Math.Sqrt(Math.Pow(xraster.Item3[i], 2) + Math.Pow(yraster.Item3[i], 2))); newImage.SetPixel(i, r, g, b); }); return(newImage); }
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { PNM pnm = values[0] as PNM; int? selection = values[1] as int?; Visibility?visibility = values[2] as Visibility?; if (pnm == null || selection == null || visibility != Visibility.Visible) { return(Binding.DoNothing); } double[] rawData; switch (selection) { case 0: rawData = pnm.GetHistogramLuminosity(); break; case 1: rawData = pnm.GetHistogramRed(); break; case 2: rawData = pnm.GetHistogramGreen(); break; case 3: rawData = pnm.GetHistogramBlue(); break; default: return(Binding.DoNothing); } return(BuildHistogramGeometry(rawData)); }
public void Undo() { image = undoList.Pop(); OnPropertyChanged("Image"); }
public static PNM Copy(PNM image) { PNM newImage = new PNM(image.Width, image.Height); Buffer.BlockCopy(image.raster, 0, newImage.raster, 0, image.raster.Length); return newImage; }
internal static void Trim(PNM image, int padding) { image.raster = Trim(image.raster, image.Width * 3, image.Height, padding * 3, padding); image.Width -= 2 * padding; image.Height -= 2 * padding; }
internal void SaveImage(string path, PNMFormat format) { PNM.SaveFile(Image, path, format); Path = path; Format = format; }
internal void SaveImage() { PNM.SaveFile(Image, Path, Format); Path = path; }
public static PNM ApplyHarrisDetector(this PNM image) { // gaussian window float[] gaussian = new float[] { 0, 0.01F, 0.02F, 0.01F, 0, 0.01F, 0.06F, 0.1F, 0.06F, 0.01F, 0.02F, 0.1F, 0.16F, 0.1F, 0.02F, 0.01F, 0.06F, 0.1F, 0.06F, 0.01F, 0, 0.01F, 0.02F, 0.01F, 0 }; // greyscale PNM workImage = PNM.Copy(image).ApplyPointProcessing(Color.ToGrayscale); Filter.Pad(workImage, 1); // integrate with prewitt double[] normalizedWorkImage = workImage.raster.Where((b, idx) => idx % 3 == 0).Select(b => b / 255d).ToArray(); double[] xraster = RunConvolution(normalizedWorkImage, workImage.Width, workImage.Height, Edges.SobelX, 3); double[] yraster = RunConvolution(normalizedWorkImage, workImage.Width, workImage.Height, Edges.SobelY, 3); double[] rasterA = new double[xraster.Length]; double[] rasterB = new double[xraster.Length]; double[] rasterC = new double[xraster.Length]; for (int i = 0; i < xraster.Length; i++) { rasterA[i] = Math.Pow(xraster[i], 2); rasterB[i] = Math.Pow(yraster[i], 2); rasterC[i] = xraster[i] * yraster[i]; } rasterA = Filter.PadWithZeros(rasterA, image.Width, image.Height, 2, 2); rasterB = Filter.PadWithZeros(rasterB, image.Width, image.Height, 2, 2); rasterC = Filter.PadWithZeros(rasterC, image.Width, image.Height, 2, 2); // calculate the matrices double[][] matrices = new double[image.Width * image.Height][]; int maxHeight = image.Height + 2; int maxWidth = image.Width + 2; int newWidth = image.Width + 4; int width = image.Width; for (int i = 2; i < maxHeight; i++) { //Parallel.For(2, maxHeight, (i) => //{ for (int j = 2; j < maxWidth; j++) { // apply convolution double accumulatorA = 0; double accumulatorB = 0; double accumulatorC = 0; int mi = 0; for (int x0 = -2; x0 <= 2; x0++) { for (int y0 = -2; y0 <= 2; y0++) { accumulatorA += gaussian[mi] * rasterA[(i + x0) * newWidth + j + y0]; accumulatorB += gaussian[mi] * rasterB[(i + x0) * newWidth + j + y0]; accumulatorC += gaussian[mi] * rasterC[(i + x0) * newWidth + j + y0]; mi++; } } int realPosition = (i - 2) * width + (j - 2); matrices[realPosition] = new double[] { accumulatorA, accumulatorB, accumulatorC }; } //}); } // do the part 2 and 3 double[] cornerness = new double[image.Width * image.Height]; for (int i = 0; i < matrices.Length; i++) { double det = (matrices[i][0] * matrices[i][1]) - (matrices[i][2] * matrices[i][2]); double trace = matrices[i][0] + matrices[i][1]; double corner = det - (HarrisK * (trace * trace)); if (corner >= HarrisThreshold) { cornerness[i] = corner; } } //return ToPNM(cornerness, image.Width, image.Height); CenteredNonMaximumSuppression(cornerness, image.Width, image.Height, 3); // draw corners PNM newImage = PNM.Copy(image); for (int i = 0; i < cornerness.Length; i++) { if (cornerness[i] == 0) { continue; } MarkPixel(newImage, i); } return(newImage); }
private static void MarkPixel(PNM image, int index) { int x = index % image.Width; int y = index / image.Width; for (int x0 = -1; x0 <= 1; x0++) { for (int y0 = -1; y0 <= 1; y0++) { if(x0 == 0 && y0 == 0) continue; int currentY = y + y0; int currentX = x + x0; if(currentX < 0 || currentX >= image.Width || currentY < 0 || currentY >= image.Height) continue; image.SetPixel(x + x0, y + y0, 0, 255, 0); } } }