private static IReadWriteBitmapData?DoLoadBitmapData(IAsyncContext context, Stream stream)
        {
            context.Progress?.New(DrawingOperation.Loading, 1000);
            var reader = new BinaryReader(stream);

            if (reader.ReadInt32() != magicNumber)
            {
                throw new ArgumentException(Res.ImagingNotBitmapDataStream, nameof(stream));
            }
            var     size           = new Size(reader.ReadInt32(), reader.ReadInt32());
            var     pixelFormat    = (PixelFormat)reader.ReadInt32();
            Color32 backColor      = Color32.FromArgb(reader.ReadInt32());
            byte    alphaThreshold = reader.ReadByte();

            Palette?palette       = null;
            int     paletteLength = reader.ReadInt32();

            if (paletteLength > 0)
            {
                var entries = new Color32[paletteLength];
                for (int i = 0; i < paletteLength; i++)
                {
                    entries[i] = Color32.FromArgb(reader.ReadInt32());
                }
                palette = new Palette(entries, backColor, alphaThreshold);
            }

            context.Progress?.SetProgressValue((int)(stream.Position * 1000 / stream.Length));
            if (context.IsCancellationRequested)
            {
                return(null);
            }

            IBitmapDataInternal result = CreateManagedBitmapData(size, pixelFormat, backColor, alphaThreshold, palette);
            int  bpp      = pixelFormat.ToBitsPerPixel();
            bool canceled = false;

            try
            {
                IBitmapDataRowInternal row = result.DoGetRow(0);
                for (int y = 0; y < result.Height; y++)
                {
                    if (canceled = context.IsCancellationRequested)
                    {
                        return(null);
                    }

                    switch (bpp)
                    {
                    case 32:
                        for (int x = 0; x < result.Width; x++)
                        {
                            row.DoWriteRaw(x, reader.ReadInt32());
                        }
                        break;

                    case 16:
                        for (int x = 0; x < result.Width; x++)
                        {
                            row.DoWriteRaw(x, reader.ReadInt16());
                        }
                        break;

                    case 64:
                        for (int x = 0; x < result.Width; x++)
                        {
                            row.DoWriteRaw(x, reader.ReadInt64());
                        }
                        break;

                    default:
                        for (int x = 0; x < result.RowSize; x++)
                        {
                            row.DoWriteRaw(x, reader.ReadByte());
                        }
                        break;
                    }

                    row.MoveNextRow();
                    context.Progress?.SetProgressValue((int)(stream.Position * 1000 / stream.Length));
                }

                return((canceled = context.IsCancellationRequested) ? null : result);
            }
            finally
            {
                if (canceled)
                {
                    result.Dispose();
                }
            }
        }
Example #2
0
 public OptimizedPaletteQuantizerSession(OptimizedPaletteQuantizer quantizer, IReadableBitmapData source, IAsyncContext context)
 {
     this.quantizer = quantizer;
     Palette        = InitializePalette(source, context);
 }
Example #3
0
 internal Palette(Palette palette, Color32 backColor, byte alphaThreshold)
     : this(palette.Entries, backColor, alphaThreshold, palette.customGetNearestColorIndex)
 {
 }
