示例#1
0
        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 unsafe override void Apply(ColorBgra *dst, ColorBgra *src, int length)
 {
     PlatformMemory.Copy(dst, src, (ulong)length * (ulong)ColorBgra.SizeOf);
 }
示例#3
0
        //same as RenderRect, except the histogram is alpha-weighted instead of keeping a separate alpha channel histogram.
        public unsafe void RenderRectWithAlpha(
            int rad,
            Surface src,
            Surface dst,
            Rectangle rect)
        {
            int width  = src.Width;
            int height = src.Height;

            int *leadingEdgeX = stackalloc int[rad + 1];
            int  stride       = src.Stride / sizeof(ColorBgra);

            // approximately (rad + 0.5)^2
            int cutoff = ((rad * 2 + 1) * (rad * 2 + 1) + 2) / 4;

            for (int v = 0; v <= rad; ++v)
            {
                for (int u = 0; u <= rad; ++u)
                {
                    if (u * u + v * v <= cutoff)
                    {
                        leadingEdgeX[v] = u;
                    }
                }
            }

            const int hLength = 256;
            int *     hb      = stackalloc int[hLength];
            int *     hg      = stackalloc int[hLength];
            int *     hr      = stackalloc int[hLength];
            uint      hSize   = (uint)(sizeof(int) * hLength);

            for (int y = rect.Top; y < rect.Bottom; y++)
            {
                PlatformMemory.SetToZero(hb, hSize);
                PlatformMemory.SetToZero(hg, hSize);
                PlatformMemory.SetToZero(hr, hSize);

                int area = 0;
                int sum  = 0;

                ColorBgra *ps = src.GetPointAddressUnchecked(rect.Left, y);
                ColorBgra *pd = dst.GetPointAddressUnchecked(rect.Left, y);

                // assert: v + y >= 0
                int top = -Math.Min(rad, y);

                // assert: v + y <= height - 1
                int bottom = Math.Min(rad, height - 1 - y);

                // assert: u + x >= 0
                int left = -Math.Min(rad, rect.Left);

                // assert: u + x <= width - 1
                int right = Math.Min(rad, width - 1 - rect.Left);

                for (int v = top; v <= bottom; ++v)
                {
                    ColorBgra *psamp = src.GetPointAddressUnchecked(rect.Left + left, y + v);

                    for (int u = left; u <= right; ++u)
                    {
                        byte w = psamp->A;
                        if ((u * u + v * v) <= cutoff)
                        {
                            ++area;
                            sum          += w;
                            hb[psamp->B] += w;
                            hg[psamp->G] += w;
                            hr[psamp->R] += w;
                        }

                        ++psamp;
                    }
                }

                for (int x = rect.Left; x < rect.Right; x++)
                {
                    *pd = ApplyWithAlpha(*ps, area, sum, hb, hg, hr);

                    // assert: u + x >= 0
                    left = -Math.Min(rad, x);

                    // assert: u + x <= width - 1
                    right = Math.Min(rad + 1, width - 1 - x);

                    // Subtract trailing edge top half
                    int v = -1;

                    while (v >= top)
                    {
                        int u = leadingEdgeX[-v];

                        if (-u >= left)
                        {
                            break;
                        }

                        --v;
                    }

                    while (v >= top)
                    {
                        int        u = leadingEdgeX[-v];
                        ColorBgra *p = unchecked (ps + (v * stride)) - u;
                        byte       w = p->A;

                        hb[p->B] -= w;
                        hg[p->G] -= w;
                        hr[p->R] -= w;
                        sum      -= w;
                        --area;

                        --v;
                    }

                    // add leading edge top half
                    v = -1;
                    while (v >= top)
                    {
                        int u = leadingEdgeX[-v];

                        if (u + 1 <= right)
                        {
                            break;
                        }

                        --v;
                    }

                    while (v >= top)
                    {
                        int        u = leadingEdgeX[-v];
                        ColorBgra *p = unchecked (ps + (v * stride)) + u + 1;
                        byte       w = p->A;

                        hb[p->B] += w;
                        hg[p->G] += w;
                        hr[p->R] += w;
                        sum      += w;
                        ++area;

                        --v;
                    }

                    // Subtract trailing edge bottom half
                    v = 0;

                    while (v <= bottom)
                    {
                        int u = leadingEdgeX[v];

                        if (-u >= left)
                        {
                            break;
                        }

                        ++v;
                    }

                    while (v <= bottom)
                    {
                        int        u = leadingEdgeX[v];
                        ColorBgra *p = ps + v * stride - u;
                        byte       w = p->A;

                        hb[p->B] -= w;
                        hg[p->G] -= w;
                        hr[p->R] -= w;
                        sum      -= w;
                        --area;

                        ++v;
                    }

                    // add leading edge bottom half
                    v = 0;

                    while (v <= bottom)
                    {
                        int u = leadingEdgeX[v];

                        if (u + 1 <= right)
                        {
                            break;
                        }

                        ++v;
                    }

                    while (v <= bottom)
                    {
                        int        u = leadingEdgeX[v];
                        ColorBgra *p = ps + v * stride + u + 1;
                        byte       w = p->A;

                        hb[p->B] += w;
                        hg[p->G] += w;
                        hr[p->R] += w;
                        sum      += w;
                        ++area;

                        ++v;
                    }

                    ++ps;
                    ++pd;
                }
            }
        }
