static void Clear32Bpp(IAsyncContext context, IBitmapDataInternal bitmapData, Color32 color, int width)
            {
                int longWidth = bitmapData.RowSize >> 3;

                // writing as longs
                if (longWidth > 0)
                {
                    Color32 rawColor = bitmapData.PixelFormat switch
                    {
                        PixelFormat.Format32bppPArgb => color.ToPremultiplied(),
                        PixelFormat.Format32bppRgb => color.BlendWithBackground(bitmapData.BackColor),
                        _ => color,
                    };

                    uint argb = (uint)rawColor.ToArgb();
                    ClearRaw(context, bitmapData, longWidth, ((ulong)argb << 32) | argb);
                }

                // handling the rest (can be either the last column if width is odd, or even the whole content if RowSize is 0)
                int left = longWidth << 1;

                if (left < width && !context.IsCancellationRequested)
                {
                    ClearDirectFallback(context, bitmapData, color, left);
                }
            }
Пример #2
0
            private Palette?InitializePalette(IReadableBitmapData source, IAsyncContext context)
            {
                using var alg = new TAlg();
                alg.Initialize(quantizer.maxColors, source);
                int width = source.Width;
                IReadableBitmapDataRow row = source.FirstRow;

                context.Progress?.New(DrawingOperation.InitializingQuantizer, source.Height);
                do
                {
                    if (context.IsCancellationRequested)
                    {
                        return(null);
                    }

                    // TODO: parallel if possible
                    for (int x = 0; x < width; x++)
                    {
                        Color32 c = row[x];

                        // handling alpha including full transparency
                        if (c.A != Byte.MaxValue)
                        {
                            c = c.A < quantizer.alphaThreshold ? default : c.BlendWithBackground(quantizer.backColor);
                        }
                        alg.AddColor(c);
                    }
                    context.Progress?.Increment();
                } while (row.MoveNextRow());

                Color32[]? palette = alg.GeneratePalette(context);
                return(context.IsCancellationRequested ? null : new Palette(palette !, quantizer.backColor, quantizer.alphaThreshold));
            }
        public override unsafe void DoSetColor32(int x, Color32 c)
        {
            if (c.A != Byte.MaxValue)
            {
                c = c.A >= BitmapData.AlphaThreshold ? c.BlendWithBackground(BitmapData.BackColor)
                    : c.A < 128 ? c
                    : default;
            }

            ((Color16Argb1555 *)Address)[x] = new Color16Argb1555(c);
        }
Пример #4
0
 public override unsafe void DoSetColor32(int x, Color32 c)
 // performing the quantization to RGB555 before setting as RGB888
 => ((Color24 *)Address)[x] = new Color24(new Color16Rgb555(c.A == Byte.MaxValue ? c : c.BlendWithBackground(BitmapData.BackColor)).ToColor32());
 public override void DoSetColor32(int x, Color32 c)
 => Row[x] = new Color48(c.A == Byte.MaxValue ? c : c.BlendWithBackground(BitmapData.BackColor));
 public override unsafe void DoSetColor32(int x, Color32 c)
 => ((Color16Rgb565 *)Address)[x] = new Color16Rgb565(c.A == Byte.MaxValue ? c : c.BlendWithBackground(BitmapData.BackColor));
Пример #7
0
 public override unsafe void DoSetColor32(int x, Color32 c)
 => ((Color48 *)Address)[x] = (c.A == Byte.MaxValue ? c : c.BlendWithBackground(BitmapData.BackColor)).ToColor48PlatformDependent();
Пример #8
0
        private void PerformDrawWithDithering(IQuantizingSession quantizingSession, IDitheringSession ditheringSession)
        {
            IBitmapDataInternal source = Source;
            IBitmapDataInternal target = Target;
            Point sourceLocation       = SourceRectangle.Location;
            Point targetLocation       = TargetRectangle.Location;
            int   sourceWidth          = SourceRectangle.Width;

            // Sequential processing
            if (ditheringSession.IsSequential || SourceRectangle.Width < parallelThreshold >> ditheringScale)
            {
                context.Progress?.New(DrawingOperation.ProcessingPixels, SourceRectangle.Height);
                for (int y = 0; y < SourceRectangle.Height; y++)
                {
                    if (context.IsCancellationRequested)
                    {
                        return;
                    }
                    ProcessRow(y);
                    context.Progress?.Increment();
                }

                return;
            }

            // Parallel processing
            ParallelHelper.For(context, DrawingOperation.ProcessingPixels, 0, SourceRectangle.Height, ProcessRow);

            #region Local Methods

            void ProcessRow(int y)
            {
                IDitheringSession      session = ditheringSession;
                IBitmapDataRowInternal rowSrc  = source.DoGetRow(sourceLocation.Y + y);
                IBitmapDataRowInternal rowDst  = target.DoGetRow(targetLocation.Y + y);
                int  offsetSrc      = sourceLocation.X;
                int  offsetDst      = targetLocation.X;
                byte alphaThreshold = quantizingSession.AlphaThreshold;
                int  width          = sourceWidth;

                for (int x = 0; x < width; x++)
                {
                    Color32 colorSrc = rowSrc.DoGetColor32(x + offsetSrc);

                    // fully solid source: overwrite
                    if (colorSrc.A == Byte.MaxValue)
                    {
                        rowDst.DoSetColor32(x + offsetDst, session.GetDitheredColor(colorSrc, x, y));
                        continue;
                    }

                    // fully transparent source: skip
                    if (colorSrc.A == 0)
                    {
                        continue;
                    }

                    // source here has a partial transparency: we need to read the target color
                    int     pos      = x + offsetDst;
                    Color32 colorDst = rowDst.DoGetColor32(pos);

                    // non-transparent target: blending
                    if (colorDst.A != 0)
                    {
                        colorSrc = colorDst.A == Byte.MaxValue
                                   // target pixel is fully solid: simple blending
                            ? colorSrc.BlendWithBackground(colorDst)
                                   // both source and target pixels are partially transparent: complex blending
                            : colorSrc.BlendWith(colorDst);
                    }

                    // overwriting target color only if blended color has high enough alpha
                    if (colorSrc.A < alphaThreshold)
                    {
                        continue;
                    }

                    rowDst.DoSetColor32(pos, session.GetDitheredColor(colorSrc, x, y));
                }
            }

            #endregion
        }
