internal static HistoRaw CalculateHistogram(ImageComponent <int> image) { var maxValue = 1 << image.ColorDepth; HistoRaw histogram = new HistoRaw() { luma = new int[maxValue], red = new int[maxValue], blue = new int[maxValue], green = new int[maxValue] }; for (int y = 0; y < image.dim.height; y++) { long realY = (y + image.offset.height) * image.UncroppedDim.width; for (int x = 0; x < image.dim.width; x++) { long realPix = realY + x + image.offset.width; histogram.luma[(int)(0.299 * image.red[realPix] + 0.587 * image.green[realPix] + 0.114 * image.blue[realPix])]++; histogram.red[image.red[realPix]]++; histogram.green[image.green[realPix]]++; histogram.blue[image.blue[realPix]]++; } } return(histogram); }
internal static void HistogramEqualisation(ImageComponent <int> image, HistoRaw histogram) { //TODO change and correct //apply histogram equalisation if needed using the histogram //create a lookup table var lut = new int[uint.MaxValue]; double pixelCount = image.dim.height * image.dim.width; int sum = 0; // build a LUT containing scale factor for (int i = 0; i < lut.Length; ++i) { sum += histogram.luma[i]; lut[i] = (int)(sum * 255 / pixelCount); } // transform image using sum histogram as a LUT Parallel.For(0, image.dim.height, y => { long realY = y * image.dim.width; for (int x = 0; x < image.dim.width; x++) { long realX = realY + x; image.red[realX] = lut[image.red[realX]]; image.green[realX] = lut[image.green[realX]]; image.blue[realX] = lut[image.blue[realX]]; } }); }
public unsafe HistoRaw ApplyTo16Bits(ImageComponent <ushort> image, SoftwareBitmap bitmap, bool histogram) { Debug.Assert(bitmap.BitmapPixelFormat == BitmapPixelFormat.Rgba16); var buffer = Apply(image); //Clip the image //Luminance.Clip(buffer, 16); HistoRaw histo = null; //calculate the new histogram (create a 8 bits histogram) if (histogram) { histo = HistogramHelper.CalculateHistogram(buffer); } //copy the buffer to the image with clipping //calculte the shift between colordepth input and output int shift = image.ColorDepth - 16; using (BitmapBuffer buff = bitmap.LockBuffer(BitmapBufferAccessMode.Write)) using (var reference = buff.CreateReference()) { ((IMemoryBufferByteAccess)reference).GetBuffer(out var temp, out uint capacity); Parallel.For(0, buffer.dim.height, y => { long realY = y * buffer.dim.width; for (int x = 0; x < buffer.dim.width; x++) { long realPix = realY + x; long bufferPix = realPix * 8; temp[bufferPix] = (byte)(buffer.red[realPix] >> 8); temp[bufferPix + 1] = (byte)(buffer.red[realPix]); temp[bufferPix + 2] = (byte)(buffer.green[realPix] >> 8); temp[bufferPix + 3] = (byte)(buffer.green[realPix]); temp[bufferPix + 4] = (byte)(buffer.blue[realPix] >> 8); temp[bufferPix + 5] = (byte)(buffer.blue[realPix]); temp[bufferPix + 6] = 255; //set transparency to 255 else image will be blank temp[bufferPix + 7] = 255; //set transparency to 255 else image will be blank } }); } return(histo); }
public unsafe HistoRaw ApplyTo8Bits(ImageComponent <ushort> image, SoftwareBitmap bitmap, bool histogram) { Debug.Assert(image.red != null); Debug.Assert(image.blue != null); Debug.Assert(image.green != null); Debug.Assert(image.dim.Area >= 4); Debug.Assert(bitmap != null); Debug.Assert(image.dim.Area == bitmap.PixelHeight * bitmap.PixelWidth); var buffer = Apply(image); //Clip the image Luminance.Clip(buffer, 8); //calculate the new histogram (create a 8 bits histogram) HistoRaw histo = null; if (histogram) { histo = HistogramHelper.CalculateHistogram(buffer); } //copy the buffer to the image with clipping using (BitmapBuffer buff = bitmap.LockBuffer(BitmapBufferAccessMode.Write)) using (var reference = buff.CreateReference()) { ((IMemoryBufferByteAccess)reference).GetBuffer(out var temp, out uint capacity); Parallel.For(0, buffer.dim.height, y => { long realY = y * buffer.dim.width; for (int x = 0; x < buffer.dim.width; x++) { long realPix = realY + x; long bufferPix = realPix * 4; temp[bufferPix] = (byte)(buffer.blue[realPix]); temp[bufferPix + 1] = (byte)(buffer.green[realPix]); temp[bufferPix + 2] = (byte)(buffer.red[realPix]); temp[bufferPix + 3] = 255; //set transparency to 255 else image will be blank } }); } return(histo); }
internal static HistoRaw CalculateLumaHistogram(ImageComponent <int> image) { HistoRaw histogram = new HistoRaw() { luma = new int[(1 << image.ColorDepth)] }; for (int y = 0; y < image.dim.height; y++) { long realY = (y + image.offset.height) * image.UncroppedDim.width; for (int x = 0; x < image.dim.width; x++) { long realPix = realY + x + image.offset.width; histogram.luma[(int)((Math.Max(Math.Max(image.red[realPix], image.green[realPix]), image.blue[realPix]) + Math.Min(Math.Min(image.red[realPix], image.green[realPix]), image.blue[realPix])) / 2.0)]++; } } return(histogram); }