/// <summary> /// Create color histogram with N bins /// </summary> /// <param name="source">image source</param> /// <param name="histogram">byte buffer (N^3 bytes)</param> /// <param name="bins">number of bins</param> /// <param name="startX">start from this X coordinate</param> /// <param name="startY">start from this Y coordinate</param> /// <param name="width">width</param> /// <param name="height">height</param> public void HistogramN(IImage2DByteRgbA source, uint[] histogram, byte bins, int startX, int startY = 0, int width = 0, int height = 0) { if (source == null) throw new ArgumentNullException("source"); if (histogram == null) throw new ArgumentNullException("histogram"); if (bins < 2) throw new ArgumentException("bins must be at least 2", "bins"); int size = bins * bins * bins; if (histogram.Length < size) throw new ArgumentException("Buffer size for histogram must be at least " + size + " bytes", "histogram"); if (width == 0) width = source.Width - startX; if (height == 0) height = source.Height - startY; if (width < 0) throw new ArgumentOutOfRangeException("width"); if (height < 0) throw new ArgumentOutOfRangeException("height"); for (int i = 0; i < size; i++) histogram[i] = 0; float div = 256.0f / bins; int bins2 = bins * bins; for (int y = startY, yh = startY + height; y < yh; y++) { int pos = (y * source.Width + startX) * 4; for (int x = startX, xw = startX + width; x < xw; x++) { byte r = (byte)(source.HostBuffer[pos++] / div); byte g = (byte)(source.HostBuffer[pos++] / div); byte b = (byte)(source.HostBuffer[pos++] / div); pos++; histogram[r + g * bins + b * bins2]++; } } }
/// <summary> /// Create color histogram with N bins /// </summary> /// <param name="source">image source</param> /// <param name="histogram">byte buffer (N^3 bytes)</param> /// <param name="bins">number of bins</param> public void HistogramN(IImage2DByteRgbA source, uint[] histogram, byte bins) { if (source == null) throw new ArgumentNullException("source"); if (histogram == null) throw new ArgumentNullException("histogram"); int size = bins * bins * bins; if (histogram.Length < size) throw new ArgumentException("Buffer size for histogram must be at least " + size + " bytes", "histogram"); for (int i = 0; i < size; i++) histogram[i] = 0; float div = 256f / bins; int pos = 0; int bins2 = bins * bins; for (int i = 0, length = source.Width * source.Height; i < length; i++) { byte r = (byte)(source.HostBuffer[pos++] / div); byte g = (byte)(source.HostBuffer[pos++] / div); byte b = (byte)(source.HostBuffer[pos++] / div); pos++; histogram[r + g * bins + b * bins2]++; } }
/// <summary> /// Create color histogram with N bins /// </summary> /// <param name="source">image source</param> /// <param name="histogram">byte buffer (N^3 bytes)</param> /// <param name="bins">number of bins</param> /// <param name="startX">start from this X coordinate</param> /// <param name="startY">start from this Y coordinate</param> /// <param name="width">width</param> /// <param name="height">height</param> public void HistogramN(IImage2DByteRgbA source, IBuffer<uint> histogram, byte bins, int startX, int startY = 0, int width = 0, int height = 0) { HistogramN(source, histogram.HostBuffer, bins, startX, startY, width, height); }
/// <summary> /// GrayScale image /// </summary> /// <param name="source">image source</param> /// <param name="dest">image destination</param> public void GrayScale(IImage2DByteRgbA source, IImage2DByteA dest) { if (source == null) throw new ArgumentNullException("source"); if (dest == null) throw new ArgumentNullException("dest"); if ((source.Width > dest.Width) || (source.Height > dest.Height)) throw new ArgumentException("Destination image (" + dest.Width + "x" + dest.Height + ") must have at least the same size as the source image (" + source.Width + "x" + source.Height + ")"); int length = source.Width * source.Height; int pos = 0; for (int i = 0; i < length; i++) { float gray = 0.2989f * (float)source.HostBuffer[pos++] + 0.5870f * (float)source.HostBuffer[pos++] + 0.1140f * (float)source.HostBuffer[pos++]; pos++; dest.HostBuffer[i] = (byte)gray; } }
/// <summary> /// Create color histogram with N bins /// </summary> /// <param name="source">image source</param> /// <param name="histogram">byte buffer (N^3 bytes)</param> /// <param name="bins">number of bins</param> public void HistogramN(IImage2DByteRgbA source, IBuffer<uint> histogram, byte bins) { HistogramN(source, histogram.HostBuffer, bins); }
/// <summary> /// Flip image Y coordinate /// </summary> /// <param name="source">image source</param> /// <param name="dest">image destination</param> public void FlipY(IImage2DByteRgbA source, IImage2DByteRgbA dest) { if (source == null) throw new ArgumentNullException("source"); if (dest == null) throw new ArgumentNullException("dest"); if (source == dest) throw new ArgumentException("Flipping kernel is not designed to run inline therefore source and destination must be different images"); if ((source.Width > dest.Width) || (source.Height > dest.Height)) throw new ArgumentException("Destination image (" + dest.Width + "x" + dest.Height + ") must have at least the same size as the source image (" + source.Width + "x" + source.Height + ")"); var sBuf = source.HostBuffer; var dBuf = dest.HostBuffer; int posSource = 0; int posDest = 4 * (source.Height - 1) * dest.Width; for (int y = 0, h = source.Height; y < h; y++) { for (int x = 0, w = source.Width; x < w; x++) { byte color; color = sBuf[posSource++]; dBuf[posDest++] = color; color = sBuf[posSource++]; dBuf[posDest++] = color; color = sBuf[posSource++]; dBuf[posDest++] = color; color = sBuf[posSource++]; dBuf[posDest++] = color; } posDest -= 4 * (dest.Width + source.Width); } }
/// <summary> /// Extracts a channel of an RGB image /// </summary> /// <param name="source">image source</param> /// <param name="dest">image destination</param> /// <param name="offset">offset (0..3)</param> public void ExtractChannel(IImage2DByteRgbA source, IImage2DByteA dest, byte offset) { if (source == null) throw new ArgumentNullException("source"); if (dest == null) throw new ArgumentNullException("dest"); if (offset > 3) throw new ArgumentOutOfRangeException("offset", String.Format("offset must be between 0..3 but was {0}", offset)); if ((source.Width > dest.Width) || (source.Height > dest.Height)) throw new ArgumentException("Destination image (" + dest.Width + "x" + dest.Height + ") must have at least the same size as the source image (" + source.Width + "x" + source.Height + ")"); int length = source.Width * source.Height; int pos = 0; for (int i = 0; i < length; i++) for (int j = 0; j < 4; j++) if (j == offset) dest.HostBuffer[i] = source.HostBuffer[pos++]; else pos++; }
/// <summary> /// Convert gray byte image to RGB byte image /// </summary> /// <param name="source">image source</param> /// <param name="dest">image destination</param> public void ByteAToByteRgbA(IImage2DByteA source, IImage2DByteRgbA dest) { if (source == null) throw new ArgumentNullException("source"); if (dest == null) throw new ArgumentNullException("dest"); if ((source.Width > dest.Width) || (source.Height > dest.Height)) throw new ArgumentException("Destination image (" + dest.Width + "x" + dest.Height + ") must have at least the same size as the source image (" + source.Width + "x" + source.Height + ")"); int length = source.HostBuffer.Length; int pos = 0; for (int i = 0; i < length; i++) { byte val = source.HostBuffer[i]; dest.HostBuffer[pos++] = val; dest.HostBuffer[pos++] = val; dest.HostBuffer[pos++] = val; dest.HostBuffer[pos++] = 255; } }
/// <summary> /// Sets a constant value to all cells in an image /// </summary> /// <param name="image">image</param> /// <param name="value">value to set</param> public void SetValue(IImage2DByteRgbA image, uint value) { if (image == null) throw new ArgumentNullException("image"); byte r = (byte)((value >> 24) % 256); byte g = (byte)((value >> 16) % 256); byte b = (byte)((value >> 8) % 256); byte a = (byte)((value) % 256); int length = image.Width * image.Height; int pos = 0; for (int i = 0; i < length; i++) { image.HostBuffer[pos++] = r; image.HostBuffer[pos++] = g; image.HostBuffer[pos++] = b; image.HostBuffer[pos++] = a; } }
/// <summary> /// RGB to HSL image /// </summary> /// <param name="source">image source</param> /// <param name="dest">image destination</param> public void RgbToHsl(IImage2DByteRgbA source, IImage2DByteRgbA dest) { if (source == null) throw new ArgumentNullException("source"); if (dest == null) throw new ArgumentNullException("dest"); if ((source.Width > dest.Width) || (source.Height > dest.Height)) throw new ArgumentException("Destination image (" + dest.Width + "x" + dest.Height + ") must have at least the same size as the source image (" + source.Width + "x" + source.Height + ")"); for (int i = 0, j = 0, length = source.HostBuffer.Length; i < length;) { Color color = Color.FromArgb((int)source.HostBuffer[i++], (int)source.HostBuffer[i++], (int)source.HostBuffer[i++]); dest.HostBuffer[j++] = (byte)(color.GetHue() * 255f / 360f); dest.HostBuffer[j++] = (byte)(color.GetSaturation() * 255f); dest.HostBuffer[j++] = (byte)(color.GetBrightness() * 255f); dest.HostBuffer[j++] = source.HostBuffer[i++]; } }