Exemple #1
0
        public void ChangeFormat(ImageBuffer target, IColorQuantizer quantizer, Int32 parallelTaskCount = 4)
        {
            // checks parameters
            Guard.CheckNull(target, "target");
            Guard.CheckNull(quantizer, "quantizer");

            // gathers some information about the target format
            Boolean hasSourceAlpha    = PixelFormat.HasAlpha();
            Boolean hasTargetAlpha    = target.PixelFormat.HasAlpha();
            Boolean isTargetIndexed   = target.PixelFormat.IsIndexed();
            Boolean isSourceDeepColor = PixelFormat.IsDeepColor();
            Boolean isTargetDeepColor = target.PixelFormat.IsDeepColor();

            // prepares the palette if needed
            if (isTargetIndexed)
            {
                // synthetises palette using provided quantizer
                List <Color> targetPalette = SynthetizePalette(quantizer, target.PixelFormat.GetColorCount(), parallelTaskCount);

                // updates the bitmap palette
                target.bitmap.SetPalette(targetPalette);
                target.UpdatePalette(true);
            }

            // prepares the quantization function
            TransformPixelFunction changeFormat = (passIndex, sourcePixel, targetPixel) =>
            {
                // if both source and target formats are deep color formats, copies a value directly
                if (isSourceDeepColor && isTargetDeepColor)
                {
                    //UInt64 value = sourcePixel.Value;
                    //targetPixel.SetValue(value);
                }
                else
                {
                    // retrieves a source image color
                    Color color = sourcePixel.GetColor();

                    // if alpha is not present in the source image, but is present in the target, make one up
                    if (!hasSourceAlpha && hasTargetAlpha)
                    {
                        Int32 argb = 255 << 24 | color.R << 16 | color.G << 8 | color.B;
                        color = Color.FromArgb(argb);
                    }

                    // sets the color to a target pixel
                    targetPixel.SetColor(color, quantizer);
                }

                // allows to write (obviously) the transformed pixel
                return(true);
            };

            // generates the target image
            IList <Point> standardPath = new StandardPathProvider().GetPointPath(Width, Height);

            TransformPerPixelBase(target, standardPath, parallelTaskCount, changeFormat);
        }
        public void Quantize(ImageBuffer target, IColorQuantizer quantizer, IColorDitherer ditherer, Int32 colorCount, Int32 parallelTaskCount = 4)
        {
            // checks parameters
            Guard.CheckNull(target, "target");
            Guard.CheckNull(quantizer, "quantizer");

            // initializes quantization parameters
            Boolean isTargetIndexed = target.PixelFormat.IsIndexed();

            // prepares the palette if needed
            List<Color> targetPalette = isTargetIndexed ? SynthetizePalette(quantizer, colorCount, parallelTaskCount) : null;

            // updates the bitmap palette
            target.bitmap.SetPalette(targetPalette);
            target.UpdatePalette(true);

            // prepares ditherer (optional)
            if (ditherer != null) ditherer.Prepare(quantizer, colorCount, this, target);

            // prepares the quantization function
            TransformPixelFunction quantize = (passIndex, sourcePixel, targetPixel) =>
            {
                // reads the pixel color
                Color color = sourcePixel.GetColor();

                // converts alpha to solid color
                color = QuantizationHelper.ConvertAlpha(color);

                // quantizes the pixel
                targetPixel.SetColor(color, quantizer);

                // marks pixel as processed by default
                Boolean result = true;

                // preforms inplace dithering (optional)
                if (ditherer != null && ditherer.IsInplace)
                {
                    result = ditherer.ProcessPixel(passIndex, sourcePixel, targetPixel);
                }

                // returns the result
                return result;
            };

            // generates the target image
            IList<Point> path = quantizer.GetPointPath(Width, Height);
            TransformPerPixelBase(target, path, parallelTaskCount, quantize);

            // preforms non-inplace dithering (optional)
            if (ditherer != null && !ditherer.IsInplace)
            {
                Dither(target, ditherer, quantizer, colorCount, 1);
            }

            // finishes the dithering (optional)
            if (ditherer != null) ditherer.Finish();

            // cleans up the quantizer
            quantizer.Finish();
        }
        public void ChangeFormat(ImageBuffer target, IColorQuantizer quantizer, Int32 parallelTaskCount = 4)
        {
            // checks parameters
            Guard.CheckNull(target, "target");
            Guard.CheckNull(quantizer, "quantizer");

            // gathers some information about the target format
            Boolean hasSourceAlpha = PixelFormat.HasAlpha();
            Boolean hasTargetAlpha = target.PixelFormat.HasAlpha();
            Boolean isTargetIndexed = target.PixelFormat.IsIndexed();
            Boolean isSourceDeepColor = PixelFormat.IsDeepColor();
            Boolean isTargetDeepColor = target.PixelFormat.IsDeepColor();

            // prepares the palette if needed
            if (isTargetIndexed)
            {
                // synthetises palette using provided quantizer
                List<Color> targetPalette = SynthetizePalette(quantizer, target.PixelFormat.GetColorCount(), parallelTaskCount);

                // updates the bitmap palette
                target.bitmap.SetPalette(targetPalette);
                target.UpdatePalette(true);
            }

            // prepares the quantization function
            TransformPixelFunction changeFormat = (passIndex, sourcePixel, targetPixel) =>
            {
                // if both source and target formats are deep color formats, copies a value directly
                if (isSourceDeepColor && isTargetDeepColor)
                {
                    //UInt64 value = sourcePixel.Value;
                    //targetPixel.SetValue(value);
                }
                else
                {
                    // retrieves a source image color
                    Color color = sourcePixel.GetColor();

                    // if alpha is not present in the source image, but is present in the target, make one up
                    if (!hasSourceAlpha && hasTargetAlpha)
                    {
                        Int32 argb = 255 << 24 | color.R << 16 | color.G << 8 | color.B;
                        color = Color.FromArgb(argb);
                    }

                    // sets the color to a target pixel
                    targetPixel.SetColor(color, quantizer);
                }

                // allows to write (obviously) the transformed pixel
                return true;
            };

            // generates the target image
            IList<Point> standardPath = new StandardPathProvider().GetPointPath(Width, Height);
            TransformPerPixelBase(target, standardPath, parallelTaskCount, changeFormat);
        }
        private void TransformPerPixelBase(ImageBuffer target, IList<Point> path = null, Int32 parallelTaskCount = 4, params Delegate[] passes)
        {
            // checks parameters
            Guard.CheckNull(target, "target");
            Guard.CheckNull(passes, "passes");

            // creates internal quantizer if needed
            UpdatePalette();
            target.UpdatePalette();

            // checks the dimensions
            if (Width != target.Width || Height != target.Height)
            {
                const String message = "Both images have to have the same dimensions.";
                throw new ArgumentOutOfRangeException(message);
            }

            // determines mode
            Boolean isAdvanced = passes.Length > 0 && passes[0] is TransformPixelAdvancedFunction;

            // creates default path, if none is available
            if (path == null) path = StandardPathProvider.CreatePath(Width, Height);

            // process the image in a parallel manner
            Action<LineTask> transformPerPixel = lineTask =>
            {
                // creates individual pixel structures per task
                Pixel sourcePixel = CreatePixel();
                Pixel targetPixel = target.CreatePixel();
                Delegate pass = passes[lineTask.PassIndex];

                // enumerates the pixels row by row
                for (Int32 pathOffset = lineTask.StartOffset; pathOffset < lineTask.EndOffset; pathOffset++)
                {
                    Point point = path[pathOffset];
                    Boolean allowWrite;

                    // enumerates the pixel, and returns the control to the outside
                    sourcePixel.Update(point.X, point.Y);
                    targetPixel.Update(point.X, point.Y);

                    // when read is allowed, retrieves current value (in bytes)
                    if (CanRead) ReadPixel(sourcePixel);
                    if (target.CanRead) target.ReadPixel(targetPixel);

                    // process the pixel by custom user operation
                    if (isAdvanced)
                    {
                        TransformPixelAdvancedFunction transformAdvancedFunction = (TransformPixelAdvancedFunction) pass;
                        allowWrite = transformAdvancedFunction(lineTask.PassIndex, sourcePixel, targetPixel, this, target);
                    }
                    else // use simplified version with pixel parameters only
                    {
                        TransformPixelFunction transformFunction = (TransformPixelFunction) pass;
                        allowWrite = transformFunction(lineTask.PassIndex, sourcePixel, targetPixel);
                    }

                    // when write is allowed, copies the value back to the row buffer
                    if (target.CanWrite && allowWrite) target.WritePixel(targetPixel);
                }
            };

            // transforms image per pixel
            for (Int32 passIndex = 0; passIndex < passes.Length; passIndex++)
            {
                ProcessInParallel(passIndex, transformPerPixel, path, parallelTaskCount);
            }
        }
