protected void SinglePixelProcessing(ImageComponent <ushort> image, ImageComponent <int> buffer, double[] curve) { Debug.Assert(image.red != null); Debug.Assert(image.blue != null); Debug.Assert(image.green != null); Debug.Assert(image.dim.Area >= 4); Debug.Assert(buffer.red != null); Debug.Assert(buffer.blue != null); Debug.Assert(buffer.green != null); Debug.Assert(buffer.dim.Area == image.dim.Area); Parallel.For(0, 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; double red = image.red[realPix] * rMul, green = image.green[realPix] * gMul, blue = image.blue[realPix] * bMul; Luminance.Clip(ref red, ref green, ref blue, maxValue); ColorManipulation.RgbToHsl(red, green, blue, maxValue, out double h, out double s, out double l); l = curve[(int)(l * maxValue)]; s *= saturation; ColorManipulation.HslToRgb(h, s, l, maxValue, out red, out green, out blue); long bufferPix = Rotate(x, y, image.dim.width, image.dim.height); buffer.red[bufferPix] = (int)red; buffer.green[bufferPix] = (int)green; buffer.blue[bufferPix] = (int)blue; }
protected ImageComponent <int> Apply(ImageComponent <ushort> image) { Debug.Assert(image.red != null); Debug.Assert(image.blue != null); Debug.Assert(image.green != null); Debug.Assert(image.dim.Area >= 4); //calculate the max value for clip maxValue = (uint)(1 << image.ColorDepth) - 1; HistoRaw histo; //TODO cut the image in patch to reduce memory var buffer = new ImageComponent <int>(image.dim, image.ColorDepth); //apply the single pixel processing SinglePixelProcessing(image, buffer, CreateCurve()); ColorManipulation.SplitTone(buffer, new Pixel(SplitShadow), new Pixel(SplitHighlight), SplitBalance, maxValue); if (Rotation == 1 || Rotation == 3) { buffer.dim.Flip(); buffer.UncroppedDim.Flip(); } //clip Luminance.Clip(buffer); //apply histogram equalisation if any if (histogramEqual) { //calculate the histogram histo = HistogramHelper.CalculateLumaHistogram(buffer); HistogramHelper.HistogramEqualisation(buffer, histo); } //apply denoising if (denoise != 0) { buffer = Denoising.Apply(buffer, (int)denoise); } //apply sharpening (always last step) if (sharpness != 0) { buffer = Sharpening.Apply(buffer, (int)sharpness); } //return the final histogram return(buffer); }
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); }