Example #4
0
        /// <summary>
        /// Creates a managed <see cref="IBitmapDataInternal"/> with the specified <paramref name="size"/> and <paramref name="pixelFormat"/>.
        /// </summary>
        internal static IBitmapDataInternal CreateManagedBitmapData(Size size, PixelFormat pixelFormat = PixelFormat.Format32bppArgb, Color32 backColor = default, byte alphaThreshold = 128, Palette palette = null)
        {
            if (pixelFormat.IsIndexed() && palette != null)
            {
                int maxColors = 1 << pixelFormat.ToBitsPerPixel();
                if (palette.Count > maxColors)
                {
                    throw new ArgumentException(Res.ImagingPaletteTooLarge(maxColors, pixelFormat), nameof(palette));
                }
            }

            Debug.Assert(palette == null || backColor.ToOpaque() == palette.BackColor && alphaThreshold == palette.AlphaThreshold);
            switch (pixelFormat)
            {
            case PixelFormat.Format32bppArgb:
                return(new ManagedBitmapData <Color32, ManagedBitmapDataRow32Argb>(size, pixelFormat));

            case PixelFormat.Format32bppPArgb:
                return(new ManagedBitmapData <Color32, ManagedBitmapDataRow32PArgb>(size, pixelFormat));

            case PixelFormat.Format32bppRgb:
                return(new ManagedBitmapData <Color32, ManagedBitmapDataRow32Rgb>(size, pixelFormat, backColor, alphaThreshold));

            case PixelFormat.Format24bppRgb:
                return(new ManagedBitmapData <Color24, ManagedBitmapDataRow24Rgb>(size, pixelFormat, backColor, alphaThreshold));

            case PixelFormat.Format8bppIndexed:
                return(new ManagedBitmapData <byte, ManagedBitmapDataRow8I>(size, pixelFormat, backColor, alphaThreshold, palette));

            case PixelFormat.Format4bppIndexed:
                return(new ManagedBitmapData <byte, ManagedBitmapDataRow4I>(size, pixelFormat, backColor, alphaThreshold, palette));

            case PixelFormat.Format1bppIndexed:
                return(new ManagedBitmapData <byte, ManagedBitmapDataRow1I>(size, pixelFormat, backColor, alphaThreshold, palette));

            case PixelFormat.Format64bppArgb:
                return(new ManagedBitmapData <Color64, ManagedBitmapDataRow64Argb>(size, pixelFormat));

            case PixelFormat.Format64bppPArgb:
                return(new ManagedBitmapData <Color64, ManagedBitmapDataRow64PArgb>(size, pixelFormat));

            case PixelFormat.Format48bppRgb:
                return(new ManagedBitmapData <Color48, ManagedBitmapDataRow48Rgb>(size, pixelFormat, backColor, alphaThreshold));

            case PixelFormat.Format16bppRgb565:
                return(new ManagedBitmapData <Color16Rgb565, ManagedBitmapDataRow16Rgb565>(size, pixelFormat, backColor, alphaThreshold));

            case PixelFormat.Format16bppRgb555:
                return(new ManagedBitmapData <Color16Rgb555, ManagedBitmapDataRow16Rgb555>(size, pixelFormat, backColor, alphaThreshold));

            case PixelFormat.Format16bppArgb1555:
                return(new ManagedBitmapData <Color16Argb1555, ManagedBitmapDataRow16Argb1555>(size, pixelFormat, backColor, alphaThreshold));

            case PixelFormat.Format16bppGrayScale:
                return(new ManagedBitmapData <Color16Gray, ManagedBitmapDataRow16Gray>(size, pixelFormat, backColor, alphaThreshold));

            default:
                throw new ArgumentOutOfRangeException(nameof(pixelFormat), Res.PixelFormatInvalid(pixelFormat));
            }
        }
