Strange
Strange

Reputation: 166

Image downscaling is having problem with odd numbers shrinking using nearest neighbor algorithm c#

I am downscaling [1/1, 1/2 upto 1/10] my ByteImage input.Its working fine for even numbers like 1/10,1/2 etc but not working properly for odd numbers like 1/3,1/7 etc. With odd number downscaling lower right side is shifting more towards right creating angle as upper left side is intact.

I am giving target width, height as input for processing

 int width = Math.Max(image.Image.Width / reductionFactor, 1); //target width
 int height = Math.Max(image.Image.Height / reductionFactor, 1); //target height

Where reductionFactor is input from UI, which can be 1/[1 to 10] and image object is reference from custom Image class which have its own width, height properties. I am calling the main image processing method like this below. srcWidth is source or orginal width of the image.

 var byteImage = new ByteImage(width, height, image.Image.PixelFormat,
                        resizePixels(image.Image.Data, image.Image.Width, width, height, reductionFactor, image.Image.PixelFormat), null);

My downscaling method is written like below

 public ImmutableArray<byte> resizePixels(ImmutableArray<byte> data, int srcWidth, int width, int height, int downscalingFactor, 
                ByteImagePixelFormat pixelFormat)
            {
                var builder = ImmutableArray.CreateBuilder<byte>(width * height * pixelFormat.GetBytesPerPixel());
                builder.Count = builder.Capacity;

                int srcIndex = 0;
                int dstIndex = 0;
                int incPixel = (downscalingFactor - 1) * pixelFormat.GetBytesPerPixel() + 1;
                int incLine = (downscalingFactor - 1) * srcWidth * pixelFormat.GetBytesPerPixel();

                switch (pixelFormat)
                {
                     case ByteImagePixelFormat.Rgb:
                        for (int i = 0; i < height; i++)
                        {
                            for (int j = 0; j < width; j++)
                            {
                                builder[dstIndex++] = data[srcIndex++];
                                builder[dstIndex++] = data[srcIndex++];
                                builder[dstIndex++] = data[srcIndex];

                                srcIndex += incPixel;
                            }
                            srcIndex += incLine;
                        }
                        break;

                    case ByteImagePixelFormat.Argb:
                        for (int i = 0; i < height; i++)
                        {
                            for (int j = 0; j < width; j++)
                            {
                                builder[dstIndex++] = data[srcIndex++];
                                builder[dstIndex++] = data[srcIndex++];
                                builder[dstIndex++] = data[srcIndex++];
                                builder[dstIndex++] = data[srcIndex];

                                srcIndex += incPixel;
                            }
                            srcIndex += incLine;
                        }
                        break;
                }
                return builder.ToImmutable();
            }
        }

I found out if I ignore this below line it creates more angle to target image

 int incLine = (downscalingFactor - 1) * srcWidth * pixelFormat.GetBytesPerPixel();

Somewhere I am missing something in calculation while calculating the missing pixels I believe.

Upvotes: 1

Views: 91

Answers (1)

Joker
Joker

Reputation: 534

I believe you are right and have problem in that line only

 int incLine = (downscalingFactor - 1) * srcWidth * pixelFormat.GetBytesPerPixel();

Please try

int incLine = (downscalingFactor - 1) * srcWidth * pixelFormat.GetBytesPerPixel() + (srcWidth - width * downscalingFactor) * pixelFormat.GetBytesPerPixel();

Upvotes: 1

Related Questions