private static IntPtr Allocate(long bytes, bool allowRetry) { IntPtr block; try { if (bytes >= largeBlockThreshold) { block = PlatformMemory.AllocateLarge((ulong)bytes); } else { block = PlatformMemory.Allocate((ulong)bytes); } } catch (OutOfMemoryException) { if (allowRetry) { PixelUtils.GCFullCollect(); return(Allocate(bytes, false)); } else { throw; } } return(block); }
public override void BeforeRender() { PointF vec = new PointF(EndPoint.X - StartPoint.X, EndPoint.Y - StartPoint.Y); float mag = PixelUtils.Magnitude(vec); if (EndPoint.X == StartPoint.X) { _dtdx = 0; } else { _dtdx = vec.X / (mag * mag); } if (EndPoint.Y == StartPoint.Y) { _dtdy = 0; } else { _dtdy = vec.Y / (mag * mag); } base.BeforeRender(); }
internal static string ErrorMessage( int sourceWidth, int sourceHeight, PixelFormat sourcePixelFormat, int destWidth, int destHeight, PixelFormat destPixelFormat, ScaleFlag flags) => string.Format("Impossible to create scale context for the conversion fmt:{0} s:{1}x{2} -> fmt:{3} s:{4}x{5} (sws_flags: {6})", PixelUtils.GetPixelFormatName(sourcePixelFormat), sourceWidth, sourceHeight, PixelUtils.GetPixelFormatName(destPixelFormat), destWidth, destHeight, flags);
/// <summary> /// Smoothly blends between two colors. /// </summary> public static ColorBgra Blend(ColorBgra ca, ColorBgra cb, byte cbAlpha) { uint caA = (uint)PixelUtils.FastScaleByteByByte((byte)(255 - cbAlpha), ca.A); uint cbA = (uint)PixelUtils.FastScaleByteByByte(cbAlpha, cb.A); uint cbAT = caA + cbA; uint r; uint g; uint b; if (cbAT == 0) { r = 0; g = 0; b = 0; } else { r = ((ca.R * caA) + (cb.R * cbA)) / cbAT; g = ((ca.G * caA) + (cb.G * cbA)) / cbAT; b = ((ca.B * caA) + (cb.B * cbA)) / cbAT; } return(ColorBgra.FromBgra((byte)b, (byte)g, (byte)r, (byte)cbAT)); }
public ColorBgra Apply(float r, float g, float b) { ColorBgra ret = new ColorBgra(); float[] input = new float[] { b, g, r }; for (int i = 0; i < 3; i++) { float v = (input[i] - colorInLow[i]); if (v < 0) { ret[i] = colorOutLow[i]; } else if (v + colorInLow[i] >= colorInHigh[i]) { ret[i] = colorOutHigh[i]; } else { ret[i] = (byte)PixelUtils.Clamp( colorOutLow[i] + (colorOutHigh[i] - colorOutLow[i]) * Math.Pow(v / (colorInHigh[i] - colorInLow[i]), gamma[i]), 0.0f, 255.0f); } } return(ret); }
public override ColorBgra Apply(ColorBgra color) { //adjust saturation byte intensity = color.GetIntensityByte(); color.R = PixelUtils.ClampToByte((intensity * 1024 + (color.R - intensity) * satFactor) >> 10); color.G = PixelUtils.ClampToByte((intensity * 1024 + (color.G - intensity) * satFactor) >> 10); color.B = PixelUtils.ClampToByte((intensity * 1024 + (color.B - intensity) * satFactor) >> 10); HsvColor hsvColor = HsvColor.FromColor(color.ToColor()); int hue = hsvColor.Hue; hue += hueDelta; while (hue < 0) { hue += 360; } while (hue > 360) { hue -= 360; } hsvColor.Hue = hue; ColorBgra newColor = ColorBgra.FromColor(hsvColor.ToColor()); newColor = blendOp.Apply(newColor); newColor.A = color.A; return(newColor); }
/// <summary> /// Creates a new ColorBgra instance with the given color and alpha values. /// </summary> public static ColorBgra FromBgraClamped(float b, float g, float r, float a) { return(FromBgra( PixelUtils.ClampToByte(b), PixelUtils.ClampToByte(g), PixelUtils.ClampToByte(r), PixelUtils.ClampToByte(a))); }
/// <summary> /// Creates a new ColorBgra instance with the given color and alpha values. /// </summary> public static ColorBgra FromBgraClamped(int b, int g, int r, int a) { return(FromBgra( PixelUtils.ClampToByte(b), PixelUtils.ClampToByte(g), PixelUtils.ClampToByte(r), PixelUtils.ClampToByte(a))); }
/// <inheritdoc/> public byte[] Decompress(byte[] blockData, int width, int height) { IBlock self = this; byte[] alpha = new byte[8]; var colors = new ImageSharp.PixelFormats.Rgb24[4]; return(Helper.InMemoryDecode <Dxt5>(blockData, width, height, (stream, data, streamIndex, dataIndex, stride) => { streamIndex = Bc5.ExtractGradient(alpha, blockData, streamIndex); ulong alphaCodes = blockData[streamIndex++]; alphaCodes |= (ulong)blockData[streamIndex++] << 8; alphaCodes |= (ulong)blockData[streamIndex++] << 16; alphaCodes |= (ulong)blockData[streamIndex++] << 24; alphaCodes |= (ulong)blockData[streamIndex++] << 32; alphaCodes |= (ulong)blockData[streamIndex++] << 40; // Colors are stored in a pair of 16 bits. ushort color0 = blockData[streamIndex++]; color0 |= (ushort)(blockData[streamIndex++] << 8); ushort color1 = blockData[streamIndex++]; color1 |= (ushort)(blockData[streamIndex++] << 8); // Extract R5G6B5. PixelUtils.ExtractR5G6B5(color0, ref colors[0]); PixelUtils.ExtractR5G6B5(color1, ref colors[1]); colors[2].R = (byte)(((2 * colors[0].R) + colors[1].R) / 3); colors[2].G = (byte)(((2 * colors[0].G) + colors[1].G) / 3); colors[2].B = (byte)(((2 * colors[0].B) + colors[1].B) / 3); colors[3].R = (byte)((colors[0].R + (2 * colors[1].R)) / 3); colors[3].G = (byte)((colors[0].G + (2 * colors[1].G)) / 3); colors[3].B = (byte)((colors[0].B + (2 * colors[1].B)) / 3); for (int alphaShift = 0; alphaShift < 48; alphaShift += 12) { byte rowVal = blockData[streamIndex++]; for (int j = 0; j < 4; j++) { // 3 bits determine alpha index to use. byte alphaIndex = (byte)((alphaCodes >> (alphaShift + (3 * j))) & 0x07); ImageSharp.PixelFormats.Rgb24 col = colors[(rowVal >> (j * 2)) & 0x03]; data[dataIndex++] = col.R; data[dataIndex++] = col.G; data[dataIndex++] = col.B; data[dataIndex++] = alpha[alphaIndex]; } dataIndex += self.PixelDepthBytes * (stride - self.DivSize); } return streamIndex; })); }
public void SetGamma(int index, float val) { if (index < 0 || index >= 3) { throw new ArgumentOutOfRangeException("index", index, "Index must be between 0 and 2"); } gamma[index] = PixelUtils.Clamp(val, 0.1f, 10.0f); UpdateLookupTable(); }
public Pixel Map(ISourceData data) { Pixel p = data.GetPixel(0, 0); int r = PixelUtils.Clamp((int)((255.0 * Math.Pow(p.R / 255.0, 1.0 / _gammaCorrection)) + 0.5), 255, 0); int g = PixelUtils.Clamp((int)((255.0 * Math.Pow(p.G / 255.0, 1.0 / _gammaCorrection)) + 0.5), 255, 0); int b = PixelUtils.Clamp((int)((255.0 * Math.Pow(p.B / 255.0, 1.0 / _gammaCorrection)) + 0.5), 255, 0); int a = PixelUtils.Clamp((int)((255.0 * Math.Pow(p.A / 255.0, 1.0 / _gammaCorrection)) + 0.5), 255, 0); return(new Pixel(r, g, b, a)); }
/// <summary> /// Provides the interface for merging two bitmaps together. /// </summary> /// <param name="bitmapA">The first bitmap for the merge</param> /// <param name="bitmapB">The second bitmap for the merge</param> /// <returns>The resulting bitmap</returns> public Bitmap Merge(Bitmap bitmapA, Bitmap bitmapB) { // Build the storage for the resulting bitmap PixelFormat pixelFormat = bitmapA.PixelFormat; Bitmap resultingBitmap = new Bitmap(bitmapA.Width, bitmapA.Height, pixelFormat); // Perform the merge for (int w = 0; w < bitmapA.Width; w++) { for (int h = 0; h < bitmapA.Height; h++) { Color pixelA = bitmapA.GetPixel(w, h); Color pixelB = bitmapB.GetPixel(w, h); if (!PixelUtils.ColorWithinThresholdOfWhite(pixelA, WhiteThreshold)) { // Set to the average of the two pixels if (PixelUtils.ColorsAreClose(pixelA, pixelB, LikenessThreshold)) { resultingBitmap.SetPixel(w, h, pixelA); } else { int brightnessA = PixelUtils.GetBrightness(pixelA); int brightnessB = PixelUtils.GetBrightness(pixelB); Color blendedPixel; // Determine which order to blend the pixels in if (brightnessA > brightnessB) { blendedPixel = BlendPixels(pixelB, pixelA, BlendAmount); } else { blendedPixel = BlendPixels(pixelA, pixelB, BlendAmount); } resultingBitmap.SetPixel(w, h, blendedPixel); } } else if (!PixelUtils.ColorWithinThresholdOfWhite(pixelA, WhiteThreshold)) { // PixelA has valid data, copy it resultingBitmap.SetPixel(w, h, pixelA); } else { // Just set this pixel to the value of pixelB resultingBitmap.SetPixel(w, h, pixelB); } } } return(resultingBitmap); }
protected override void InverseTransform(ref TransformData data) { double x = data.X; double y = data.Y; // NOTE: when x and y are zero, this will divide by zero and return NaN double invertDistance = PixelUtils.Lerp(1d, DefaultRadius2 / ((x * x) + (y * y)), amount); data.X = x * invertDistance; data.Y = y * invertDistance; }
/// <summary> /// Linearly interpolates between two color values. /// </summary> /// <param name="from">The color value that represents 0 on the lerp number line.</param> /// <param name="to">The color value that represents 1 on the lerp number line.</param> /// <param name="frac">A value in the range [0, 1].</param> /// <remarks> /// This method does a simple lerp on each color value and on the alpha channel. It does /// not properly take into account the alpha channel's effect on color blending. /// </remarks> public static ColorBgra Lerp(ColorBgra from, ColorBgra to, double frac) { ColorBgra ret = new ColorBgra(); ret.B = (byte)PixelUtils.ClampToByte(PixelUtils.Lerp(from.B, to.B, frac)); ret.G = (byte)PixelUtils.ClampToByte(PixelUtils.Lerp(from.G, to.G, frac)); ret.R = (byte)PixelUtils.ClampToByte(PixelUtils.Lerp(from.R, to.R, frac)); ret.A = (byte)PixelUtils.ClampToByte(PixelUtils.Lerp(from.A, to.A, frac)); return(ret); }
public override float BoundLerp(float t) { if (t > 1) { t -= 2; } else if (t < -1) { t += 2; } return(PixelUtils.Clamp(Math.Abs(t), 0, 1)); }
public override void BeforeRender() { float distanceScale = PixelUtils.Distance(this.StartPoint, this.EndPoint); if (distanceScale == 0) { _invDistanceScale = 0; } else { _invDistanceScale = 1.0f / distanceScale; } base.BeforeRender(); }
public void Apply(Surface surface, RectangleF[] roiF, int startIndex, int length) { Rectangle regionBounds = Rectangle.Truncate(PixelUtils.GetRegionBounds(roiF, startIndex, length)); if (regionBounds != Rectangle.Intersect(surface.Bounds, regionBounds)) { throw new ArgumentOutOfRangeException("roiF", "Region is out of bounds"); } unsafe { for (int x = startIndex; x < startIndex + length; ++x) { ApplyRectangle(surface, Rectangle.Truncate(roiF[x])); } } }
/// <summary> /// Determines if a tile is complete. /// </summary> /// <returns>True if complete, else false</returns> public bool IsComplete() { Bitmap tileImage = GetBitmap(); int width = tileImage.Width; int height = tileImage.Height; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Color currentPixel = tileImage.GetPixel(x, y); if (PixelUtils.ColorWithinThresholdOfWhite(currentPixel, 5)) return false; } } return true; }
public static Level AutoFromLoMdHi(ColorBgra lo, ColorBgra md, ColorBgra hi) { float[] gamma = new float[3]; for (int i = 0; i < 3; i++) { if (lo[i] < md[i] && md[i] < hi[i]) { gamma[i] = (float)PixelUtils.Clamp(Math.Log(0.5, (float)(md[i] - lo[i]) / (float)(hi[i] - lo[i])), 0.1, 10.0); } else { gamma[i] = 1.0f; } } return(new Level(lo, hi, gamma, ColorBgra.FromColor(Color.Black), ColorBgra.FromColor(Color.White))); }
public void SetParameters(double angle, int distance, bool centered) { this.angle = angle; this.distance = distance; this.centered = centered; float start_x = 0, start_y = 0; double theta = ((double)(angle + 180) * 2 * Math.PI) / 360.0; double alpha = (double)distance; float end_x = (float)(alpha * Math.Cos(theta)); float end_y = (float)(alpha * Math.Sin(theta)); if (centered) { start_x = -end_x / 2.0f; start_y = -end_y / 2.0f; end_x /= 2.0f; end_y /= 2.0f; } this.points = new PointF[((1 + distance) * 3) / 2]; if (this.points.Length == 1) { this.points[0] = new PointF(0, 0); } else { for (int i = 0; i < this.points.Length; ++i) { float frac = (float)i / (float)(this.points.Length - 1); this.points[i] = PixelUtils.Lerp( new PointF(start_x, start_y), new PointF(end_x, end_y), frac); } } }
public Pixel Map(ISourceData data) { double factor = _amount; Pixel[,] pixelMatrix = PixelUtils.GetPixelMatrix(data, 1); if (factor > 10) { factor = 10; } if (factor <= 0) { factor = 0.1d; } bias = 2.0; int red = 0; int green = 0; int blue = 0; int dimLength = pixelMatrix.GetLength(0); for (int x = 0; x < dimLength; x++) { for (int y = 0; y < dimLength; y++) { red += pixelMatrix[x, y].R * filterMatrix[x, y]; green += pixelMatrix[x, y].G * filterMatrix[x, y]; blue += pixelMatrix[x, y].B * filterMatrix[x, y]; } } int r = PixelUtils.Clamp((int)((factor * red) + bias), 255, 0); int g = PixelUtils.Clamp((int)((factor * green) + bias), 255, 0); int b = PixelUtils.Clamp((int)((factor * blue) + bias), 255, 0); return(new Pixel(r, g, b, pixelMatrix[1, 1].A)); }
private static double Noise(byte ix, byte iy, double x, double y, byte seed) { double u = Fade(x); double v = Fade(y); int a = permuteLookup[ix + seed] + iy; int aa = permuteLookup[a]; int ab = permuteLookup[a + 1]; int b = permuteLookup[ix + 1 + seed] + iy; int ba = permuteLookup[b]; int bb = permuteLookup[b + 1]; double gradAA = Grad(permuteLookup[aa], x, y); double gradBA = Grad(permuteLookup[ba], x - 1, y); double edge1 = PixelUtils.Lerp(gradAA, gradBA, u); double gradAB = Grad(permuteLookup[ab], x, y - 1); double gradBB = Grad(permuteLookup[bb], x - 1, y - 1); double edge2 = PixelUtils.Lerp(gradAB, gradBB, u); return(PixelUtils.Lerp(edge1, edge2, v)); }
public void SetParameters(double angle, int distance, bool centered) { this.angle = angle; this.distance = distance; this.centered = centered; PointF start = new PointF(0, 0); double theta = ((double)(angle + 180) * 2 * Math.PI) / 360.0; double alpha = (double)distance; double x = alpha * Math.Cos(theta); double y = alpha * Math.Sin(theta); PointF end = new PointF((float)x, (float)(-y)); if (centered) { start.X = -end.X / 2.0f; start.Y = -end.Y / 2.0f; end.X /= 2.0f; end.Y /= 2.0f; } this.points = new PointF[((1 + distance) * 3) / 2]; if (this.points.Length == 1) { this.points[0] = new PointF(0, 0); } else { for (int i = 0; i < this.points.Length; ++i) { float frac = (float)i / (float)(this.points.Length - 1); this.points[i] = PixelUtils.Lerp(start, end, frac); } } }
private static IntPtr Allocate(int width, int height, out IntPtr handle, bool allowRetry) { IntPtr block; try { block = PlatformMemory.AllocateBitmap(width, height, out handle); } catch (OutOfMemoryException) { if (allowRetry) { PixelUtils.GCFullCollect(); return(Allocate(width, height, out handle, false)); } else { throw; } } return(block); }
public override void Render(Surface src, Surface dest, Rectangle[] rois, int startIndex, int length) { unsafe { int w = dest.Width; int h = dest.Height; double invH = 1.0 / h; double invZoom = 1.0 / _zoom; double invQuality = 1.0 / _quality; double aspect = (double)h / (double)w; int count = _quality * _quality + 1; double invCount = 1.0 / (double)count; for (int ri = startIndex; ri < startIndex + length; ++ri) { Rectangle rect = rois[ri]; for (int y = rect.Top; y < rect.Bottom; y++) { ColorBgra *dstPtr = dest.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; x++) { int r = 0; int g = 0; int b = 0; int a = 0; for (double i = 0; i < count; i++) { double u = (2.0 * x - w + (i * invCount)) * invH; double v = (2.0 * y - h + ((i * invQuality) % 1)) * invH; double radius = Math.Sqrt((u * u) + (v * v)); double radiusP = radius; double theta = Math.Atan2(v, u); double thetaP = theta + _angleTheta; double uP = radiusP * Math.Cos(thetaP); double vP = radiusP * Math.Sin(thetaP); double jX = (uP - vP * aspect) * invZoom; double jY = (vP + uP * aspect) * invZoom; double j = Julia(jX, jY, JR, JI); double c = _factor * j; b += PixelUtils.ClampToByte(c - 768); g += PixelUtils.ClampToByte(c - 512); r += PixelUtils.ClampToByte(c - 256); a += PixelUtils.ClampToByte(c - 0); } *dstPtr = ColorBgra.FromBgra( PixelUtils.ClampToByte(b / count), PixelUtils.ClampToByte(g / count), PixelUtils.ClampToByte(r / count), PixelUtils.ClampToByte(a / count)); ++dstPtr; } } } } }
public override float BoundLerp(float t) { return(PixelUtils.Clamp(t, 0, 1)); }
public override float BoundLerp(float t) { return(PixelUtils.Clamp(Math.Abs(t), 0, 1)); }
public override void Render(Surface src, Surface dst, Rectangle[] rois, int startIndex, int length) { unsafe { // Glow backgound glowRenderer.Render(src, dst, rois, startIndex, length); // Create black outlines by finding the edges of objects for (int i = startIndex; i < startIndex + length; ++i) { Rectangle roi = rois[i]; for (int y = roi.Top; y < roi.Bottom; ++y) { int top = y - radius; int bottom = y + radius + 1; if (top < 0) { top = 0; } if (bottom > dst.Height) { bottom = dst.Height; } ColorBgra *srcPtr = src.GetPointAddress(roi.X, y); ColorBgra *dstPtr = src.GetPointAddress(roi.X, y); for (int x = roi.Left; x < roi.Right; ++x) { int left = x - radius; int right = x + radius + 1; if (left < 0) { left = 0; } if (right > dst.Width) { right = dst.Width; } int r = 0; int g = 0; int b = 0; for (int v = top; v < bottom; v++) { ColorBgra *pRow = src.GetRowAddress(v); int j = v - y + radius; for (int u = left; u < right; u++) { int i1 = u - x + radius; int w = conv[j][i1]; ColorBgra *pRef = pRow + u; r += pRef->R * w; g += pRef->G * w; b += pRef->B * w; } } ColorBgra topLayer = ColorBgra.FromBgr( PixelUtils.ClampToByte(b), PixelUtils.ClampToByte(g), PixelUtils.ClampToByte(r)); // Desaturate topLayer = this.desaturateOp.Apply(topLayer); // Adjust Brightness and Contrast if (topLayer.R > (this.inkOutline * 255 / 100)) { topLayer = ColorBgra.FromBgra(255, 255, 255, topLayer.A); } else { topLayer = ColorBgra.FromBgra(0, 0, 0, topLayer.A); } // Change Blend Mode to Darken ColorBgra myPixel = this.darkenOp.Apply(topLayer, *dstPtr); * dstPtr = myPixel; ++srcPtr; ++dstPtr; } } } } }
public void SetParameters(int brightness, int contrast) { this.brightness = brightness; this.contrast = contrast; if (this.contrast < 0) { this.multiply = this.contrast + 100; this.divide = 100; } else if (this.contrast > 0) { this.multiply = 100; this.divide = 100 - this.contrast; } else { this.multiply = 1; this.divide = 1; } if (this.rgbTable == null) { this.rgbTable = new byte[65536]; } if (this.divide == 0) { for (int intensity = 0; intensity < 256; ++intensity) { if (intensity + this.brightness < 128) { this.rgbTable[intensity] = 0; } else { this.rgbTable[intensity] = 255; } } } else if (this.divide == 100) { for (int intensity = 0; intensity < 256; ++intensity) { int shift = (intensity - 127) * this.multiply / this.divide + 127 - intensity + this.brightness; for (int col = 0; col < 256; ++col) { int index = (intensity * 256) + col; this.rgbTable[index] = PixelUtils.ClampToByte(col + shift); } } } else { for (int intensity = 0; intensity < 256; ++intensity) { int shift = (intensity - 127 + this.brightness) * this.multiply / this.divide + 127 - intensity; for (int col = 0; col < 256; ++col) { int index = (intensity * 256) + col; this.rgbTable[index] = PixelUtils.ClampToByte(col + shift); } } } }
public override void Render(Surface src, Surface dst, Rectangle[] rois, int startIndex, int length) { ColorBgra colTransparent = ColorBgra.Transparent; unsafe { int aaSampleCount = quality * quality; PointF *aaPoints = stackalloc PointF[aaSampleCount]; PixelUtils.GetRgssOffsets(aaPoints, aaSampleCount, quality); ColorBgra *samples = stackalloc ColorBgra[aaSampleCount]; TransformData td; for (int n = startIndex; n < startIndex + length; ++n) { Rectangle rect = rois[n]; for (int y = rect.Top; y < rect.Bottom; y++) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); double relativeY = y - this.yCenterOffset; for (int x = rect.Left; x < rect.Right; x++) { double relativeX = x - this.xCenterOffset; int sampleCount = 0; for (int p = 0; p < aaSampleCount; ++p) { td.X = relativeX + aaPoints[p].X; td.Y = relativeY - aaPoints[p].Y; InverseTransform(ref td); float sampleX = (float)(td.X + this.xCenterOffset); float sampleY = (float)(td.Y + this.yCenterOffset); ColorBgra sample = colPrimary; if (IsOnSurface(src, sampleX, sampleY)) { sample = src.GetBilinearSample(sampleX, sampleY); } else { switch (this.edgeBehavior) { case WarpEdgeBehavior.Clamp: sample = src.GetBilinearSampleClamped(sampleX, sampleY); break; case WarpEdgeBehavior.Wrap: sample = src.GetBilinearSampleWrapped(sampleX, sampleY); break; case WarpEdgeBehavior.Reflect: sample = src.GetBilinearSampleClamped( ReflectCoord(sampleX, src.Width), ReflectCoord(sampleY, src.Height)); break; case WarpEdgeBehavior.Primary: sample = colPrimary; break; case WarpEdgeBehavior.Secondary: sample = colSecondary; break; case WarpEdgeBehavior.Transparent: sample = colTransparent; break; case WarpEdgeBehavior.Original: sample = src[x, y]; break; default: break; } } samples[sampleCount] = sample; ++sampleCount; } *dstPtr = ColorBgra.Blend(samples, sampleCount); ++dstPtr; } } } } }