private IColor ComputeClosestColor(IColor currentColor) { IColor retVal = (IColor)currentColor.Clone(); if (Automatic) { retVal.R = (byte)(_delta[0] * ((int)(currentColor.R / _delta[0]) + .5f) - 1); retVal.G = (byte)(_delta[1] * ((int)(currentColor.G / _delta[1]) + .5f) - 1); retVal.B = (byte)(_delta[2] * ((int)(currentColor.B / _delta[2]) + .5f) - 1); } else { double minDelta = double.MaxValue; IColor diffColor = ColorByte.Empty; for (int index = 0; index < Attractors.Length; index++) { double diff = ImageComparator.ColorDifferenceARGB(new ColorByte(Attractors[index]), currentColor, out diffColor); if (diff < ColorAttractorThreshold && diff < minDelta) { minDelta = diff; retVal.ARGB = Attractors[index].ToArgb(); } else { retVal.IsEmpty = true; } } } return(retVal); }
/* * private int[] ComputeLUT() * { * double delta = NormalizedColor.ComputedUpperBound - NormalizedColor.ComputedLowerBound + 1; * * * double scale = 0; * double translate = 0; * int[] retVal = new int[(int)(delta)]; * double normalizedBrightness = (Brightness + 1.0) / 2.0; * if (Contrast <= 0.0) * { * scale = Contrast + 1.0; * translate = (normalizedBrightness - (1.0 - normalizedBrightness) * scale) * NormalizedColor.NormalizeValue; * for (int index = 0; index < (int)delta; index++) * { * retVal[index] = (int)(SaturateColor((index * scale + translate) / NormalizedColor.NormalizeValue) * NormalizedColor.NormalizeValue); * } * * } * else * { * scale = 1.0 - Contrast; * translate = (1.0 - normalizedBrightness * (scale + 1.0)) * NormalizedColor.NormalizeValue; * for (int index = (int)NormalizedColor.ComputedLowerBound; index <= NormalizedColor.ComputedUpperBound; index++) * { * retVal[index] = (int)(SaturateColor((index - translate) / (scale * NormalizedColor.NormalizeValue)) * NormalizedColor.NormalizeValue); * } * } * return retVal; * } */ private IColor MapColor(IColor originalColor) { IColor mappedColor = (IColor)originalColor.Clone(); double scale = 0; double translate = 0; double normalizedBrightness = (Brightness + 1.0) / 2.0; if (Contrast <= 0.0) { scale = Contrast + 1.0; translate = (normalizedBrightness - (1.0 - normalizedBrightness) * scale); mappedColor.ExtendedAlpha = originalColor.ExtendedAlpha; mappedColor.ExtendedRed = originalColor.ExtendedRed * scale + translate; mappedColor.ExtendedGreen = originalColor.ExtendedGreen * scale + translate; mappedColor.ExtendedBlue = originalColor.ExtendedBlue * scale + translate; } else { scale = 1.0 - Contrast; translate = (1.0 - normalizedBrightness * (scale + 1.0)); mappedColor.ExtendedAlpha = originalColor.Alpha; mappedColor.ExtendedRed = (originalColor.ExtendedRed - translate) / scale; mappedColor.ExtendedGreen = (originalColor.ExtendedGreen - translate) / scale; mappedColor.ExtendedBlue = (originalColor.ExtendedBlue - translate) / scale; } return(mappedColor); }
/// <summary> /// Instanciate a new width * height ImageAdapter object and initalize every entry with the specified color /// </summary> /// <param name="width">The width of the image adapter</param> /// <param name="height">The height of the image adapter</param> /// <param name="initColor">The color to use for initalization</param> public ImageAdapter(int width, int height, IColor initColor) : this(width, height) { if (width < 0 || height < 0) { throw new ArgumentOutOfRangeException("Width nor Height can have negative values"); } for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (initColor != null) { _colors[x, y] = (IColor)initColor.Clone(); } } } }
/// <summary> /// Perform the operation /// </summary> /// <param name="source">The image to use for the operation</param> /// <returns>The Filtered image</returns> protected override IImageAdapter ProcessFilter(IImageAdapter source) { IImageAdapter retVal = source; if (SplitChannel) { ImageAdapter alphaChannel = new ImageAdapter(source.Width, source.Height); ImageAdapter redChannel = new ImageAdapter(source.Width, source.Height); ImageAdapter greenChannel = new ImageAdapter(source.Width, source.Height); ImageAdapter blueChannel = new ImageAdapter(source.Width, source.Height); for (int y = 0; y < source.Height; y++) { for (int x = 0; x < source.Width; x++) { double alpha = source[x, y].Alpha; alphaChannel[x, y] = (IColor)source[x, y].Clone(); alphaChannel[x, y].RGB = 0; if (ReinjectAlphaInAllChannels) { redChannel[x, y] = (IColor)source[x, y].Clone(); redChannel[x, y].RGB = source[x, y].R << 16; greenChannel[x, y] = (IColor)source[x, y].Clone(); greenChannel[x, y].RGB = source[x, y].G << 8; blueChannel[x, y] = (IColor)source[x, y].Clone(); blueChannel[x, y].RGB = source[x, y].B; } else { redChannel[x, y] = (IColor)source[x, y].Clone(); redChannel[x, y].ARGB = source[x, y].R << 16; greenChannel[x, y] = (IColor)source[x, y].Clone(); greenChannel[x, y].ARGB = source[x, y].G << 8; blueChannel[x, y] = (IColor)source[x, y].Clone(); blueChannel[x, y].ARGB = source[x, y].B; } } } AlphaChannel = alphaChannel; RedChannel = redChannel; GreenChannel = greenChannel; BlueChannel = blueChannel; } else { if (!JoinChannel && !AddChannel && !MultiplyChannel && !DivideChannel) { throw new RenderingVerificationException("Nothing selected !"); } ArrayList tempChannels = new ArrayList(4); if (AlphaChannel.Width != 0) { tempChannels.Add(AlphaChannel); } if (RedChannel.Width != 0) { tempChannels.Add(RedChannel); } if (GreenChannel.Width != 0) { tempChannels.Add(GreenChannel); } if (BlueChannel.Width != 0) { tempChannels.Add(BlueChannel); } if (source.Width != 0) { tempChannels.Add(source); } IImageAdapter[] channels = new IImageAdapter[tempChannels.Count]; tempChannels.CopyTo(channels); retVal = new ImageAdapter(source.Width, source.Height); IColor colorEmpty = (IColor)source[0, 0].Clone(); colorEmpty.IsEmpty = true; channelOperationHandler channelOperation = null; if (AddChannel || JoinChannel) { channelOperation = new channelOperationHandler(AddOperation); } if (SubtractChannel) { channelOperation = new channelOperationHandler(SubtractOperation); } if (MultiplyChannel) { channelOperation = new channelOperationHandler(MultiplyOperation); } if (DivideChannel) { channelOperation = new channelOperationHandler(DivideOperation); } IColor color = null; for (int y = 0; y < retVal.Height; y++) { for (int x = 0; x < retVal.Width; x++) { color = (IColor)colorEmpty.Clone(); color.Alpha = channelOperation(x, y, ref channels, IPUtil.ALPHA); color.Red = channelOperation(x, y, ref channels, IPUtil.RED); color.Green = channelOperation(x, y, ref channels, IPUtil.GREEN); color.Blue = channelOperation(x, y, ref channels, IPUtil.BLUE); retVal[x, y] = color; } } } // return(retVal); }
/// <summary> /// Perform a Bilinear interpolation /// </summary> /// <param name="x">position on the x Axis</param> /// <param name="y">position on the y Axis</param> /// <param name="imageSource">The image to perform interpolation on</param> /// <param name="unassignedColor">The color to use for pixel that are unassigned\nCan be set to null (Empty color will be used)</param> /// <returns>The interpolated color</returns> public static IColor ProcessPoint(double x, double y, IImageAdapter imageSource, IColor unassignedColor) { IColor retVal = null; if (imageSource == null) { throw new ArgumentNullException("imageSource", "The IImageAdapter passed in cannot be null"); } if (x >= 0.0 && y >= 0.0 && x <= imageSource.Width - 1 && y <= imageSource.Height - 1) { int ix = (int)x; int iy = (int)y; int incx = (ix >= imageSource.Width - 1) ? 0 : 1; int incy = (iy >= imageSource.Height - 1) ? 0 : 1; retVal = (IColor)imageSource[ix, iy].Clone(); retVal.IsEmpty = true; IColor c00 = imageSource[ix, iy]; IColor c01 = imageSource[ix, iy + incy]; IColor c10 = imageSource[ix + incx, iy]; IColor c11 = imageSource[ix + incx, iy + incy]; if (c00.IsEmpty) { return((IColor)unassignedColor.Clone()); } if (c01.IsEmpty || c10.IsEmpty || c11.IsEmpty) { // do this only if one of the color is "Empty" because this is time consumming (lots of computation) ColorByte tempColor = new ColorByte(); int indexC00 = (int)(Math.Sqrt(((x - ix) * (x - ix) + (y - iy) * (y - iy)) * SZAR_SQR) + 0.5); int indexC01 = (int)(Math.Sqrt(((x - ix) * (x - ix) + (y - (iy + incy)) * (y - (iy + incy))) * SZAR_SQR) + 0.5); int indexC10 = (int)(Math.Sqrt(((x - (ix + incx)) * (x - (ix + incx)) + (y - iy) * (y - iy)) * SZAR_SQR) + 0.5); int indexC11 = (int)(Math.Sqrt(((x - (ix + incx)) * (x - (ix + incx)) + (y - (iy + incy)) * (y - (iy + incy))) * SZAR_SQR) + 0.5); double weigth = 0; if (c00.IsEmpty == false && indexC00 < 1024) { weigth = _bilinearArray[indexC00]; tempColor.ExtendedAlpha = c00.ExtendedAlpha * _bilinearArray[indexC00]; tempColor.ExtendedRed = c00.ExtendedRed * _bilinearArray[indexC00]; tempColor.ExtendedGreen = c00.ExtendedGreen * _bilinearArray[indexC00]; tempColor.ExtendedBlue = c00.ExtendedBlue * _bilinearArray[indexC00]; } if (c01.IsEmpty == false && indexC01 < 1024) { weigth = _bilinearArray[indexC01]; tempColor.ExtendedAlpha += c01.ExtendedAlpha * _bilinearArray[indexC01]; tempColor.ExtendedRed += c01.ExtendedRed * _bilinearArray[indexC01]; tempColor.ExtendedGreen += c01.ExtendedGreen * _bilinearArray[indexC01]; tempColor.ExtendedBlue += c01.ExtendedBlue * _bilinearArray[indexC01]; } if (c10.IsEmpty == false && indexC10 < 1024) { weigth = _bilinearArray[indexC10]; tempColor.ExtendedAlpha += c10.ExtendedAlpha * _bilinearArray[indexC10]; tempColor.ExtendedRed += c10.ExtendedRed * _bilinearArray[indexC10]; tempColor.ExtendedGreen += c10.ExtendedGreen * _bilinearArray[indexC10]; tempColor.ExtendedBlue += c10.ExtendedBlue * _bilinearArray[indexC10]; } if (c11.IsEmpty == false && indexC11 < 1024) { weigth = _bilinearArray[indexC11]; tempColor.ExtendedAlpha += c11.ExtendedAlpha * _bilinearArray[indexC11]; tempColor.ExtendedRed += c11.ExtendedRed * _bilinearArray[indexC11]; tempColor.ExtendedGreen += c11.ExtendedGreen * _bilinearArray[indexC11]; tempColor.ExtendedBlue += c11.ExtendedBlue * _bilinearArray[indexC11]; } if (tempColor.IsEmpty == false) { tempColor.ExtendedAlpha /= weigth; tempColor.ExtendedRed /= weigth; tempColor.ExtendedGreen /= weigth; tempColor.ExtendedBlue /= weigth; retVal = tempColor; } } else { int indexX = (int)((x - ix) * SZAR); int indexY = (int)((y - iy) * SZAR); double v0 = c00.ExtendedAlpha * _bilinearArray[indexX] + c10.ExtendedAlpha * (1.0 - _bilinearArray[indexX]); double v1 = c01.ExtendedAlpha * _bilinearArray[indexX] + c11.ExtendedAlpha * (1.0 - _bilinearArray[indexX]); retVal.ExtendedAlpha = (v0 * _bilinearArray[indexY] + v1 * (1.0 - _bilinearArray[indexY])); v0 = c00.ExtendedRed * _bilinearArray[indexX] + c10.ExtendedRed * (1.0 - _bilinearArray[indexX]); v1 = c01.ExtendedRed * _bilinearArray[indexX] + c11.ExtendedRed * (1.0 - _bilinearArray[indexX]); retVal.ExtendedRed = (v0 * _bilinearArray[indexY] + v1 * (1.0 - _bilinearArray[indexY])); v0 = c00.ExtendedGreen * _bilinearArray[indexX] + c10.ExtendedGreen * (1.0 - _bilinearArray[indexX]); v1 = c01.ExtendedGreen * _bilinearArray[indexX] + c11.ExtendedGreen * (1.0 - _bilinearArray[indexX]); retVal.ExtendedGreen = (v0 * _bilinearArray[indexY] + v1 * (1.0 - _bilinearArray[indexY])); v0 = c00.ExtendedBlue * _bilinearArray[indexX] + c10.ExtendedBlue * (1.0 - _bilinearArray[indexX]); v1 = c01.ExtendedBlue * _bilinearArray[indexX] + c11.ExtendedBlue * (1.0 - _bilinearArray[indexX]); retVal.ExtendedBlue = (v0 * _bilinearArray[indexY] + v1 * (1.0 - _bilinearArray[indexY])); } } else { // Out of bound of the original image, fill with IColor.Empty or the unassignedColor passed in if (unassignedColor == null) { retVal = (IColor)imageSource[0, 0].Clone(); retVal.IsEmpty = true; } else { retVal = (IColor)unassignedColor.Clone(); } } return(retVal); }