public unsafe CairoSurfaceWrapper (Cairo.ImageSurface surface) { this.surface = surface; this.data_ptr = (ColorBgra*)surface.DataPtr; height = surface.Height; width = surface.Width; }
public BitVector2DSurfaceAdapter(ImageSurface surface) { if (surface == null) throw new ArgumentNullException ("surface"); this.surface = surface; src_width = surface.Width; src_height = surface.Height; src_data_ptr = (ColorBgra*)surface.DataPtr; }
public unsafe override void BeginUpdate () { Interlocked.Increment (ref lock_count); if (lock_count > 1) return; bitmap_data = surface.LockBits (new System.Drawing.Rectangle (0, 0, surface.Width, surface.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); data_ptr = (ColorBgra*)bitmap_data.Scan0; }
internal static unsafe void Rotate90CW(ref Surface surface) { Surface temp = null; try { int newWidth = surface.Height; int newHeight = surface.Width; temp = new Surface(newWidth, newHeight); int lastColumn = newWidth - 1; for (int y = 0; y < newWidth; y++) { ColorBgra *srcPtr = surface.GetRowPointerUnchecked(y); ColorBgra *dstPtr = temp.GetPointPointerUnchecked(lastColumn - y, 0); for (int x = 0; x < newHeight; x++) { *dstPtr = *srcPtr; srcPtr++; dstPtr += newWidth; } } surface.Dispose(); surface = temp; temp = null; } finally { temp?.Dispose(); } }
/////////////////////////////////////////////////////////////////////////////// // // The color-conversion formulas come from the Colour Space Conversions FAQ: // http://www.poynton.com/PDFs/coloureq.pdf // // RGB --> CMYK CMYK --> RGB // --------------------------------------- -------------------------------------------- // Black = minimum(1-Red,1-Green,1-Blue) Red = 1-minimum(1,Cyan*(1-Black)+Black) // Cyan = (1-Red-Black)/(1-Black) Green = 1-minimum(1,Magenta*(1-Black)+Black) // Magenta = (1-Green-Black)/(1-Black) Blue = 1-minimum(1,Yellow*(1-Black)+Black) // Yellow = (1-Blue-Black)/(1-Black) // /////////////////////////////////////////////////////////////////////////////// private static unsafe void SetPDNRowCmyk(ColorBgra *pDest, ColorBgra *pDestEnd, int idxSrc, DecodeContext context) { while (pDest < pDestEnd) { // CMYK values are stored as complements, presumably to allow for some // measure of compatibility with RGB-only applications. var C = 255 - context.Channels[0].ImageData[idxSrc]; var M = 255 - context.Channels[1].ImageData[idxSrc]; var Y = 255 - context.Channels[2].ImageData[idxSrc]; var K = 255 - context.Channels[3].ImageData[idxSrc]; int nRed = 255 - Math.Min(255, C * (255 - K) / 255 + K); int nGreen = 255 - Math.Min(255, M * (255 - K) / 255 + K); int nBlue = 255 - Math.Min(255, Y * (255 - K) / 255 + K); pDest->R = (byte)nRed; pDest->G = (byte)nGreen; pDest->B = (byte)nBlue; pDest++; idxSrc += context.ByteDepth; } }
public void Apply(Surface dst, Surface lhs, Surface rhs) { if (dst.Size != lhs.Size) { throw new ArgumentException("dst.Size != lhs.Size"); } if (lhs.Size != rhs.Size) { throw new ArgumentException("lhs.Size != rhs.Size"); } unsafe { for (int y = 0; y < dst.Height; ++y) { ColorBgra *dstPtr = dst.GetRowAddressUnchecked(y); ColorBgra *lhsPtr = lhs.GetRowAddressUnchecked(y); ColorBgra *rhsPtr = lhs.GetRowAddressUnchecked(y); Apply(dstPtr, lhsPtr, rhsPtr, dst.Width); } } }
/// <summary> /// Check for non-transparent pixels in a row, or portion of a row. /// Expands the size of the image rectangle if any were found. /// </summary> /// <returns>True if non-transparent pixels were found, false otherwise.</returns> unsafe private static bool ExpandImageRectangle(Surface surface, int y, int xStart, int xEnd, ref Util.RectanglePosition rectPos) { bool fPixelFound = false; ColorBgra *rowStart = surface.GetRowAddress(y); ColorBgra *pixel = rowStart + xStart; for (int x = xStart; x < xEnd; x++) { if (pixel->A > 0) { // Expand the rectangle to include the specified point. if (x < rectPos.Left) { rectPos.Left = x; } if (x > rectPos.Right) { rectPos.Right = x; } if (y < rectPos.Top) { rectPos.Top = y; } if (y > rectPos.Bottom) { rectPos.Bottom = y; } fPixelFound = true; } pixel++; } return(fPixelFound); }
/// <summary> /// Add a given color value to the octree /// </summary> /// <param name="pixel"></param> public void AddColor(ColorBgra *pixel) { // Check if this request is for the same color as the last if (this._previousColor == pixel->Bgra) { // If so, check if I have a previous node setup. This will only ocurr if the first color in the image // happens to be black, with an alpha component of zero. if (null == this._previousNode) { this._previousColor = pixel->Bgra; this._root.AddColor(pixel, this._maxColorBits, 0, this); } else { // Just update the previous node this._previousNode.Increment(pixel); } } else { this._previousColor = pixel->Bgra; this._root.AddColor(pixel, this._maxColorBits, 0, this); } }
public unsafe override void Apply(ColorBgra *dst, ColorBgra *lhs, ColorBgra *rhs, int length) { PlatformMemory.Copy(dst, rhs, (ulong)length * (ulong)ColorBgra.SizeOf); }
public unsafe override void Render(EffectConfigToken properties, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length) { TwoAmountsConfigToken token = (TwoAmountsConfigToken)properties; int brushSize = token.Amount1; byte smoothness = (byte)token.Amount2; Surface src = srcArgs.Surface; Surface dst = dstArgs.Surface; int width = src.Width; int height = src.Height; int arrayLens = 1 + smoothness; int* intensityCount = stackalloc int[arrayLens]; uint* avgRed = stackalloc uint[arrayLens]; uint* avgGreen = stackalloc uint[arrayLens]; uint* avgBlue = stackalloc uint[arrayLens]; uint* avgAlpha = stackalloc uint[arrayLens]; byte maxIntensity = smoothness; for (int r = startIndex; r < startIndex + length; ++r) { Rectangle rect = rois[r]; int rectTop = rect.Top; int rectBottom = rect.Bottom; int rectLeft = rect.Left; int rectRight = rect.Right; for (int y = rectTop; y < rectBottom; ++y) { ColorBgra *dstPtr = dst.GetPointAddress(rect.Left, y); int top = y - brushSize; int bottom = y + brushSize + 1; if (top < 0) { top = 0; } if (bottom > height) { bottom = height; } for (int x = rectLeft; x < rectRight; ++x) { int left = x - brushSize; int right = x + brushSize + 1; if (left < 0) { left = 0; } if (right > width) { right = width; } for (int i = 0; i < arrayLens; ++i) { intensityCount[i] = 0; avgRed[i] = 0; avgGreen[i] = 0; avgBlue[i] = 0; avgAlpha[i] = 0; } int numInt = 0; for (int j = top; j < bottom; ++j) { ColorBgra *srcPtr = src.GetPointAddress(left, j); for (int i = left; i < right; ++i) { byte intensity = (byte)((srcPtr->GetIntensityByte() * maxIntensity) / 255); ++intensityCount[intensity]; ++numInt; avgRed[intensity] += srcPtr->R; avgGreen[intensity] += srcPtr->G; avgBlue[intensity] += srcPtr->B; avgAlpha[intensity] += srcPtr->A; ++srcPtr; } } byte chosenIntensity = 0; int maxInstance = 0; for (int i = 0; i <= maxIntensity; ++i) { if (intensityCount[i] > maxInstance) { chosenIntensity = (byte)i; maxInstance = intensityCount[i]; } } byte R = (byte)(avgRed[chosenIntensity] / maxInstance); byte G = (byte)(avgGreen[chosenIntensity] / maxInstance); byte B = (byte)(avgBlue[chosenIntensity] / maxInstance); byte A = (byte)(avgAlpha[chosenIntensity] / maxInstance); *dstPtr = ColorBgra.FromBgra(B, G, R, A); ++dstPtr; } } } }
public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois) { float twist = Data.Amount; float hw = dst.Width / 2.0f; float hh = dst.Height / 2.0f; float maxrad = Math.Min(hw, hh); twist = twist * twist * Math.Sign(twist); int aaLevel = Data.Antialias; int aaSamples = aaLevel * aaLevel + 1; PointD *aaPoints = stackalloc PointD[aaSamples]; for (int i = 0; i < aaSamples; ++i) { PointD pt = new PointD( ((i * aaLevel) / (float)aaSamples), i / (float)aaSamples); pt.X -= (int)pt.X; aaPoints[i] = pt; } int src_width = src.Width; ColorBgra *src_data_ptr = (ColorBgra *)src.DataPtr; foreach (var rect in rois) { for (int y = rect.Top; y < rect.Bottom; y++) { float j = y - hh; ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); ColorBgra *srcPtr = src.GetPointAddressUnchecked(src_data_ptr, src_width, rect.Left, y); for (int x = rect.Left; x < rect.Right; x++) { float i = x - hw; if (i * i + j * j > (maxrad + 1) * (maxrad + 1)) { *dstPtr = *srcPtr; } else { int b = 0; int g = 0; int r = 0; int a = 0; for (int p = 0; p < aaSamples; ++p) { float u = i + (float)aaPoints[p].X; float v = j + (float)aaPoints[p].Y; double rad = Math.Sqrt(u * u + v * v); double theta = Math.Atan2(v, u); double t = 1 - rad / maxrad; t = (t < 0) ? 0 : (t * t * t); theta += (t * twist) / 100; ColorBgra sample = src.GetPointUnchecked(src_data_ptr, src_width, (int)(hw + (float)(rad * Math.Cos(theta))), (int)(hh + (float)(rad * Math.Sin(theta)))); b += sample.B; g += sample.G; r += sample.R; a += sample.A; } *dstPtr = ColorBgra.FromBgra( (byte)(b / aaSamples), (byte)(g / aaSamples), (byte)(r / aaSamples), (byte)(a / aaSamples)); } ++dstPtr; ++srcPtr; } } } }
protected override unsafe Gdk.Rectangle OnMouseMove(Context g, Color strokeColor, ImageSurface surface, int x, int y, int lastX, int lastY) { int rad = (int)(g.LineWidth / 2.0 + 0.5); if (rad < 2) { rad = 2; } Gdk.Rectangle surface_rect = new Gdk.Rectangle(0, 0, surface.Width, surface.Height); Gdk.Rectangle brush_rect = new Gdk.Rectangle(x - rad, y - rad, 2 * rad, 2 * rad); Gdk.Rectangle dest_rect = Gdk.Rectangle.Intersect(surface_rect, brush_rect); if ((dest_rect.Width > 1) && (dest_rect.Height > 1)) { //Allow Clipping through a temporary surface ImageSurface tmp_surface = new ImageSurface(Format.Argb32, dest_rect.Width, dest_rect.Height); using (Context g2 = new Context(tmp_surface)) { g2.Operator = Operator.Source; g2.SetSourceSurface(surface, -dest_rect.Left, -dest_rect.Top); g2.Rectangle(new Rectangle(0, 0, dest_rect.Width, dest_rect.Height)); g2.Fill(); } //Flush to make sure all drawing operations are finished tmp_surface.Flush(); ColorBgra[,] tmp = new ColorBgra[dest_rect.Width, dest_rect.Height]; for (int iy = 0; iy < dest_rect.Height; iy++) { ColorBgra *srcRowPtr = tmp_surface.GetPointAddressUnchecked(0, iy); for (int ix = 0; ix < dest_rect.Width; ix++) { tmp[ix, iy] = (*srcRowPtr).ToStraightAlpha(); srcRowPtr++; } } for (int iy = 1; iy < dest_rect.Height - 1; iy++) { ColorBgra *dstRowPtr = tmp_surface.GetPointAddressUnchecked(1, iy); int dy = dest_rect.Top + iy - y; for (int ix = 1; ix < dest_rect.Width - 1; ix++) { int dx = dest_rect.Left + ix - x; if ((dx * dx + dy * dy) < rad * rad) { ColorBgra col = ColorBgra.Black; col.R = (byte)((2 * tmp[ix, iy].R + tmp[ix - 1, iy].R + tmp[ix + 1, iy].R + tmp[ix, iy - 1].R + tmp[ix, iy + 1].R + 3) / 6); col.G = (byte)((2 * tmp[ix, iy].G + tmp[ix - 1, iy].G + tmp[ix + 1, iy].G + tmp[ix, iy - 1].G + tmp[ix, iy + 1].G + 3) / 6); col.B = (byte)((2 * tmp[ix, iy].B + tmp[ix - 1, iy].B + tmp[ix + 1, iy].B + tmp[ix, iy - 1].B + tmp[ix, iy + 1].B + 3) / 6); col.A = (byte)((2 * tmp[ix, iy].A + tmp[ix - 1, iy].A + tmp[ix + 1, iy].A + tmp[ix, iy - 1].A + tmp[ix, iy + 1].A + 3) / 6); *dstRowPtr = col.ToPremultipliedAlpha(); } dstRowPtr++; } } //Draw the final result on the surface g.Operator = Operator.Source; g.SetSourceSurface(tmp_surface, dest_rect.Left, dest_rect.Top); g.Rectangle(new Rectangle(dest_rect.Left, dest_rect.Top, dest_rect.Width, dest_rect.Height)); g.Fill(); } return(Gdk.Rectangle.Zero); }
public unsafe override void Render(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { foreach (Gdk.Rectangle rect in rois) { for (int y = rect.Top; y <= rect.GetBottom(); y++) { ColorBgra *srcRowPtr = src.GetPointAddressUnchecked(rect.Left, y); ColorBgra *dstRowPtr = dest.GetPointAddressUnchecked(rect.Left, y); ColorBgra *dstRowEndPtr = dstRowPtr + rect.Width; int dither = y & 1; while (dstRowPtr < dstRowEndPtr) { ColorBgra col = (*srcRowPtr).ToStraightAlpha(); dither++; int r = col.R, g = col.G, b = col.B;; if ((dither & 1) == 0) { r += 2; g += 2; b += 2; if (r > 255) { r = 255; } if (g > 255) { g = 255; } if (b > 255) { b = 255; } } else { r -= 2; g -= 2; b -= 2; if (r < 0) { r = 0; } if (g < 0) { g = 0; } if (b < 0) { b = 0; } } col.R = (byte)r; col.G = (byte)g; col.B = (byte)b; *dstRowPtr = col.ToPremultipliedAlpha(); ++dstRowPtr; ++srcRowPtr; } } } }
protected unsafe override void OnMouseMove(object o, Gtk.MotionNotifyEventArgs args, Cairo.PointD point) { Document doc = PintaCore.Workspace.ActiveDocument; ColorBgra old_color; ColorBgra new_color; if (mouse_button == 1) { old_color = PintaCore.Palette.PrimaryColor.ToColorBgra(); new_color = PintaCore.Palette.SecondaryColor.ToColorBgra(); } else if (mouse_button == 3) { old_color = PintaCore.Palette.SecondaryColor.ToColorBgra(); new_color = PintaCore.Palette.PrimaryColor.ToColorBgra(); } else { last_point = point_empty; return; } int x = (int)point.X; int y = (int)point.Y; if (last_point.Equals(point_empty)) { last_point = new Point(x, y); } if (doc.Workspace.PointInCanvas(point)) { surface_modified = true; } ImageSurface surf = doc.CurrentUserLayer.Surface; ImageSurface tmp_layer = doc.ToolLayer.Surface; Gdk.Rectangle roi = GetRectangleFromPoints(last_point, new Point(x, y)); roi = PintaCore.Workspace.ClampToImageSize(roi); myTolerance = (int)(Tolerance * 256); tmp_layer.Flush(); ColorBgra *tmp_data_ptr = (ColorBgra *)tmp_layer.DataPtr; int tmp_width = tmp_layer.Width; ColorBgra *surf_data_ptr = (ColorBgra *)surf.DataPtr; int surf_width = surf.Width; // The stencil lets us know if we've already checked this // pixel, providing a nice perf boost // Maybe this should be changed to a BitVector2DSurfaceAdapter? for (int i = roi.X; i <= roi.GetRight(); i++) { for (int j = roi.Y; j <= roi.GetBottom(); j++) { if (stencil[i, j]) { continue; } if (IsColorInTolerance(new_color, surf.GetColorBgraUnchecked(surf_data_ptr, surf_width, i, j))) { *tmp_layer.GetPointAddressUnchecked(tmp_data_ptr, tmp_width, i, j) = AdjustColorDifference(new_color, old_color, surf.GetColorBgraUnchecked(surf_data_ptr, surf_width, i, j)); } stencil[i, j] = true; } } tmp_layer.MarkDirty(); using (Context g = new Context(surf)) { g.AppendPath(doc.Selection.SelectionPath); g.FillRule = FillRule.EvenOdd; g.Clip(); g.Antialias = UseAntialiasing ? Antialias.Subpixel : Antialias.None; g.MoveTo(last_point.X, last_point.Y); g.LineTo(x, y); g.LineWidth = BrushWidth; g.LineJoin = LineJoin.Round; g.LineCap = LineCap.Round; g.SetSource(tmp_layer); g.Stroke(); } doc.Workspace.Invalidate(roi); last_point = new Point(x, y); }
protected unsafe override void OnMouseDown(QueuedToolEventArgs le) { SmudgeEventArgs e = le as SmudgeEventArgs; lastmouse = e.Location; if (e.Button == MouseButtons.Left) { mousedown = true; using (Surface brushsource = e.Brush.GetSurface(e.BrushWidth)) { brushheight = brushsource.Height; brushwidth = brushsource.Width; brushsize = new Size(brushwidth, brushheight); brushcenteroffset = new Size(brushwidth / 2, brushheight / 2); spacing = GetSpacing(brushsize, e.Quality); int brusharea = brushwidth * brushheight; brush = new float[brusharea * 4]; Point srcpt = Point.Subtract(e.Location, new Size(brushwidth / 2, brushheight / 2)); strengthmask = new float[brusharea]; float strength = (float)(Math.Pow(e.Strength, .25) / 255.0); fixed(float *_strmask = strengthmask) { float *strmask = _strmask; ColorBgra *voidstar = (ColorBgra *)brushsource.Scan0.VoidStar; for (int i = 0; i < brushsource.Scan0.Length; i += 4) { *strmask = voidstar->A * strength; ++voidstar; ++strmask; } } //fill the brush buffer by copying the surface where we clicked into the buffer fixed(float *brshptrpin = brush) { float *brshptr = brshptrpin; ColorBgra *ptr0 = (ColorBgra *)Surface.Scan0.VoidStar; for (int y = 0; y < brushheight; ++y) { int srcy = Clamp(srcpt.Y + y, 0, srfcHeight - 1); ColorBgra *ptrrow = ptr0 + srfcWidth * srcy; for (int x = 0; x < brushwidth; ++x) { int srcx = Clamp(srcpt.X + x, 0, srfcWidth - 1); ColorBgra *ptr = ptrrow + srcx; brshptr[B] = ptr->B; brshptr[G] = ptr->G; brshptr[R] = ptr->R; brshptr[A] = ptr->A; brshptr += 4; } } } } } }
public unsafe override void Render(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { // Glow backgound glowEffect.Data.Radius = 6; glowEffect.Data.Brightness = -(Data.Coloring - 50) * 2; glowEffect.Data.Contrast = -(Data.Coloring - 50) * 2; this.glowEffect.Render(src, dest, rois); // Create black outlines by finding the edges of objects foreach (Gdk.Rectangle roi in rois) { 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 > dest.Height) { bottom = dest.Height; } ColorBgra *srcPtr = src.GetPointAddress(roi.X, y); ColorBgra *dstPtr = dest.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 > dest.Width) { right = dest.Width; } int r = 0; int g = 0; int b = 0; int src_width = src.Width; ColorBgra *src_dataptr = (ColorBgra *)src.DataPtr; for (int v = top; v < bottom; v++) { ColorBgra *pRow = src.GetRowAddressUnchecked(src_dataptr, src_width, 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( Utility.ClampToByte(b), Utility.ClampToByte(g), Utility.ClampToByte(r)); // Desaturate topLayer = this.desaturateOp.Apply(topLayer); // Adjust Brightness and Contrast if (topLayer.R > (Data.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; } } } }
protected unsafe override void OnRender(Rectangle[] renderRects, int startIndex, int length) { Surface dst = DstArgs.Surface; Surface src = SrcArgs.Surface; Rectangle bounds = SrcArgs.Bounds; dst.CopySurface(src, renderRects); foreach (Rectangle rect in renderRects) { for ( double xoffset = 0, yoffset = 0; xoffset <= DistanceX && yoffset <= DistanceY; xoffset += SpacingX, yoffset += SpacingY) { float xdirectedoffset = -(float)xoffset * DirectionX; float ydirectedoffset = -(float)yoffset * DirectionY; if (IsCancelRequested) { return; } for (int y = rect.Top; y < rect.Bottom; ++y) { float srcy = y + ydirectedoffset; if (!(bounds.Top <= srcy && srcy < bounds.Bottom)) { continue; } ColorBgra *dstptr = dst.GetPointAddressUnchecked(rect.Left, y); ColorBgra *srcptr = src.GetPointAddressUnchecked(0, (int)srcy); for (int x = rect.Left; x < rect.Right; ++x) { float srcx = x + xdirectedoffset; if (!(bounds.Left <= srcx && srcx < bounds.Right)) { ++dstptr; continue; } ColorBgra srcpixel; if (Bilinear) { srcpixel = src.GetBilinearSample(srcx, srcy); } else { srcpixel = *(srcptr + (int)srcx); } if (Fade) { srcpixel.A = (byte)((srcpixel.A) * (1 - xoffset / DistanceX)); } *dstptr = blendOp.Apply(srcpixel, *dstptr); ++dstptr; } } } } }
public unsafe ColorBgraArrayWrapper (ColorBgra* data, int width, int height) { data_ptr = data; this.height = height; this.width = width; }
public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois) { if (Data.Amount == 0) { // Copy src to dest return; } int src_width = src.Width; ColorBgra *src_data_ptr = (ColorBgra *)src.DataPtr; int dst_width = dst.Width; ColorBgra *dst_data_ptr = (ColorBgra *)dst.DataPtr; Gdk.Rectangle src_bounds = src.GetBounds(); long w = dst.Width; long h = dst.Height; long fox = (long)(dst.Width * Data.Offset.X * 32768.0); long foy = (long)(dst.Height * Data.Offset.Y * 32768.0); long fcx = fox + (w << 15); long fcy = foy + (h << 15); long fz = Data.Amount; const int n = 64; foreach (Gdk.Rectangle rect in rois) { for (int y = rect.Top; y <= rect.GetBottom(); ++y) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(dst_data_ptr, dst_width, rect.Left, y); ColorBgra *srcPtr = src.GetPointAddressUnchecked(src_data_ptr, src_width, rect.Left, y); for (int x = rect.Left; x <= rect.GetRight(); ++x) { long fx = (x << 16) - fcx; long fy = (y << 16) - fcy; int sr = 0; int sg = 0; int sb = 0; int sa = 0; int sc = 0; sr += srcPtr->R * srcPtr->A; sg += srcPtr->G * srcPtr->A; sb += srcPtr->B * srcPtr->A; sa += srcPtr->A; ++sc; for (int i = 0; i < n; ++i) { fx -= ((fx >> 4) * fz) >> 10; fy -= ((fy >> 4) * fz) >> 10; int u = (int)(fx + fcx + 32768 >> 16); int v = (int)(fy + fcy + 32768 >> 16); if (src_bounds.Contains(u, v)) { ColorBgra *srcPtr2 = src.GetPointAddressUnchecked(src_data_ptr, src_width, u, v); sr += srcPtr2->R * srcPtr2->A; sg += srcPtr2->G * srcPtr2->A; sb += srcPtr2->B * srcPtr2->A; sa += srcPtr2->A; ++sc; } } if (sa != 0) { *dstPtr = ColorBgra.FromBgra( Utility.ClampToByte(sb / sa), Utility.ClampToByte(sg / sa), Utility.ClampToByte(sr / sa), Utility.ClampToByte(sa / sc)); } else { dstPtr->Bgra = 0; } ++srcPtr; ++dstPtr; } } } }
protected override unsafe Gdk.Rectangle OnMouseMove(Context g, Color strokeColor, ImageSurface surface, int x, int y, int lastX, int lastY) { int rad = (int)(g.LineWidth / 2.0) + 1; Gdk.Rectangle surface_rect = new Gdk.Rectangle(0, 0, surface.Width, surface.Height); Gdk.Rectangle brush_rect = new Gdk.Rectangle(x - rad, y - rad, 2 * rad, 2 * rad); Gdk.Rectangle dest_rect = Gdk.Rectangle.Intersect(surface_rect, brush_rect); //Initialize lookup table when first used (to prevent slower startup of the application) if (lut_factor == null) { lut_factor = new byte[LUT_Resolution + 1, LUT_Resolution + 1]; for (int dy = 0; dy < LUT_Resolution + 1; dy++) { for (int dx = 0; dx < LUT_Resolution + 1; dx++) { double d = Math.Sqrt(dx * dx + dy * dy) / LUT_Resolution; if (d > 1.0) { lut_factor [dx, dy] = 0; } else { lut_factor [dx, dy] = (byte)(Math.Cos(Math.Sqrt(d) * Math.PI / 2.0) * 255.0); } } } } if ((dest_rect.Width > 0) && (dest_rect.Height > 0)) { //Allow Clipping through a temporary surface ImageSurface tmp_surface = new ImageSurface(Format.Argb32, dest_rect.Width, dest_rect.Height); using (Context g2 = new Context(tmp_surface)) { g2.Operator = Operator.Source; g2.SetSourceSurface(surface, -dest_rect.Left, -dest_rect.Top); g2.Rectangle(new Rectangle(0, 0, dest_rect.Width, dest_rect.Height)); g2.Fill(); } //Flush to make sure all drawing operations are finished tmp_surface.Flush(); int mean_r = 0, mean_g = 0, mean_b = 0; int max_diff_r = 1, max_diff_g = 1, max_diff_b = 1; int sz = 0; byte[,] factors = new byte[dest_rect.Right - dest_rect.Left, dest_rect.Bottom - dest_rect.Top]; for (int iy = dest_rect.Top; iy < dest_rect.Bottom; iy++) { ColorBgra *srcRowPtr = tmp_surface.GetPointAddressUnchecked(0, iy - dest_rect.Top); for (int ix = dest_rect.Left; ix < dest_rect.Right; ix++) { ColorBgra col = (*srcRowPtr).ToStraightAlpha(); int dx = ((ix - x) * LUT_Resolution) / rad; if (dx < 0) { dx = -dx; } int dy = ((iy - y) * LUT_Resolution) / rad; if (dy < 0) { dy = -dy; } int factor = lut_factor[dx, dy]; sz += factor; mean_r += col.R * factor; mean_g += col.G * factor; mean_b += col.B * factor; srcRowPtr++; } } if (sz > 0) { mean_r /= sz; mean_g /= sz; mean_b /= sz; } for (int iy = dest_rect.Top; iy < dest_rect.Bottom; iy++) { ColorBgra *srcRowPtr = tmp_surface.GetPointAddressUnchecked(0, iy - dest_rect.Top); for (int ix = dest_rect.Left; ix < dest_rect.Right; ix++) { ColorBgra col = (*srcRowPtr).ToStraightAlpha(); int dr = col.R - mean_r; int dg = col.G - mean_g; int db = col.B - mean_b; if (dr < 0) { dr = -dr; } if (dg < 0) { dg = -dg; } if (db < 0) { db = -db; } if (dr > max_diff_r) { max_diff_r = dr; } if (dg > max_diff_g) { max_diff_g = dg; } if (db > max_diff_b) { max_diff_b = db; } srcRowPtr++; } } for (int iy = dest_rect.Top; iy < dest_rect.Bottom; iy++) { ColorBgra *srcRowPtr = tmp_surface.GetPointAddressUnchecked(0, iy - dest_rect.Top); int dy = ((iy - y) * LUT_Resolution) / rad; if (dy < 0) { dy = -dy; } for (int ix = dest_rect.Left; ix < dest_rect.Right; ix++) { ColorBgra col = (*srcRowPtr).ToStraightAlpha(); int dx = ((ix - x) * LUT_Resolution) / rad; if (dx < 0) { dx = -dx; } int dr = ((col.R - mean_r) * 2 * LUT_Resolution) / max_diff_r; int dg = ((col.G - mean_g) * 2 * LUT_Resolution) / max_diff_g; int db = ((col.B - mean_b) * 2 * LUT_Resolution) / max_diff_b; if (dr < 0) { dr = -dr; } if (dg < 0) { dg = -dg; } if (db < 0) { db = -db; } if (dr > LUT_Resolution) { dr = LUT_Resolution; } if (dg > LUT_Resolution) { dg = LUT_Resolution; } if (db > LUT_Resolution) { db = LUT_Resolution; } int factor; if ((max_diff_r > 32) || (max_diff_g > 32) || (max_diff_b > 32)) { factor = lut_factor[dx, dy] * lut_factor[dg, (dr + db) / 2]; col.A = (byte)((col.A * (0xFFFF - factor)) / 0xFFFF); } else { factor = lut_factor[dx, dy]; col.A = (byte)((col.A * (0xFF - factor)) / 0xFF); } *srcRowPtr = col.ToPremultipliedAlpha(); srcRowPtr++; } } //Draw the final result on the surface g.Operator = Operator.Source; g.SetSourceSurface(tmp_surface, dest_rect.Left, dest_rect.Top); g.Rectangle(new Rectangle(dest_rect.Left, dest_rect.Top, dest_rect.Width, dest_rect.Height)); g.Fill(); } return(Gdk.Rectangle.Zero); }
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 virtual void Apply(ColorBgra *dst, ColorBgra *src, int length) { throw new NotImplementedException("Derived class must implement Apply(ColorBgra*,ColorBgra*,int)"); }
float remainingSpace; //keeps track of spacing protected unsafe override void OnMouseMove(QueuedToolEventArgs le) { SmudgeEventArgs e = le as SmudgeEventArgs; int jittermax = (int)(e.Jitter * e.BrushWidth); Rectangle invrect = new Rectangle(lastmouse.X - brushwidth / 2, lastmouse.Y - brushheight / 2, brushwidth, brushheight); invrect = Rectangle.Union(invrect, new Rectangle(e.X - brushwidth / 2, e.Y - brushheight / 2, brushwidth, brushheight)); invrect.Inflate(jittermax, jittermax); if (e.Button == MouseButtons.Left && mousedown) { float dist = Distance(lastmouse, e.Location); ColorBgra *ptr0 = (ColorBgra *)Surface.Scan0.VoidStar; float f; for (f = remainingSpace; f < dist && !IsAborted; f += spacing) { PointF currentpoint = Lerp(lastmouse, e.Location, f / dist); if (jittermax > 0) { currentpoint.X += r.Next(-jittermax, jittermax); currentpoint.Y += r.Next(-jittermax, jittermax); } Point dstpt = Point.Subtract(new Point((int)currentpoint.X, (int)currentpoint.Y), brushcenteroffset); Rectangle dstRect = new Rectangle(dstpt, brushsize); Rectangle clippedRect = Rectangle.Intersect(dstRect, Surface.Bounds); fixed(float *brshpin = brush, _strmask = strengthmask) { float *brshptr = brshpin, strmask = _strmask; int maxy = dstpt.Y + dstRect.Height; int maxx = dstpt.X + dstRect.Width; for (int y = dstpt.Y; y < maxy; ++y) { int dsty = Clamp(y, 0, srfcHeight - 1); ColorBgra *ptrrow = ptr0 + srfcWidth * dsty; for (int x = dstpt.X; x < maxx; ++x) { int dstx = Clamp(x, 0, srfcWidth - 1); ColorBgra *srfcptr = ptrrow + dstx; float invstr = 1.0f - *strmask; //eliminate fringing from 0-alpha //this officially makes us awesomer than Photoshop if (brshptr[A] == 0.0f) { brshptr[B] = srfcptr->B; brshptr[G] = srfcptr->G; brshptr[R] = srfcptr->R; } else if (srfcptr->A == 0) { srfcptr->B = (byte)(brshptr[B]); srfcptr->G = (byte)(brshptr[G]); srfcptr->R = (byte)(brshptr[R]); } //blend the surface into the brush buffer, then copy it back onto the surface brshptr[B] = (brshptr[B] * *strmask + srfcptr->B * invstr); srfcptr->B = (byte)(brshptr[B] + 0.5f); brshptr[G] = (brshptr[G] * *strmask + srfcptr->G * invstr); srfcptr->G = (byte)(brshptr[G] + 0.5f); brshptr[R] = (brshptr[R] * *strmask + srfcptr->R * invstr); srfcptr->R = (byte)(brshptr[R] + 0.5f); brshptr[A] = (brshptr[A] * *strmask + srfcptr->A * invstr); srfcptr->A = (byte)(brshptr[A] + 0.5f); brshptr += 4; ++strmask; } } } } remainingSpace = f - dist; } OnInvalidated(invrect); lastmouse = e.Location; }
public override void Render(Surface src, Surface dst, Rectangle[] rois, int startIndex, int length) { long w = dst.Width; long h = dst.Height; long fox = (long)(dst.Width * offsetX * 32768.0); long foy = (long)(dst.Height * offsetY * 32768.0); long fcx = fox + (w << 15); long fcy = foy + (h << 15); long fz = this.amount; unsafe { for (int r = startIndex; r < startIndex + length; ++r) { Rectangle rect = rois[r]; for (int y = rect.Top; y < rect.Bottom; ++y) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); ColorBgra *srcPtr = src.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; ++x) { long fx = (x << 16) - fcx; long fy = (y << 16) - fcy; int sr = 0; int sg = 0; int sb = 0; int sa = 0; int sc = 0; sr += srcPtr->R * srcPtr->A; sg += srcPtr->G * srcPtr->A; sb += srcPtr->B * srcPtr->A; sa += srcPtr->A; ++sc; for (int i = 0; i < n; ++i) { fx -= ((fx >> 4) * fz) >> 10; fy -= ((fy >> 4) * fz) >> 10; int u = (int)(fx + fcx + 32768 >> 16); int v = (int)(fy + fcy + 32768 >> 16); if (src.IsVisible(u, v)) { ColorBgra *srcPtr2 = src.GetPointAddressUnchecked(u, v); sr += srcPtr2->R * srcPtr2->A; sg += srcPtr2->G * srcPtr2->A; sb += srcPtr2->B * srcPtr2->A; sa += srcPtr2->A; ++sc; } } if (sa != 0) { *dstPtr = ColorBgra.FromBgra( PixelUtils.ClampToByte(sb / sa), PixelUtils.ClampToByte(sg / sa), PixelUtils.ClampToByte(sr / sa), PixelUtils.ClampToByte(sa / sc)); } else { dstPtr->Bgra = 0; } ++srcPtr; ++dstPtr; } } } } }
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; } } } } }
public unsafe override void Render(Surface dst, System.Drawing.Point offset) { if (OwnerList.ScaleFactor < new ScaleFactor(2, 1)) { return; } int[] d2SLookupX = OwnerList.Dst2SrcLookupX; int[] d2SLookupY = OwnerList.Dst2SrcLookupY; int[] s2DLookupX = OwnerList.Src2DstLookupX; int[] s2DLookupY = OwnerList.Src2DstLookupY; ColorBgra[] blackAndWhite = new ColorBgra[2] { ColorBgra.White, ColorBgra.Black }; // draw horizontal lines int sTop = d2SLookupY[offset.Y]; int sBottom = d2SLookupY[offset.Y + dst.Height]; for (int srcY = sTop; srcY <= sBottom; ++srcY) { int dstY = s2DLookupY[srcY]; int dstRow = dstY - offset.Y; if (dst.IsRowVisible(dstRow)) { ColorBgra *dstRowPtr = dst.GetRowAddress(dstRow); ColorBgra *dstRowEndPtr = dstRowPtr + dst.Width; dstRowPtr += offset.X & 1; while (dstRowPtr < dstRowEndPtr) { *dstRowPtr = ColorBgra.Black; dstRowPtr += 2; } } } // draw vertical lines int sLeft = d2SLookupX[offset.X]; int sRight = d2SLookupX[offset.X + dst.Width]; for (int srcX = sLeft; srcX <= sRight; ++srcX) { int dstX = s2DLookupX[srcX]; int dstCol = dstX - offset.X; if (dst.IsColumnVisible(dstX - offset.X)) { byte *dstColPtr = (byte *)dst.GetPointAddress(dstCol, 0); byte *dstColEndPtr = dstColPtr + dst.Stride * dst.Height; dstColPtr += (offset.Y & 1) * dst.Stride; while (dstColPtr < dstColEndPtr) { *((ColorBgra *)dstColPtr) = ColorBgra.Black; dstColPtr += 2 * dst.Stride; } } } }
public unsafe void RenderColorDifferenceEffect( double[][] weights, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length) { Surface dst = dstArgs.Surface; Surface src = srcArgs.Surface; for (int i = startIndex; i < startIndex + length; ++i) { Rectangle rect = rois[i]; // loop through each line of target rectangle for (int y = rect.Top; y < rect.Bottom; ++y) { int fyStart = 0; int fyEnd = 3; if (y == src.Bounds.Top) { fyStart = 1; } if (y == src.Bounds.Bottom - 1) { fyEnd = 2; } // loop through each point in the line ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; ++x) { int fxStart = 0; int fxEnd = 3; if (x == src.Bounds.Left) { fxStart = 1; } if (x == src.Bounds.Right - 1) { fxEnd = 2; } // loop through each weight double rSum = 0.0; double gSum = 0.0; double bSum = 0.0; for (int fy = fyStart; fy < fyEnd; ++fy) { for (int fx = fxStart; fx < fxEnd; ++fx) { double weight = weights[fy][fx]; ColorBgra c = src.GetPointUnchecked(x - 1 + fx, y - 1 + fy); rSum += weight * (double)c.R; gSum += weight * (double)c.G; bSum += weight * (double)c.B; } } int iRsum = (int)rSum; int iGsum = (int)gSum; int iBsum = (int)bSum; if (iRsum > 255) { iRsum = 255; } if (iGsum > 255) { iGsum = 255; } if (iBsum > 255) { iBsum = 255; } if (iRsum < 0) { iRsum = 0; } if (iGsum < 0) { iGsum = 0; } if (iBsum < 0) { iBsum = 0; } *dstPtr = ColorBgra.FromBgra((byte)iBsum, (byte)iGsum, (byte)iRsum, 255); ++dstPtr; } } } }
public unsafe void Render(Surface src, Surface dst, Rectangle[] rois, int start, int len) { int width = src.Width; int height = src.Height; int arrayLens = 1 + this.coarseness; int localStoreSize = arrayLens * 5 * sizeof(int); byte *localStore = stackalloc byte[localStoreSize]; byte *p = localStore; int *intensityCount = (int *)p; p += arrayLens * sizeof(int); uint *avgRed = (uint *)p; p += arrayLens * sizeof(uint); uint *avgGreen = (uint *)p; p += arrayLens * sizeof(uint); uint *avgBlue = (uint *)p; p += arrayLens * sizeof(uint); uint *avgAlpha = (uint *)p; p += arrayLens * sizeof(uint); byte maxIntensity = this.coarseness; //TODO: review here for (int r = start; r < start + len; ++r) { Rectangle rect = rois[r]; int rectTop = rect.Top; int rectBottom = rect.Bottom; int rectLeft = rect.Left; int rectRight = rect.Right; for (int y = rectTop; y < rectBottom; ++y) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); int top = y - brushSize; int bottom = y + brushSize + 1; if (top < 0) { top = 0; } if (bottom > height) { bottom = height; } for (int x = rectLeft; x < rectRight; ++x) { PlatformMemory.SetToZero(localStore, (ulong)localStoreSize); int left = x - brushSize; int right = x + brushSize + 1; if (left < 0) { left = 0; } if (right > width) { right = width; } int numInt = 0; for (int j = top; j < bottom; ++j) { ColorBgra *srcPtr = src.GetPointAddressUnchecked(left, j); for (int i = left; i < right; ++i) { byte intensity = PixelUtils.FastScaleByteByByte(srcPtr->GetIntensityByte(), maxIntensity); ++intensityCount[intensity]; ++numInt; avgRed[intensity] += srcPtr->R; avgGreen[intensity] += srcPtr->G; avgBlue[intensity] += srcPtr->B; avgAlpha[intensity] += srcPtr->A; ++srcPtr; } } byte chosenIntensity = 0; int maxInstance = 0; for (int i = 0; i <= maxIntensity; ++i) { if (intensityCount[i] > maxInstance) { chosenIntensity = (byte)i; maxInstance = intensityCount[i]; } } // TODO: correct handling of alpha values? byte R = (byte)(avgRed[chosenIntensity] / maxInstance); byte G = (byte)(avgGreen[chosenIntensity] / maxInstance); byte B = (byte)(avgBlue[chosenIntensity] / maxInstance); byte A = (byte)(avgAlpha[chosenIntensity] / maxInstance); *dstPtr = ColorBgra.FromBgra(B, G, R, A); ++dstPtr; } } } }
public override unsafe void Apply(ColorBgra *dst, ColorBgra *src, int length) { while (length > 0) { int h = 0; int s = 0; int v = 0; int max = (src->R > src->G) ? src->R : src->G; if (max < src->B) { max = src->B; } v = max; int NewV = CurveV[v]; if (NewV == 0) // if the target Value is zero, there is no point calculating Saturation or Hue ... { dst->B = 0; dst->G = 0; dst->R = 0; } else { int min = (src->R < src->G) ? src->R : src->G; if (min > src->B) { min = src->B; } int delta = max - min; if (delta > 0) { s = CommonUtil.IntDiv(255 * delta, max); } int NewS = CurveS[s]; if (NewS == 0) // if the target saturation is zero, then there is no point calculating a hue { dst->B = (byte)NewV; dst->G = (byte)NewV; dst->R = (byte)NewV; } else { if (src->R == max) // Between Yellow and Magenta { h = CommonUtil.IntDiv(255 * (src->G - src->B), delta); } else if (src->G == max) // Between Cyan and Yellow { h = 512 + CommonUtil.IntDiv(255 * (src->B - src->R), delta); } else // Between Magenta and Cyan { h = 1024 + CommonUtil.IntDiv(255 * (src->R - src->G), delta); } if (h < 0) { h += 1536; } h = CommonUtil.IntDiv(h, 6); } int NewH = CurveH[h]; if ((NewH == h) && (NewS == s)) { dst->B = (byte)(CommonUtil.IntDiv(src->B * NewV, v)); dst->G = (byte)(CommonUtil.IntDiv(src->G * NewV, v)); dst->R = (byte)(CommonUtil.IntDiv(src->R * NewV, v)); } else { NewH *= 6; int fractionalSector = (NewH & 0xff); int sectorNumber = (NewH >> 8); dst->B = src->B; dst->G = src->G; dst->R = src->R; //// Assign the fractional colors to r, g, and b //// based on the sector the angle is in. switch (sectorNumber) { case 0: dst->R = (byte)NewV; int tmp0 = ((NewS * (255 - fractionalSector)) + 128) >> 8; dst->G = (byte)(((NewV * (255 - tmp0)) + 128) >> 8); dst->B = (byte)(((NewV * (255 - NewS)) + 128) >> 8); break; case 1: int tmp1 = ((NewS * fractionalSector) + 128) >> 8; dst->R = (byte)(((NewV * (255 - tmp1)) + 128) >> 8); dst->G = (byte)NewV; dst->B = (byte)(((NewV * (255 - NewS)) + 128) >> 8); break; case 2: dst->R = (byte)(((NewV * (255 - NewS)) + 128) >> 8); dst->G = (byte)NewV; int tmp2 = ((NewS * (255 - fractionalSector)) + 128) >> 8; dst->B = (byte)(((NewV * (255 - tmp2)) + 128) >> 8); break; case 3: dst->R = (byte)(((NewV * (255 - NewS)) + 128) >> 8); int tmp3 = ((NewS * fractionalSector) + 128) >> 8; dst->G = (byte)(((NewV * (255 - tmp3)) + 128) >> 8); dst->B = (byte)NewV; break; case 4: int tmp4 = ((NewS * (255 - fractionalSector)) + 128) >> 8; dst->R = (byte)(((NewV * (255 - tmp4)) + 128) >> 8); dst->G = (byte)(((NewV * (255 - NewS)) + 128) >> 8); dst->B = (byte)NewV; break; case 5: dst->R = (byte)NewV; dst->G = (byte)(((NewV * (255 - NewS)) + 128) >> 8); int tmp5 = ((NewS * fractionalSector) + 128) >> 8; dst->B = (byte)(((NewV * (255 - tmp5)) + 128) >> 8); break; } } } dst->A = src->A; ++dst; ++src; --length; } }
public unsafe override void Apply(ColorBgra *dst, ColorBgra *src, int length) { Memory.Copy(dst, src, (ulong)length * (ulong)ColorBgra.SizeOf); }
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 unsafe override void Render(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { int width = src.Width; int height = src.Height; int arrayLens = 1 + Data.Coarseness; int localStoreSize = arrayLens * 5 * sizeof(int); byte *localStore = stackalloc byte[localStoreSize]; byte *p = localStore; int *intensityCount = (int *)p; p += arrayLens * sizeof(int); uint *avgRed = (uint *)p; p += arrayLens * sizeof(uint); uint *avgGreen = (uint *)p; p += arrayLens * sizeof(uint); uint *avgBlue = (uint *)p; p += arrayLens * sizeof(uint); uint *avgAlpha = (uint *)p; p += arrayLens * sizeof(uint); byte maxIntensity = (byte)Data.Coarseness; foreach (Gdk.Rectangle rect in rois) { int rectTop = rect.Top; int rectBottom = rect.GetBottom(); int rectLeft = rect.Left; int rectRight = rect.GetRight(); ColorBgra *dst_dataptr = (ColorBgra *)dest.DataPtr; int dst_width = dest.Width; ColorBgra *src_dataptr = (ColorBgra *)src.DataPtr; int src_width = src.Width; for (int y = rectTop; y <= rectBottom; ++y) { ColorBgra *dstPtr = dest.GetPointAddressUnchecked(dst_dataptr, dst_width, rect.Left, y); int top = y - Data.BrushSize; int bottom = y + Data.BrushSize + 1; if (top < 0) { top = 0; } if (bottom > height) { bottom = height; } for (int x = rectLeft; x <= rectRight; ++x) { SetToZero(localStore, (ulong)localStoreSize); int left = x - Data.BrushSize; int right = x + Data.BrushSize + 1; if (left < 0) { left = 0; } if (right > width) { right = width; } int numInt = 0; for (int j = top; j < bottom; ++j) { ColorBgra *srcPtr = src.GetPointAddressUnchecked(src_dataptr, src_width, left, j); for (int i = left; i < right; ++i) { byte intensity = Utility.FastScaleByteByByte(srcPtr->GetIntensityByte(), maxIntensity); ++intensityCount[intensity]; ++numInt; avgRed[intensity] += srcPtr->R; avgGreen[intensity] += srcPtr->G; avgBlue[intensity] += srcPtr->B; avgAlpha[intensity] += srcPtr->A; ++srcPtr; } } byte chosenIntensity = 0; int maxInstance = 0; for (int i = 0; i <= maxIntensity; ++i) { if (intensityCount[i] > maxInstance) { chosenIntensity = (byte)i; maxInstance = intensityCount[i]; } } // TODO: correct handling of alpha values? byte R = (byte)(avgRed[chosenIntensity] / maxInstance); byte G = (byte)(avgGreen[chosenIntensity] / maxInstance); byte B = (byte)(avgBlue[chosenIntensity] / maxInstance); byte A = (byte)(avgAlpha[chosenIntensity] / maxInstance); *dstPtr = ColorBgra.FromBgra(B, G, R, A); ++dstPtr; } } } }
/// <summary> /// Process the pixel in the first pass of the algorithm /// </summary> /// <param name="pixel">The pixel to quantize</param> /// <remarks> /// This function need only be overridden if your quantize algorithm needs two passes, /// such as an Octree quantizer. /// </remarks> protected override void InitialQuantizePixel(ColorBgra *pixel) { _octree.AddColor(pixel); }
public unsafe void Render(Surface surface, Rectangle[] rois, int startIndex, int length) { byte startAlpha; byte endAlpha; if (this.alphaOnly) { ComputeAlphaOnlyValuesFromColors(this.startColor, this.endColor, out startAlpha, out endAlpha); } else { startAlpha = this.startColor.A; endAlpha = this.endColor.A; } for (int ri = startIndex; ri < startIndex + length; ++ri) { Rectangle rect = rois[ri]; if (this.startPoint == this.endPoint) { // Start and End point are the same ... fill with solid color. for (int y = rect.Top; y < rect.Bottom; ++y) { ColorBgra *pixelPtr = surface.GetPointAddress(rect.Left, y); for (int x = rect.Left; x < rect.Right; ++x) { ColorBgra result; if (this.alphaOnly && this.alphaBlending) { byte resultAlpha = (byte)Utility.FastDivideShortByByte((ushort)(pixelPtr->A * endAlpha), 255); result = *pixelPtr; result.A = resultAlpha; } else if (this.alphaOnly && !this.alphaBlending) { result = *pixelPtr; result.A = endAlpha; } else if (!this.alphaOnly && this.alphaBlending) { result = this.normalBlendOp.Apply(*pixelPtr, this.endColor); } else //if (!this.alphaOnly && !this.alphaBlending) { result = this.endColor; } *pixelPtr = result; ++pixelPtr; } } } else { for (int y = rect.Top; y < rect.Bottom; ++y) { ColorBgra *pixelPtr = surface.GetPointAddress(rect.Left, y); if (this.alphaOnly && this.alphaBlending) { for (int x = rect.Left; x < rect.Right; ++x) { float lerpUnbounded = ComputeUnboundedLerp(x, y); float lerpBounded = BoundLerp(lerpUnbounded); byte lerpByte = (byte)(lerpBounded * 255.0f); byte lerpAlpha = this.lerpAlphas[lerpByte]; byte resultAlpha = (byte)Utility.FastScaleByteByByte(pixelPtr->A, lerpAlpha); pixelPtr->A = resultAlpha; ++pixelPtr; } } else if (this.alphaOnly && !this.alphaBlending) { for (int x = rect.Left; x < rect.Right; ++x) { float lerpUnbounded = ComputeUnboundedLerp(x, y); float lerpBounded = BoundLerp(lerpUnbounded); byte lerpByte = (byte)(lerpBounded * 255.0f); byte lerpAlpha = this.lerpAlphas[lerpByte]; pixelPtr->A = lerpAlpha; ++pixelPtr; } } else if (!this.alphaOnly && (this.alphaBlending && (startAlpha != 255 || endAlpha != 255))) { // If we're doing all color channels, and we're doing alpha blending, and if alpha blending is necessary for (int x = rect.Left; x < rect.Right; ++x) { float lerpUnbounded = ComputeUnboundedLerp(x, y); float lerpBounded = BoundLerp(lerpUnbounded); byte lerpByte = (byte)(lerpBounded * 255.0f); ColorBgra lerpColor = this.lerpColors[lerpByte]; ColorBgra result = this.normalBlendOp.Apply(*pixelPtr, lerpColor); * pixelPtr = result; ++pixelPtr; } } else //if (!this.alphaOnly && !this.alphaBlending) // or sC.A == 255 && eC.A == 255 { for (int x = rect.Left; x < rect.Right; ++x) { float lerpUnbounded = ComputeUnboundedLerp(x, y); float lerpBounded = BoundLerp(lerpUnbounded); byte lerpByte = (byte)(lerpBounded * 255.0f); ColorBgra lerpColor = this.lerpColors[lerpByte]; * pixelPtr = lerpColor; ++pixelPtr; } } } } } AfterRender(); }