/// <summary> /// Writes an RGBImage to the stream. /// </summary> /// <param name="stream">The stream to write to</param> /// <param name="image">The image to write</param> public static unsafe void Write(Stream stream, RGBImage image) { int rows = image.Rows; int columns = image.Columns; int scan = columns * 3; byte[] row = new byte[scan]; fixed(byte *src = image.RawArray, dst = row) { byte *srcPtr = src; for (int r = 0; r < rows; r++) { int count = scan; byte *dstPtr = dst; while (count-- != 0) { *dstPtr++ = *srcPtr++; } stream.Write(row, 0, scan); } } stream.Flush(); }
private static unsafe RGBImage readColorShortImage(int columns, int rows, int max, FileStream stream) { RGBImage image = new RGBImage(rows, columns); double multiplier = 255.0 / max; fixed(byte *src = image.RawArray) { byte *ptr = src; byte[] scanline = new byte[columns * 6]; for (int r = 0; r < rows; r++) { int count = 0; while (count < scanline.Length) { count += stream.Read(scanline, count, scanline.Length - count); } for (int c = 0; c < columns; c++) { int shortR = scanline[c * 6]; shortR = shortR << 8 + scanline[c * 6 + 1]; int shortG = scanline[c * 6 + 2]; shortG = shortG << 8 + scanline[c * 6 + 3]; int shortB = scanline[c * 6 + 4]; shortB = shortB << 8 + scanline[c * 6 + 5]; *ptr++ = (byte)(multiplier * shortR); *ptr++ = (byte)(multiplier * shortG); *ptr++ = (byte)(multiplier * shortB); } } } return(image); }
/// <summary> /// Constructor. /// </summary> /// <param name="image">The color image to construct this image from. The values are calculated as (min(R,G,B) + max(R,G,B))/2</param> public unsafe MonochromeImage(RGBImage image) { int rows = image.Rows; int columns = image.Columns; _handler = new IntegerArrayHandler(rows, columns, 1); fixed(int *dst = _handler.RawArray) { fixed(byte *src = image.RawArray) { int * dstPtr = dst; byte *srcPtr = src; int count = rows * columns; while (count-- > 0) { int R = *srcPtr++; int G = *srcPtr++; int B = *srcPtr++; int min = R < G ? (R < B ? R : (B < G ? B : G)) : (G < B ? G : B); int max = R > G ? (R > B ? R : (B > G ? B : G)) : (G > B ? G : B); * dstPtr++ = (min + max) >> 1; } } } }
/// <summary> /// Constructor. /// </summary> /// <param name="rgb">Source image</param> /// <param name="converter">Converter to use</param> public unsafe ColorImage(RGBImage rgb, ColorSpaceConverter converter) { _handler = new FloatArrayHandler(rgb.Rows, rgb.Columns, 3); fixed(byte *src = rgb.RawArray) { fixed(float *dst = _handler.RawArray) { byte * srcPtr = src; float *dstPtr = dst; int length = Rows * Columns; while (length-- > 0) { float i1 = *srcPtr++; float i2 = *srcPtr++; float i3 = *srcPtr++; float o1, o2, o3; o1 = o2 = o3 = 0; converter(i1, i2, i3, ref o1, ref o2, ref o3); *dstPtr++ = o1; *dstPtr++ = o2; *dstPtr++ = o3; } } } }
private static unsafe RGBImage readColorByteImage(int columns, int rows, int max, FileStream stream) { RGBImage image = new RGBImage(rows, columns); double multiplier = 255.0 / max; fixed(byte *src = image.RawArray) { byte *ptr = src; byte[] scanline = new byte[columns * 3]; for (int r = 0; r < rows; r++) { int count = 0; while (count < scanline.Length) { count += stream.Read(scanline, count, scanline.Length - count); } for (int c = 0; c < columns; c++) { byte R = scanline[c * 3]; byte G = scanline[c * 3 + 1]; byte B = scanline[c * 3 + 2]; * ptr++ = (byte)(R * multiplier); * ptr++ = (byte)(G * multiplier); * ptr++ = (byte)(B * multiplier); } } } return(image); }
/// <summary> /// Converts the image to an RGB image. /// </summary> /// <param name="converter">The converter to use.</param> /// <returns>The converted image</returns> public RGBImage ToRGBImage(ColorSpaceConverter converter) { RGBImage rgb = new RGBImage(Rows, Columns); unsafe { fixed(float *src = RawArray) { fixed(byte *dst = rgb.RawArray) { float *srcPtr = src; byte * dstPtr = dst; int length = Rows * Columns; while (length-- > 0) { float i1 = *srcPtr++; float i2 = *srcPtr++; float i3 = *srcPtr++; float o1, o2, o3; o1 = o2 = o3 = 0; converter(i1, i2, i3, ref o1, ref o2, ref o3); *dstPtr++ = (byte)o1; *dstPtr++ = (byte)o2; *dstPtr++ = (byte)o3; } } } } return(rgb); }
/// <summary> /// Constructor. /// </summary> /// <param name="image">Source image</param> public unsafe GrayscaleImage(RGBImage image) { _handler = new FloatArrayHandler(image.Rows, image.Columns, 1); fixed(byte *src = image.RawArray) { fixed(float *dst = _handler.RawArray) { byte * srcPtr = src; float *dstPtr = dst; int length = Rows * Columns; while (length-- > 0) { int R = *srcPtr++; int G = *srcPtr++; int B = *srcPtr++; float min = Math.Min(R, Math.Min(G, B)); float max = Math.Max(R, Math.Max(G, B)); float val = (min + max) / 2; * dstPtr++ = val / 255; } } } ID = image.ID; }
/// <summary> /// Constructor. /// </summary> /// <param name="image">Source image</param> /// <param name="transform">Transform that converts RGB to grayscale</param> public unsafe GrayscaleImage(RGBImage image, float[] transform) { float t0 = transform[0]; float t1 = transform[1]; float t2 = transform[2]; _handler = new FloatArrayHandler(image.Rows, image.Columns, 1); fixed(byte *src = image.RawArray) { fixed(float *dst = _handler.RawArray) { byte * srcPtr = src; float *dstPtr = dst; int length = Rows * Columns; while (length-- > 0) { int R = *srcPtr++; int G = *srcPtr++; int B = *srcPtr++; *dstPtr++ = t0 * R + t1 * G + t2 * B; } } } ID = image.ID; }
/// <summary> /// Writes an RGBImage to the provided location. /// </summary> /// <param name="filename">The filename to write to. If this ends with ".gz", then the data will be compressed with GZip as it is written.</param> /// <param name="image">The image to write</param> public static unsafe void Write(string filename, RGBImage image) { Stream output = new FileStream(filename, FileMode.Create, FileAccess.Write); if (filename.EndsWith(".gz")) { output = new GZipStream(output, CompressionMode.Compress); } Write(output, image); output.Close(); }
/// <summary> /// Converts this monochrome image to an RGB image. If the image is an integral image, it will store the bottom 24 bits in the R, G and B values. If /// it is not an integral image, it will convert each brightness value to a byte. /// </summary> /// <returns></returns> public unsafe RGBImage ToRGB() { int rows = Rows; int columns = Columns; RGBImage rgb; if (IsIntegral) { rows++; columns++; rgb = new RGBImage(rows, columns); fixed(int *src = _handler.RawArray) { fixed(byte *dst = rgb.RawArray) { int * srcPtr = src; byte *dstPtr = dst; int count = rows * columns; while (count-- != 0) { int val = *srcPtr++; * dstPtr++ = (byte)((val & 0xFF0000) >> 16); * dstPtr++ = (byte)((val & 0xFF00) >> 8); * dstPtr++ = (byte)(val & 0xFF); } } } } else { rgb = new RGBImage(rows, columns); fixed(int *src = _handler.RawArray) { fixed(byte *dst = rgb.RawArray) { int * srcPtr = src; byte *dstPtr = dst; int count = rows * columns; while (count-- != 0) { int val = *srcPtr++; byte small = (byte)val; * dstPtr++ = small; * dstPtr++ = small; * dstPtr++ = small; } } } } return(rgb); }
/// <summary> /// Creates a "heat" image wherein values are shown on a scale from blue to red for better visualization of gradients using /// the provided min and max values. /// </summary> /// <returns>An RGB Image</returns> public unsafe RGBImage ToHeatImage(float min, float max) { RGBImage result = new RGBImage(Rows, Columns); float scale = max - min; if (scale == 0) scale = 1; fixed(byte *dst = result.RawArray) { fixed(float *src = _handler.RawArray) { float *srcPtr = src; byte * dstPtr = dst; int length = Rows * Columns; while (length-- != 0) { float tmp = *srcPtr++; float x = (tmp - min) / scale; if (x == 0) { *dstPtr++ = 0; *dstPtr++ = 0; *dstPtr++ = 255; } else if (x < .5f) { float val = 255 * x / .5f; * dstPtr++ = 0; * dstPtr++ = (byte)val; * dstPtr++ = (byte)(255 - val); } else { x -= .5f; float val = 255 * x / .5f; * dstPtr++ = (byte)val; * dstPtr++ = (byte)(255 - val); * dstPtr++ = 0; } } } } return(result); }
/// <summary> /// Converts the grayscale image to an RGB image using the provided <paramref name="min"/> and <paramref name="max"/> values. /// </summary> /// <param name="min">Minimum value (corresponds to a brightness of 0)</param> /// <param name="max">Maximum value (corresponds to a brightness of 255)</param> /// <param name="color">Color to use for tinting the image</param> /// <returns></returns> public unsafe RGBImage ToRGBImage(float min, float max, Color color) { RGBImage result = new RGBImage(Rows, Columns); byte R = color.R; byte G = color.G; byte B = color.B; float scale = max - min; if (scale == 0) { scale = 1; } scale = 1.0f / scale; fixed(byte *dst = result.RawArray) { fixed(float *src = _handler.RawArray) { float *srcPtr = src; byte * dstPtr = dst; int length = Rows * Columns; while (length-- > 0) { float tmp = *srcPtr++; if (tmp > max) { tmp = max; } if (tmp < min) { tmp = min; } float val = (tmp - min) * scale; * dstPtr++ = (byte)(val * R); * dstPtr++ = (byte)(val * G); * dstPtr++ = (byte)(val * B); } } } return(result); }
/// <summary> /// When converted to a Bitmap, the image will show red at corners, blue at uniform regions, and green at edges. /// </summary> /// <param name="sensitivity">The sensitivity threshold to use when determining edges and corners.</param> /// <returns>A representative Bitmap</returns> public unsafe BitmapSource ToBitmap(float sensitivity) { RGBImage rgb = new RGBImage(Rows, Columns); fixed(byte *dst = rgb.RawArray) { fixed(float *src = RawArray) { byte * dstPtr = dst; float *srcPtr = src; int length = Rows * Columns; while (length-- > 0) { float lambda1 = *srcPtr++; float lambda2 = *srcPtr++; srcPtr += 4; if (lambda1 < sensitivity && lambda2 < sensitivity) { dstPtr[2] = (byte)255; } else if (lambda2 < sensitivity) { dstPtr[1] = (byte)255; } else { *dstPtr = (byte)255; } dstPtr += 3; } } } return(rgb.ToBitmap()); }
/// <summary> /// Reads RAW data from the stream as an RGB image. /// </summary> /// <param name="stream">The stream containing the image data</param> /// <param name="rows">The number of rows in the image</param> /// <param name="columns">The number of columns in the image</param> /// <returns>The RGB image</returns> public static unsafe RGBImage ReadAsRGB(Stream stream, int rows, int columns) { RGBImage image = new RGBImage(rows, columns); int scan = columns * 3; byte[] row = new byte[scan]; fixed(byte *dst = image.RawArray, src = row) { byte *dstPtr = dst; for (int r = 0; r < rows; r++) { stream.Read(row, 0, scan); int count = scan; byte *srcPtr = src; while (count-- != 0) { *dstPtr++ = *srcPtr++; } } } return(image); }
/// <summary> /// Saves the provided image to the destination path using the extension to determine the file format. /// </summary> /// <param name="image">Image to save</param> /// <param name="filename">Path to destination image</param> public static void Save(RGBImage image, string filename) { Save(image, filename, IO.GetEncoder(filename)); }
/// <summary> /// Constructor. Uses the <see cref="ColorConversion.RGB2rgb"/> converter. /// </summary> /// <param name="image">Source image</param> public ColorImage(RGBImage image) : this(image, new ColorSpaceConverter(ColorConversion.RGB2rgb)) { }
/// <summary> /// Saves the provided image to the destination path using the provided encoder. /// </summary> /// <param name="image">Image to save</param> /// <param name="filename">Path to destination file</param> /// <param name="encoder">Encoder to use</param> public static void Save(RGBImage image, string filename, BitmapEncoder encoder) { encoder.Frames.Add(BitmapFrame.Create(image.ToBitmap())); encoder.Save(filename); }