示例#4
0
        internal unsafe static void GetRegionScans(IntPtr hRgn, out Rectangle[] scans, out int area)
        {
            uint bytes     = 0;
            int  countdown = screwUpMax;
            int  error     = 0;

            // HACK: It seems that sometimes the GetRegionData will return ERROR_INVALID_HANDLE
            //       even though the handle (the HRGN) is fine. Maybe the function is not
            //       re-entrant? I'm not sure, but trying it again seems to fix it.
            while (countdown > 0)
            {
                bytes = SafeNativeMethods.GetRegionData(hRgn, 0, (NativeStructs.RGNDATA *)IntPtr.Zero);
                error = Marshal.GetLastWin32Error();

                if (bytes == 0)
                {
                    --countdown;
                    System.Threading.Thread.Sleep(5);
                }
                else
                {
                    break;
                }
            }

            // But if we retry several times and it still messes up then we will finally give up.
            if (bytes == 0)
            {
                throw new Win32Exception(error, "GetRegionData returned " + bytes.ToString() + ", GetLastError() = " + error.ToString());
            }

            byte *data;

            // Up to 512 bytes, allocate on the stack. Otherwise allocate from the heap.
            if (bytes <= 512)
            {
                byte *data1 = stackalloc byte[(int)bytes];
                data = data1;
            }
            else
            {
                data = (byte *)PlatformMemory.Allocate(bytes).ToPointer();
            }

            try
            {
                NativeStructs.RGNDATA *pRgnData = (NativeStructs.RGNDATA *)data;
                uint result = SafeNativeMethods.GetRegionData(hRgn, bytes, pRgnData);

                if (result != bytes)
                {
                    throw new OutOfMemoryException("SafeNativeMethods.GetRegionData returned 0");
                }

                NativeStructs.RECT *pRects = NativeStructs.RGNDATA.GetRectsPointer(pRgnData);
                scans = new Rectangle[pRgnData->rdh.nCount];
                area  = 0;

                for (int i = 0; i < scans.Length; ++i)
                {
                    scans[i] = Rectangle.FromLTRB(pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom);
                    area    += scans[i].Width * scans[i].Height;
                }

                pRects   = null;
                pRgnData = null;
            }

            finally
            {
                if (bytes > 512)
                {
                    PlatformMemory.Free(new IntPtr(data));
                }
            }
        }