Example #5
0
        internal static IBitmapDataInternal CreateBitmapData(Bitmap bitmap, ImageLockMode lockMode, Color32 backColor = default, byte alphaThreshold = 128, Palette palette = null)
        {
            if (bitmap == null)
            {
                throw new ArgumentNullException(nameof(bitmap), PublicResources.ArgumentNull);
            }
            if (!lockMode.IsDefined())
            {
                throw new ArgumentOutOfRangeException(nameof(lockMode), PublicResources.EnumOutOfRange(lockMode));
            }
            Debug.Assert(palette == null || backColor.ToOpaque() == palette.BackColor && alphaThreshold == palette.AlphaThreshold);

            var pixelFormat = bitmap.PixelFormat;

            switch (pixelFormat)
            {
            case PixelFormat.Format32bppArgb:
                return(new NativeBitmapData <NativeBitmapDataRow32Argb>(bitmap, pixelFormat, lockMode));

            case PixelFormat.Format32bppPArgb:
                return(new NativeBitmapData <NativeBitmapDataRow32PArgb>(bitmap, pixelFormat, lockMode));

            case PixelFormat.Format32bppRgb:
                return(new NativeBitmapData <NativeBitmapDataRow32Rgb>(bitmap, pixelFormat, lockMode, backColor, alphaThreshold));

            case PixelFormat.Format24bppRgb:
                return(new NativeBitmapData <NativeBitmapDataRow24Rgb>(bitmap, pixelFormat, lockMode, backColor, alphaThreshold));

            case PixelFormat.Format8bppIndexed:
                return(new NativeBitmapData <NativeBitmapDataRow8I>(bitmap, pixelFormat, lockMode, backColor, alphaThreshold, palette));

            case PixelFormat.Format4bppIndexed:
                return(new NativeBitmapData <NativeBitmapDataRow4I>(bitmap, pixelFormat, lockMode, backColor, alphaThreshold, palette));

            case PixelFormat.Format1bppIndexed:
                return(new NativeBitmapData <NativeBitmapDataRow1I>(bitmap, pixelFormat, lockMode, backColor, alphaThreshold, palette));

            case PixelFormat.Format64bppArgb:
                return(new NativeBitmapData <NativeBitmapDataRow64Argb>(bitmap, pixelFormat, lockMode));

            case PixelFormat.Format64bppPArgb:
                return(new NativeBitmapData <NativeBitmapDataRow64PArgb>(bitmap, pixelFormat, lockMode));

            case PixelFormat.Format48bppRgb:
                return(new NativeBitmapData <NativeBitmapDataRow48Rgb>(bitmap, pixelFormat, lockMode, backColor, alphaThreshold));

            case PixelFormat.Format16bppRgb565:
                return(OSUtils.IsWindows
                        ? (NativeBitmapDataBase) new NativeBitmapData <NativeBitmapDataRow16Rgb565>(bitmap, pixelFormat, lockMode, backColor, alphaThreshold)
                        : new NativeBitmapData <NativeBitmapDataRow16Rgb565Via24Bpp>(bitmap, PixelFormat.Format24bppRgb, lockMode, backColor, alphaThreshold));

            case PixelFormat.Format16bppRgb555:
                return(OSUtils.IsWindows
                        ? (NativeBitmapDataBase) new NativeBitmapData <NativeBitmapDataRow16Rgb555>(bitmap, pixelFormat, lockMode, backColor, alphaThreshold)
                        : new NativeBitmapData <NativeBitmapDataRow16Rgb555Via24Bpp>(bitmap, PixelFormat.Format24bppRgb, lockMode, backColor, alphaThreshold));

            case PixelFormat.Format16bppArgb1555:
                return(new NativeBitmapData <NativeBitmapDataRow16Argb1555>(bitmap, pixelFormat, lockMode, backColor, alphaThreshold));

            case PixelFormat.Format16bppGrayScale:
                return(new NativeBitmapData <NativeBitmapDataRow16Gray>(bitmap, pixelFormat, lockMode, backColor, alphaThreshold));

            default:
                throw new InvalidOperationException(Res.InternalError($"Unexpected pixel format {pixelFormat}"));
            }
        }
