private void DisplayParameters(Bitmap img, ImageType type)
 {
     ImagePropertiesUi propertyObject = GetPropertyObject(type);
     float rawSize;
     using (var bh = new BitmapHelper(img))
     {
         rawSize = bh.SizeBytes / 1024.0f / 1024.0f;
     }
     propertyObject.Resolution = img.Size;
     propertyObject.RawSize = rawSize;
     propertyObject.PixelFormat = img.PixelFormat;
 }
 public void LoadImageLayers(List<Bitmap> imageList)
 {
     var layers = new List<Layer>();
     foreach (Bitmap image in imageList)
     {
         using (var helper = new BitmapHelper(image))
         {
             BackgroundStatitics.CommitImageMemory(helper.SizeBytes);
         }
         Rectangle region = AppModel.Instance.Layout.NewLayerMetrics(image.Size);
         layers.Add(new Picture(image, region, 0));
     }
     AppModel.Instance.LayerManager.AddRange(layers);
 }
        // ====================================================================
        // Helpers to operate with .NET types
        // ====================================================================
        public static void ImageInterpolate(Bitmap srcImg, Bitmap tarImg, Bitmap dstImg, float step)
        {
            StaticCheckFormat(PixelFormat.Format24bppRgb, srcImg, tarImg, dstImg);
            StaticCheckSameSize(srcImg, tarImg, dstImg);

            // Less work for caller: let C++ handle threading
            using (var ibSrc = new BitmapHelper(srcImg))
            using (var ibTar = new BitmapHelper(tarImg))
            using (var ibDest = new BitmapHelper(dstImg))
            {
                unsafe
                {
                    ImageProcessingWrapper.Blend24bgr_24bgr(
                        ibSrc.Start, ibTar.Start, ibDest.Start, ibDest.SizeBytes, step);
                }
            }

            // More work for caller: let C# run more threads
            // TODO: How to mark here that C++ should not do MT in this case?
            /*unsafe
            {
                BitmapData resultData = resultImage.LockBits(
                    new Rectangle(0, 0, resultImage.Width, resultImage.Height), ImageLockMode.ReadWrite,
                    resultImage.PixelFormat);
                BitmapData src1Data = srcImage1.LockBits(
                    new Rectangle(0, 0, srcImage1.Width, srcImage1.Height), ImageLockMode.ReadOnly,
                    srcImage1.PixelFormat);
                BitmapData src2Data = srcImage2.LockBits(
                    new Rectangle(0, 0, srcImage2.Width, srcImage2.Height), ImageLockMode.ReadOnly,
                    srcImage2.PixelFormat);

                int heightInPixels = resultData.Height;
                uint stride = (uint)Math.Abs(resultData.Stride);

                Parallel.For(0, heightInPixels, y =>
                {
                    byte* currentLineSrc1 = (byte*)src1Data.Scan0 + (y * stride);
                    byte* currentLineSrc2 = (byte*)src2Data.Scan0 + (y * stride);
                    byte* currentLineResult = (byte*)resultData.Scan0 + (y * stride);
                    ImageProcessingWrapper.Blend24bgr_24bgr(
                        currentLineSrc1, currentLineSrc2, currentLineResult, stride, step);
                });

                resultImage.UnlockBits(resultData);
                srcImage1.UnlockBits(src1Data);
                srcImage2.UnlockBits(src2Data);
            }*/
        }
        public static void ImageAlphaBlend(Bitmap srcImg, Bitmap tarImg, Bitmap dstImg)
        {
            StaticCheckFormat(PixelFormat.Format32bppArgb, srcImg, tarImg, dstImg);
            StaticCheckSameSize(srcImg, tarImg, dstImg);

            // Less work for caller: let C++ handle threading
            using (var ibSrc = new BitmapHelper(srcImg))
            using (var ibTar = new BitmapHelper(tarImg))
            using (var ibDest = new BitmapHelper(dstImg))
            {
                unsafe
                {
                    ImageProcessingWrapper.AlphaBlend32bgra_32bgra(
                        ibSrc.Start, ibTar.Start, ibDest.Start, ibDest.SizeBytes);
                }
            }
        }
        public static void ConvolutionFilter(Bitmap srcImg, Bitmap dstImg, float[] kernel)
        {
            StaticCheckFormat(PixelFormat.Format32bppArgb, srcImg, dstImg);
            StaticCheckSameSize(srcImg, dstImg);

            using (var ibSrc = new BitmapHelper(srcImg))
            using (var ibDest = new BitmapHelper(dstImg))
            {
                var stride = ibSrc.Stride;
                var size = ibSrc.SizeBytes;
                var kw = (uint)Math.Sqrt(kernel.GetLength(0));
                var kh = (uint)kernel.Length / kw;
                unsafe
                {
                    // TODO: Testing only - reference c code
                    //SetImplementationLevel("ConvFilter_32bgra", 0);

                    ImageProcessingWrapper.ConvFilter_32bgra(
                        ibSrc.Start, ibDest.Start, size, stride, kernel, kw, kh);
                }
            }
        }
        private unsafe void ScanlineRenderer(int y, Rectangle dirtyRegion, BitmapHelper frameData)
        {
            byte* currentScanLine = frameData.Start + (y * frameData.Stride);

            // TODO: If top-most layer covering the scanline is 100% opaque
            /*if (objectCollection.Count > 0)
            {
                Layer last = objectCollection.Last;
                if (last.Transparency == 100 &&
                    (ScanlineIntersects(y, last.Region)))
                {
                    CompositeIfNeeded(y, dirtyRegion, currentScanLine, last, rasterizer);
                    return;
                }
            }*/

            // Do a Painter's algorithm iteration (back->front) on the layers
            for (int index = 0; index < objectCollection.Count; index++)
            {
                Layer layer = objectCollection[index];
                CompositeIfNeeded(y, dirtyRegion, currentScanLine, layer);
            }
        }
 private unsafe byte* LayerPixel(Rectangle layerRegion, BitmapHelper layerInfo, int y)
 {
     byte* src = (layerInfo.Start +                                                              // layer data start
                 (y - layerRegion.Top) * layerInfo.Stride) +                                     // image data row
                 (layerRegion.Left < 0 ? layerInfo.PixelSize * Math.Abs(layerRegion.Left) : 0);  // image data column
     return src;
 }
 private unsafe byte* FrameBufferPixel(byte* currentScanLine, int leftOffset, BitmapHelper layerInfo)
 {
     byte* dst = currentScanLine + (leftOffset) * layerInfo.PixelSize; // frame scanline
     return dst;
 }
 private uint DirtySize(int leftOffset, int rightOffset, BitmapHelper layerInfo)
 {
     uint dirtySizeBytes = (uint)((rightOffset - leftOffset) * layerInfo.PixelSize); // size of modified scanline region
     return dirtySizeBytes;
 }
        public void UpdateFrame(SortedContainer<Layer> objectCollection,
                                IRenderingPolicy renderPolicy)
        {
            // Clip the invalidated region to the size of the frame
            renderPolicy.ClipToFrame(frame.Size);

            // Refreh the invalidated frame/region
            profiler.ProfileClearFrame(() =>
            {
                Color clearColor = Color.FromArgb(255, surfaceInfo.GraphicsBackground);
                using (SolidBrush clearBrush = new SolidBrush(clearColor))
                {
                    /*var localPolicy = renderPolicy as MinimalUpdate;
                    if (localPolicy != null && localPolicy.OldRegion != default(Rectangle))
                    {
                        _frameGraphics.FillRectangle(clearBrush, localPolicy.OldRegion);
                    }*/
                    frameGraphics.FillRectangle(clearBrush, renderPolicy.DirtyRegion);
                }
            });

            profiler.ProfileRasterizeObjects(() =>
            {
                using (var frameInfo = new BitmapHelper(frame)) // lock framebuffer data
                using (var rasterizer = new RasterizerStage(objectCollection, surfaceInfo)) // rasterize all scene objects
                using (var compositor = new CompositionStage(objectCollection, rasterizer))
                {
                    // perform scene composition on needed regions
                    compositor.Composite(renderPolicy, frameInfo);
                }
            });

            // Draw the new completed frame/region on the visible area
            profiler.ProfileDrawFrame(() =>
            {
                RefreshFrame(renderPolicy);
            });

            // Notify interested clients with statistics after frame update
            if (graphicsUpdateCallback != null) graphicsUpdateCallback.BeginInvoke(profiler, null, null);
        }
        public static void ImageOpacity(Bitmap srcImg, Bitmap dstImg, float step)
        {
            StaticCheckFormat(PixelFormat.Format32bppArgb, srcImg, dstImg, dstImg);
            StaticCheckSameSize(srcImg, srcImg, dstImg);

            // Less work for caller: let C++ handle threading
            using (var ibSrc = new BitmapHelper(srcImg))
            using (var ibDest = new BitmapHelper(dstImg))
            {
                unsafe
                {
                    ImageProcessingWrapper.OpacityAdjust_32bgra(
                        ibSrc.Start, ibDest.Start, ibDest.SizeBytes, step);
                }
            }
        }