internal static bool IsFastPremultiplied(this IBitmapData bitmapData) { PixelFormat pixelFormat = bitmapData.PixelFormat; return(pixelFormat == PixelFormat.Format32bppPArgb || pixelFormat.IsPremultiplied() && (!(bitmapData is NativeBitmapDataBase) || ColorExtensions.Max16BppValue == UInt16.MaxValue)); }
private static void AdjustQuantizerAndDitherer(IBitmapData target, ref IQuantizer quantizer, ref IDitherer ditherer) { if (quantizer != null || ditherer == null) { return; } if (target.PixelFormat.CanBeDithered()) { quantizer = PredefinedColorsQuantizer.FromBitmapData(target); } else { ditherer = null; } }
private static bool HasAlpha(this IBitmapData bitmapData) { PixelFormat pixelFormat = bitmapData.PixelFormat; return(pixelFormat.HasAlpha() || pixelFormat.IsIndexed() && bitmapData.Palette?.HasAlpha == true); }
internal static Size GetSize(this IBitmapData bitmapData) => bitmapData == null ? default : new Size(bitmapData.Width, bitmapData.Height);
internal static bool HasMultiLevelAlpha(this IBitmapData bitmapData) { PixelFormat pixelFormat = bitmapData.PixelFormat; return(pixelFormat.HasMultiLevelAlpha() || pixelFormat.IsIndexed() && bitmapData.Palette?.HasMultiLevelAlpha == true); }
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++; } }
public void Initialize(int requestedColors, IBitmapData source) { maxColors = requestedColors; root = new ColorBucket(source.Width * source.Height); }
public void Initialize(int requestedColors, IBitmapData source) => maxColors = requestedColors;
public BitmapShot(IBitmapData bitmapData) => BitmapData = bitmapData;
internal DitheringSessionRaster(IQuantizingSession quantizer, ErrorDiffusionDitherer ditherer, IBitmapData source) { this.quantizer = quantizer; this.ditherer = ditherer; ImageWidth = source.Width; imageHeight = source.Height; byBrightness = ditherer.byBrightness ?? quantizer.Palette?.IsGrayscale ?? false; // Initializing a circular buffer for the diffused errors. // This helps to minimize used memory because it needs only a few lines to be stored. // Another solution could be to store resulting colors instead of just the errors but then the color // entries would be clipped not just in the end but in every iteration, and small errors would be lost // that could stack up otherwise. // See also the ErrorDiffusionDitherer constructor for more comments on why using floats. errorsBuffer = new CircularList <(float, float, float)[]>(ditherer.matrixHeight);