예제 #1
0
            internal override void Initialize(Bitmap source, bool isInUse)
            {
                // this must be the first line to prevent disposing source if next lines fail
                isSourceCloned = isInUse;
                PixelFormat origPixelFormat = source.PixelFormat;
                PixelFormat pixelFormat     = origPixelFormat.HasAlpha() || origPixelFormat.IsIndexed() && source.Palette.Entries.Any(c => c.A != Byte.MaxValue)
                    ? PixelFormat.Format32bppPArgb
                    : PixelFormat.Format24bppRgb;

                targetBitmap     = new Bitmap(Size.Width, Size.Height, pixelFormat);
                targetBitmapData = targetBitmap.GetReadWriteBitmapData();

                // Locking on source image to avoid "bitmap region is already locked" if the UI is painting the image when we clone it.
                // This works this way because UI can repaint the image any time and is also locks the image for that period.
                // Another solution could be if we used a clone of the original image but it is better to avoid using multiple clones.
                if (isInUse)
                {
                    // if image is in use (in the view of this VM) we lock it only for a short time to prevent the UI freezing
                    lock (source)
                        sourceBitmap = source.CloneCurrentFrame();
                }
                else
                {
                    // If no direct use could be detected using a long-term lock to spare a clone.
                    // It is still needed because the image still can be used in the main V/VM.
                    Monitor.Enter(source);
                    sourceBitmap = source;
                }

                sourceBitmapData = sourceBitmap.GetReadableBitmapData();
            }
예제 #2
0
        protected static void GenerateAlphaGradient(IReadWriteBitmapData bitmapData)
        {
            var   firstRow = bitmapData.FirstRow;
            float ratio    = 255f / (bitmapData.Width / 6f);
            float limit    = bitmapData.Width / 6f;

            for (int x = 0; x < bitmapData.Width; x++)
            {
                // red -> yellow
                if (x < limit)
                {
                    firstRow[x] = new Color32(255, (x * ratio).ClipToByte(), 0);
                }
                // yellow -> green
                else if (x < limit * 2)
                {
                    firstRow[x] = new Color32((255 - (x - limit) * ratio).ClipToByte(), 255, 0);
                }
                // green -> cyan
                else if (x < limit * 3)
                {
                    firstRow[x] = new Color32(0, 255, ((x - limit * 2) * ratio).ClipToByte());
                }
                // cyan -> blue
                else if (x < limit * 4)
                {
                    firstRow[x] = new Color32(0, (255 - (x - limit * 3) * ratio).ClipToByte(), 255);
                }
                // blue -> magenta
                else if (x < limit * 5)
                {
                    firstRow[x] = new Color32(((x - limit * 4) * ratio).ClipToByte(), 0, 255);
                }
                // magenta -> red
                else
                {
                    firstRow[x] = new Color32(255, 0, (255 - (x - limit * 5) * ratio).ClipToByte());
                }
            }

            if (bitmapData.Height < 2)
            {
                return;
            }

            var row = bitmapData[1];

            ratio = 255f / bitmapData.Height;
            do
            {
                byte a = (255 - row.Index * ratio).ClipToByte();
                for (int x = 0; x < bitmapData.Width; x++)
                {
                    row[x] = Color32.FromArgb(a, firstRow[x]);
                }
            } while (row.MoveNextRow());
        }
        public void CopyToClippedTest(PixelFormat pixelFormat)
        {
            using IReadableBitmapData src = Icons.Information.ExtractBitmap(new Size(256, 256)).ConvertPixelFormat(pixelFormat).GetReadableBitmapData();
            Size targetSize = new Size(128, 128);

            using IReadWriteBitmapData dst = BitmapDataFactory.CreateBitmapData(targetSize, pixelFormat);

            new PerformanceTest {
                CpuAffinity = null, Iterations = 10_000
            }
예제 #4
0
            internal override void SetCompleted()
            {
                sourceBitmapData?.Dispose();
                sourceBitmapData = null;
                if (isSourceCloned)
                {
                    sourceBitmap?.Dispose();
                }
                else if (sourceBitmap != null)
                {
                    Monitor.Exit(sourceBitmap);
                }
                sourceBitmap = null;

                targetBitmapData?.Dispose();
                targetBitmapData = null;
                base.SetCompleted();
            }
예제 #5
0
 internal override void SetCompleted()
 {
     BitmapData?.Dispose();
     BitmapData = null;
     base.SetCompleted();
 }
예제 #6
0
 internal override void Initialize(Bitmap source, bool isInUse)
 {
     lock (source)
         result = source.CloneCurrentFrame();
     BitmapData = result.GetReadWriteBitmapData();
 }
예제 #7
0
        internal ClippedBitmapData(IBitmapData source, Rectangle clippingRegion)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            region = clippingRegion;

            // source is already clipped: unwrapping to prevent tiered nesting (not calling Unwrap because other types should not be extracted here)
            if (source is ClippedBitmapData parent)
            {
                BitmapData = parent.BitmapData;
                region.Offset(parent.region.Location);
                region.Intersect(parent.region);
            }
            else
            {
                BitmapData = source;
                region.Intersect(new Rectangle(Point.Empty, source.GetSize()));
            }

            if (region.IsEmpty)
            {
                throw new ArgumentOutOfRangeException(nameof(clippingRegion), PublicResources.ArgumentOutOfRange);
            }

            bitmapDataType = BitmapData switch
            {
                IBitmapDataInternal _ => BitmapDataType.Internal,
                IReadWriteBitmapData _ => BitmapDataType.ReadWrite,
                IReadableBitmapData _ => BitmapDataType.Readable,
                IWritableBitmapData _ => BitmapDataType.Writable,
                                    _ => BitmapDataType.None
            };

            PixelFormat    = BitmapData.PixelFormat;
            BackColor      = BitmapData.BackColor;
            AlphaThreshold = BitmapData.AlphaThreshold;
            Palette        = BitmapData.Palette;
            int bpp = PixelFormat.ToBitsPerPixel();

            int maxRowSize = (region.Width * bpp) >> 3;
            RowSize = region.Left > 0
                      // Any clipping from the left disables raw access because ReadRaw/WriteRaw offset depends on size of T,
                      // which will fail for any T whose size is not the same as the actual pixel size
                ? 0
                      // Even one byte padding is disabled to protect the right edge of a region by default
                : Math.Min(source.RowSize, maxRowSize);

            if (bpp >= 8 || RowSize < maxRowSize)
            {
                return;
            }

            // 1/4bpp: Adjust RowSize if needed
            // right edge: if not at byte boundary but that is the right edge of the original image, then we allow including padding
            if (PixelFormat.IsAtByteBoundary(region.Width) && region.Right == BitmapData.Width)
            {
                RowSize++;
            }
        }