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;
}
}