Exemple #5
0
        public void Quantize(ImageBuffer target, IColorQuantizer quantizer, IColorDitherer ditherer, Int32 colorCount, Int32 parallelTaskCount = 4)
        {
            // checks parameters
            Guard.CheckNull(target, "target");
            Guard.CheckNull(quantizer, "quantizer");

            // initializes quantization parameters
            Boolean isTargetIndexed = target.PixelFormat.IsIndexed();

            // prepares the palette if needed
            List <Color> targetPalette = isTargetIndexed ? SynthetizePalette(quantizer, colorCount, parallelTaskCount) : null;

            // updates the bitmap palette
            target.bitmap.SetPalette(targetPalette);
            target.UpdatePalette(true);

            // prepares ditherer (optional)
            if (ditherer != null)
            {
                ditherer.Prepare(quantizer, colorCount, this, target);
            }

            // prepares the quantization function
            TransformPixelFunction quantize = (passIndex, sourcePixel, targetPixel) =>
            {
                // reads the pixel color
                Color color = sourcePixel.GetColor();

                // converts alpha to solid color
                color = QuantizationHelper.ConvertAlpha(color);

                // quantizes the pixel
                targetPixel.SetColor(color, quantizer);

                // marks pixel as processed by default
                Boolean result = true;

                // preforms inplace dithering (optional)
                if (ditherer != null && ditherer.IsInplace)
                {
                    result = ditherer.ProcessPixel(passIndex, sourcePixel, targetPixel);
                }

                // returns the result
                return(result);
            };

            // generates the target image
            IList <Point> path = quantizer.GetPointPath(Width, Height);

            TransformPerPixelBase(target, path, parallelTaskCount, quantize);

            // preforms non-inplace dithering (optional)
            if (ditherer != null && !ditherer.IsInplace)
            {
                Dither(target, ditherer, quantizer, colorCount, 1);
            }

            // finishes the dithering (optional)
            if (ditherer != null)
            {
                ditherer.Finish();
            }

            // cleans up the quantizer
            quantizer.Finish();
        }