Example #6
0
        /// <summary>
        /// Creates a managed <see cref="IReadWriteBitmapData"/> with the specified <paramref name="size"/>, <paramref name="pixelFormat"/> and <paramref name="palette"/>.
        /// <br/>See the <strong>Remarks</strong> section for details.
        /// </summary>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="size"/> or <paramref name="pixelFormat"/> has an invalid value.</exception>
        /// <exception cref="ArgumentException"><paramref name="palette"/> contains too many colors for the indexed format specified by <paramref name="pixelFormat"/>.</exception>
        /// <param name="size">The size of the bitmap data to create.</param>
        /// <param name="pixelFormat">The desired pixel format of the bitmap data to create.</param>
        /// <param name="palette">If <paramref name="pixelFormat"/> specifies an indexed format, then specifies the desired <see cref="IBitmapData.Palette"/> of the returned <see cref="IReadWriteBitmapData"/> instance.
        /// It determines also the <see cref="IBitmapData.BackColor"/> and <see cref="IBitmapData.AlphaThreshold"/> properties of the result.</param>
        /// <returns>A managed <see cref="IReadWriteBitmapData"/> with the specified <paramref name="size"/>, <paramref name="pixelFormat"/> and <paramref name="palette"/>.</returns>
        /// <remarks>
        /// <para>All possible <see cref="PixelFormat"/>s are supported, regardless of the native <see cref="Bitmap"/> support of the current operating system.
        /// <note>When <paramref name="pixelFormat"/> specifies a wide-color format (48/64 bit or 16 bit grayscale), then the returned instance will use the full 16-bit range of the color channels.
        /// This means a different raw content to Windows' wide-color <see cref="Bitmap"/> instances, which use 13-bit channels. But this difference is transparent in most cases
        /// unless we access actual raw content by the <see cref="IReadableBitmapDataRow.ReadRaw{T}">ReadRaw</see> and <see cref="IWritableBitmapDataRow.WriteRaw{T}">WriteRaw</see> methods.</note></para>
        /// <para>If <paramref name="palette"/> is not specified, then a default palette will be used for indexed formats, and a default <see cref="IBitmapData.BackColor"/> and <see cref="IBitmapData.AlphaThreshold"/>
        /// value will be used.</para>
        /// <note type="tip">
        /// <list type="bullet">
        /// <item>You can use the <see cref="BitmapDataExtensions.ToBitmap">ToBitmap</see> extension method to convert the created <see cref="IReadWriteBitmapData"/> to a <see cref="Bitmap"/> instance.</item>
        /// <item>To create an <see cref="IReadWriteBitmapData"/> instance from a native <see cref="Bitmap"/> use the <see cref="BitmapExtensions.GetReadWriteBitmapData">GetReadWriteBitmapData</see> extension method.</item>
        /// </list></note>
        /// </remarks>
        /// <seealso cref="CreateBitmapData(Size, PixelFormat, Color32, byte)"/>
        /// <seealso cref="BitmapDataExtensions.ToBitmap"/>
        /// <seealso cref="BitmapExtensions.GetReadableBitmapData"/>
        /// <seealso cref="BitmapExtensions.GetWritableBitmapData"/>
        /// <seealso cref="BitmapExtensions.GetReadWriteBitmapData"/>
        public static IReadWriteBitmapData CreateBitmapData(Size size, PixelFormat pixelFormat, Palette palette)
        {
            if (size.Width < 1 || size.Height < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(size), PublicResources.ArgumentOutOfRange);
            }
            if (!pixelFormat.IsValidFormat())
            {
                throw new ArgumentOutOfRangeException(nameof(pixelFormat), Res.PixelFormatInvalid(pixelFormat));
            }

            return(CreateManagedBitmapData(size, pixelFormat, palette?.BackColor ?? default, palette?.AlphaThreshold ?? 128, palette));
        }
Example #7
0
        internal ManagedBitmapData(Size size, PixelFormat pixelFormat, Color32 backColor = default, byte alphaThreshold = 0, Palette palette = null)
        {
            Debug.Assert(size.Width > 0 && size.Height > 0, "Non-empty size expected");
            Debug.Assert(pixelFormat.IsValidFormat(), "Valid format expected");
            Debug.Assert(!pixelFormat.IsIndexed() || typeof(TColor) == typeof(byte), "For indexed pixel formats byte elements are expected");

            BackColor = pixelFormat.HasMultiLevelAlpha() ? default : backColor.ToOpaque();
                        AlphaThreshold = alphaThreshold;
                        PixelFormat    = pixelFormat;
                        Width          = size.Width;

                        // Unlike native bitmaps our stride have 1 byte alignment so Stride = (Width * bpp + 7) / 8)
                        int bpp       = pixelFormat.ToBitsPerPixel();
                        int byteWidth = pixelFormat.GetByteWidth(size.Width);

                        RowSize = byteWidth;
                        Buffer  = new Array2D <TColor>(size.Height, bpp <= 8 ? byteWidth : size.Width);
                        if (!pixelFormat.IsIndexed())
                        {
                            return;
                        }

                        if (palette != null)
                        {
                            Debug.Assert(palette.Entries.Length <= (1 << bpp), "Too many colors");
                            Palette = palette;
                            return;
                        }

                        // if there was no palette specified we use a default one
                        Palette = pixelFormat switch
                        {
                            PixelFormat.Format8bppIndexed => Palette.SystemDefault8BppPalette(backColor, alphaThreshold),
                            PixelFormat.Format4bppIndexed => Palette.SystemDefault4BppPalette(backColor),
                            _ => Palette.SystemDefault1BppPalette(backColor)
                        };
        }