示例#5
0
        public override void Render(Surface src, Surface dst, Rectangle[] rois, int startIndex, int length)
        {
            unsafe
            {
                if (this.radius == 0)
                {
                    for (int ri = startIndex; ri < startIndex + length; ++ri)
                    {
                        dst.CopySurface(src, rois[ri].Location, rois[ri]);
                    }

                    return;
                }


                int   r    = this.radius;
                int[] w    = CreateGaussianBlurRow(r);
                int   wlen = w.Length;

                int   localStoreSize = wlen * 6 * sizeof(long);
                byte *localStore     = stackalloc byte[localStoreSize];
                byte *p = localStore;

                long *waSums = (long *)p;
                p += wlen * sizeof(long);

                long *wcSums = (long *)p;
                p += wlen * sizeof(long);

                long *aSums = (long *)p;
                p += wlen * sizeof(long);

                long *bSums = (long *)p;
                p += wlen * sizeof(long);

                long *gSums = (long *)p;
                p += wlen * sizeof(long);

                long *rSums = (long *)p;
                p += wlen * sizeof(long);

                ulong arraysLength = (ulong)(sizeof(long) * wlen);

                for (int ri = startIndex; ri < startIndex + length; ++ri)
                {
                    Rectangle rect = rois[ri];

                    if (rect.Height >= 1 && rect.Width >= 1)
                    {
                        for (int y = rect.Top; y < rect.Bottom; ++y)
                        {
                            PlatformMemory.SetToZero(localStore, (ulong)localStoreSize);

                            long waSum = 0;
                            long wcSum = 0;
                            long aSum  = 0;
                            long bSum  = 0;
                            long gSum  = 0;
                            long rSum  = 0;

                            ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);

                            for (int wx = 0; wx < wlen; ++wx)
                            {
                                int srcX = rect.Left + wx - r;
                                waSums[wx] = 0;
                                wcSums[wx] = 0;
                                aSums[wx]  = 0;
                                bSums[wx]  = 0;
                                gSums[wx]  = 0;
                                rSums[wx]  = 0;

                                if (srcX >= 0 && srcX < src.Width)
                                {
                                    for (int wy = 0; wy < wlen; ++wy)
                                    {
                                        int srcY = y + wy - r;

                                        if (srcY >= 0 && srcY < src.Height)
                                        {
                                            ColorBgra c  = src.GetPointUnchecked(srcX, srcY);
                                            int       wp = w[wy];

                                            waSums[wx] += wp;
                                            wp         *= c.A + (c.A >> 7);
                                            wcSums[wx] += wp;
                                            wp        >>= 8;

                                            aSums[wx] += wp * c.A;
                                            bSums[wx] += wp * c.B;
                                            gSums[wx] += wp * c.G;
                                            rSums[wx] += wp * c.R;
                                        }
                                    }

                                    int wwx = w[wx];
                                    waSum += wwx * waSums[wx];
                                    wcSum += wwx * wcSums[wx];
                                    aSum  += wwx * aSums[wx];
                                    bSum  += wwx * bSums[wx];
                                    gSum  += wwx * gSums[wx];
                                    rSum  += wwx * rSums[wx];
                                }
                            }

                            wcSum >>= 8;

                            if (waSum == 0 || wcSum == 0)
                            {
                                dstPtr->Bgra = 0;
                            }
                            else
                            {
                                int alpha = (int)(aSum / waSum);
                                int blue  = (int)(bSum / wcSum);
                                int green = (int)(gSum / wcSum);
                                int red   = (int)(rSum / wcSum);

                                dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha);
                            }

                            ++dstPtr;

                            for (int x = rect.Left + 1; x < rect.Right; ++x)
                            {
                                for (int i = 0; i < wlen - 1; ++i)
                                {
                                    waSums[i] = waSums[i + 1];
                                    wcSums[i] = wcSums[i + 1];
                                    aSums[i]  = aSums[i + 1];
                                    bSums[i]  = bSums[i + 1];
                                    gSums[i]  = gSums[i + 1];
                                    rSums[i]  = rSums[i + 1];
                                }

                                waSum = 0;
                                wcSum = 0;
                                aSum  = 0;
                                bSum  = 0;
                                gSum  = 0;
                                rSum  = 0;

                                int wx;
                                for (wx = 0; wx < wlen - 1; ++wx)
                                {
                                    long wwx = (long)w[wx];
                                    waSum += wwx * waSums[wx];
                                    wcSum += wwx * wcSums[wx];
                                    aSum  += wwx * aSums[wx];
                                    bSum  += wwx * bSums[wx];
                                    gSum  += wwx * gSums[wx];
                                    rSum  += wwx * rSums[wx];
                                }

                                wx = wlen - 1;

                                waSums[wx] = 0;
                                wcSums[wx] = 0;
                                aSums[wx]  = 0;
                                bSums[wx]  = 0;
                                gSums[wx]  = 0;
                                rSums[wx]  = 0;

                                int srcX = x + wx - r;

                                if (srcX >= 0 && srcX < src.Width)
                                {
                                    for (int wy = 0; wy < wlen; ++wy)
                                    {
                                        int srcY = y + wy - r;

                                        if (srcY >= 0 && srcY < src.Height)
                                        {
                                            ColorBgra c  = src.GetPointUnchecked(srcX, srcY);
                                            int       wp = w[wy];

                                            waSums[wx] += wp;
                                            wp         *= c.A + (c.A >> 7);
                                            wcSums[wx] += wp;
                                            wp        >>= 8;

                                            aSums[wx] += wp * (long)c.A;
                                            bSums[wx] += wp * (long)c.B;
                                            gSums[wx] += wp * (long)c.G;
                                            rSums[wx] += wp * (long)c.R;
                                        }
                                    }

                                    int wr = w[wx];
                                    waSum += (long)wr * waSums[wx];
                                    wcSum += (long)wr * wcSums[wx];
                                    aSum  += (long)wr * aSums[wx];
                                    bSum  += (long)wr * bSums[wx];
                                    gSum  += (long)wr * gSums[wx];
                                    rSum  += (long)wr * rSums[wx];
                                }

                                wcSum >>= 8;

                                if (waSum == 0 || wcSum == 0)
                                {
                                    dstPtr->Bgra = 0;
                                }
                                else
                                {
                                    int alpha = (int)(aSum / waSum);
                                    int blue  = (int)(bSum / wcSum);
                                    int green = (int)(gSum / wcSum);
                                    int red   = (int)(rSum / wcSum);

                                    dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha);
                                }

                                ++dstPtr;
                            }
                        }
                    }
                }
            }
        }
示例#6
0
 public static void SetPlatformMemImpl(PlatformMemory p)
 {
     platformMem = p;
 }