0

I have this simple class to plot points on an image. It is limited to 24bbp. but at certain widths the image breaks, colors are distorted and the image moves towards the right the lower down in the image it gets. its only correct when the width is a multiple of 4 and I cant figure out why. can someone please point out my mistake? Thanks guys. Example of problem

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using static System.Math;

    public class TImage
    {
        private readonly Bitmap source = null;
        private IntPtr Iptr = IntPtr.Zero;
        private BitmapData bitmapData = null;
        private bool locked = false;
        private readonly int PixelCount;
        private byte[] pixels;
        public int Width { get; private set; }
        public int Height { get; private set; }

        public TImage(int width, int height)
        {
            source = new Bitmap(width, height, PixelFormat.Format24bppRgb);
            Width = width; Height = height;
            PixelCount = Width * Height;
        }

        public TImage(Bitmap image)
        {
            if (image.PixelFormat != PixelFormat.Format24bppRgb) throw new FormatException("Only 24bppRgb can be used");
            source = image;
            Width = source.Width; Height = source.Height;
            PixelCount = Width * Height;
        }

        private void Lock()
        {
            if (!locked)
            {
                Rectangle rect = new Rectangle(0, 0, Width, Height);
                bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

                // create byte array to copy pixel values
                pixels = new byte[PixelCount * 3];
                Iptr = bitmapData.Scan0;

                // Copy data from pointer to array
                Marshal.Copy(Iptr, pixels, 0, pixels.Length);
                locked = true;
            }
        }

        private void Unlock()
        {
            if (locked)
            {
                Marshal.Copy(pixels, 0, Iptr, pixels.Length);
                source.UnlockBits(bitmapData);
                locked = false;
            }
        }

        public Color GetPixel(int x, int y)
        {
            if (!locked) Lock();

            // Get start index of the pixel
            int i = (y * Width + x) * 3;

            if (i+2 > pixels.Length || i <0) throw new IndexOutOfRangeException();
            byte b = pixels[i];
            byte g = pixels[i + 1];
            byte r = pixels[i + 2];
            return Color.FromArgb(r, g, b);
        }

        public void SetPixel(int x, int y, Color color)
        {
            if (!locked) Lock();
            int i = ((y * Width + x) * 3);
            if (i + 2 < pixels.Length && i >= 0)
            {
                pixels[i] = color.B;
                pixels[i + 1] = color.G;
                pixels[i + 2] = color.R;
            }
        }

        public void SetPixel(double x, double y, Color color)
        {
            SetPixel((int)Round(x), (int)Round(y), color);
        }

        public static implicit operator Bitmap(TImage img)
        {
            img.Unlock();
            return img.source;
        }
    }
  • 1
    You assume [stride](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.imaging.bitmapdata.stride?view=windowsdesktop-5.0) = width, but this is mostly not the case. – Steeeve Nov 06 '21 at 00:14
  • @Steeeve So there may be padding on each line? ok ill see if i can fugure that out, thanks – aceofjohnonlone Nov 06 '21 at 00:20
  • Exactly. The scanlines will be padded, you'll need only to allocate your pixel array accordingly and take care that the stride can also be negative. – Steeeve Nov 06 '21 at 00:22
  • awsome so ive changed it to (int i = (y * bitmapData.Stride) + (x * 3);) – aceofjohnonlone Nov 06 '21 at 00:24
  • The stride is the width of a line in bytes but it's negative for bottom-up images. So your pixel array should be something like `pixels = new byte[Math.Abs(stride) * height]` – Steeeve Nov 06 '21 at 00:33
  • brilliant Thank you so much – aceofjohnonlone Nov 06 '21 at 00:37

0 Answers0