Пример #9
0
        internal void PerformDrawDirect()
        {
            IBitmapDataInternal source = Source;
            IBitmapDataInternal target = Target;
            Point sourceLocation       = SourceRectangle.Location;
            Point targetLocation       = TargetRectangle.Location;
            int   sourceWidth          = SourceRectangle.Width;

            // Sequential processing
            if (SourceRectangle.Width < parallelThreshold)
            {
                if (Target.IsFastPremultiplied())
                {
                    context.Progress?.New(DrawingOperation.ProcessingPixels, SourceRectangle.Height);
                    for (int y = 0; y < SourceRectangle.Height; y++)
                    {
                        if (context.IsCancellationRequested)
                        {
                            return;
                        }
                        ProcessRowPremultiplied(y);
                        context.Progress?.Increment();
                    }
                }
                else
                {
                    context.Progress?.New(DrawingOperation.ProcessingPixels, SourceRectangle.Height);
                    for (int y = 0; y < SourceRectangle.Height; y++)
                    {
                        if (context.IsCancellationRequested)
                        {
                            return;
                        }
                        ProcessRowStraight(y);
                        context.Progress?.Increment();
                    }
                }

                return;
            }

            // Parallel processing
            Action <int> processRow = Target.IsFastPremultiplied()
                ? ProcessRowPremultiplied
                : (Action <int>)ProcessRowStraight;

            ParallelHelper.For(context, DrawingOperation.ProcessingPixels, 0, SourceRectangle.Height, processRow);

            #region Local Methods

            void ProcessRowStraight(int y)
            {
                IBitmapDataRowInternal rowSrc = source.DoGetRow(sourceLocation.Y + y);
                IBitmapDataRowInternal rowDst = target.DoGetRow(targetLocation.Y + y);
                int  offsetSrc      = sourceLocation.X;
                int  offsetDst      = targetLocation.X;
                byte alphaThreshold = target.AlphaThreshold;
                int  width          = sourceWidth;

                for (int x = 0; x < width; x++)
                {
                    Color32 colorSrc = rowSrc.DoGetColor32(x + offsetSrc);

                    // fully solid source: overwrite
                    if (colorSrc.A == Byte.MaxValue)
                    {
                        rowDst.DoSetColor32(x + offsetDst, colorSrc);
                        continue;
                    }

                    // fully transparent source: skip
                    if (colorSrc.A == 0)
                    {
                        continue;
                    }

                    // source here has a partial transparency: we need to read the target color
                    int     pos      = x + offsetDst;
                    Color32 colorDst = rowDst.DoGetColor32(pos);

                    // non-transparent target: blending
                    if (colorDst.A != 0)
                    {
                        colorSrc = colorDst.A == Byte.MaxValue
                                   // target pixel is fully solid: simple blending
                            ? colorSrc.BlendWithBackground(colorDst)
                                   // both source and target pixels are partially transparent: complex blending
                            : colorSrc.BlendWith(colorDst);
                    }

                    // overwriting target color only if blended color has high enough alpha
                    if (colorSrc.A < alphaThreshold)
                    {
                        continue;
                    }

                    rowDst.DoSetColor32(pos, colorSrc);
                }
            }

            void ProcessRowPremultiplied(int y)
            {
                IBitmapDataRowInternal rowSrc = source.DoGetRow(sourceLocation.Y + y);
                IBitmapDataRowInternal rowDst = target.DoGetRow(targetLocation.Y + y);
                int offsetSrc = sourceLocation.X;
                int offsetDst = targetLocation.X;
                int width     = sourceWidth;

                for (int x = 0; x < width; x++)
                {
                    Color32 colorSrc = rowSrc.DoGetColor32Premultiplied(x + offsetSrc);

                    // fully solid source: overwrite
                    if (colorSrc.A == Byte.MaxValue)
                    {
                        rowDst.DoSetColor32Premultiplied(x + offsetDst, colorSrc);
                        continue;
                    }

                    // fully transparent source: skip
                    if (colorSrc.A == 0)
                    {
                        continue;
                    }

                    // source here has a partial transparency: we need to read the target color
                    int     pos      = x + offsetDst;
                    Color32 colorDst = rowDst.DoGetColor32Premultiplied(pos);

                    // non-transparent target: blending
                    if (colorDst.A != 0)
                    {
                        colorSrc = colorSrc.BlendWithPremultiplied(colorDst);
                    }

                    rowDst.DoSetColor32Premultiplied(pos, colorSrc);
                }
            }

            #endregion
        }