Exemple #6
0
        private void TransformPerPixelBase(ImageBuffer target, IList <Point> path = null, Int32 parallelTaskCount = 4, params Delegate[] passes)
        {
            // checks parameters
            Guard.CheckNull(target, "target");
            Guard.CheckNull(passes, "passes");

            // creates internal quantizer if needed
            UpdatePalette();
            target.UpdatePalette();

            // checks the dimensions
            if (Width != target.Width || Height != target.Height)
            {
                const String message = "Both images have to have the same dimensions.";
                throw new ArgumentOutOfRangeException(message);
            }

            // determines mode
            Boolean isAdvanced = passes.Length > 0 && passes[0] is TransformPixelAdvancedFunction;

            // creates default path, if none is available
            if (path == null)
            {
                path = StandardPathProvider.CreatePath(Width, Height);
            }

            // process the image in a parallel manner
            Action <LineTask> transformPerPixel = lineTask =>
            {
                // creates individual pixel structures per task
                Pixel    sourcePixel = CreatePixel();
                Pixel    targetPixel = target.CreatePixel();
                Delegate pass        = passes[lineTask.PassIndex];

                // enumerates the pixels row by row
                for (Int32 pathOffset = lineTask.StartOffset; pathOffset < lineTask.EndOffset; pathOffset++)
                {
                    Point   point = path[pathOffset];
                    Boolean allowWrite;

                    // enumerates the pixel, and returns the control to the outside
                    sourcePixel.Update(point.X, point.Y);
                    targetPixel.Update(point.X, point.Y);

                    // when read is allowed, retrieves current value (in bytes)
                    if (CanRead)
                    {
                        ReadPixel(sourcePixel);
                    }
                    if (target.CanRead)
                    {
                        target.ReadPixel(targetPixel);
                    }

                    // process the pixel by custom user operation
                    if (isAdvanced)
                    {
                        TransformPixelAdvancedFunction transformAdvancedFunction = (TransformPixelAdvancedFunction)pass;
                        allowWrite = transformAdvancedFunction(lineTask.PassIndex, sourcePixel, targetPixel, this, target);
                    }
                    else // use simplified version with pixel parameters only
                    {
                        TransformPixelFunction transformFunction = (TransformPixelFunction)pass;
                        allowWrite = transformFunction(lineTask.PassIndex, sourcePixel, targetPixel);
                    }

                    // when write is allowed, copies the value back to the row buffer
                    if (target.CanWrite && allowWrite)
                    {
                        target.WritePixel(targetPixel);
                    }
                }
            };

            // transforms image per pixel
            for (Int32 passIndex = 0; passIndex < passes.Length; passIndex++)
            {
                ProcessInParallel(passIndex, transformPerPixel, path, parallelTaskCount);
            }
        }