I am trying to built a program which reads a tiff file, selects a number of pages.
extracts those pages and will put it in a List
the Original tiffs have a TiffCompressOption.Ccitt4 compression.
after extracting x pages from different files, I want to rebuild the tiff using tifflib.
However when i create the tiff, the pages are not visible (probably broken) with the same compression. When I rebuild it with another comrpression (LZW AND Photometrix on RGB). It works, only the tiffs are 10 times as big.
The code is under.:
public bool CreateTiff(List<Bitmap> listBitmap, string fileName)
{
int numberOfPages = listBitmap.Count;
using (Tiff output = Tiff.Open(fileName, "w"))
{
for (int page = 0; page < numberOfPages; ++page)
{
// get bufferData
var bmp = listBitmap[page];
byte[] raster = getImageRasterBytes(bmp, PixelFormat.Format32bppArgb);
output.SetField(TiffTag.IMAGEWIDTH, bmp.Width);
output.SetField(TiffTag.IMAGELENGTH, bmp.Height);
output.SetField(TiffTag.COMPRESSION, Compression.CCITT_T6);
output.SetField(TiffTag.PHOTOMETRIC, Photometric.MINISBLACK);
output.SetField(TiffTag.ROWSPERSTRIP, bmp.Height);
output.SetField(TiffTag.XRESOLUTION, bmp.HorizontalResolution);
output.SetField(TiffTag.YRESOLUTION, bmp.VerticalResolution);
output.SetField(TiffTag.BITSPERSAMPLE, 8);
output.SetField(TiffTag.SAMPLESPERPIXEL, 4);
output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
output.SetField(TiffTag.EXTRASAMPLES, 1, new short[] { (short)ExtraSample.UNASSALPHA });
output.SetField(TiffTag.PAGENUMBER, page, numberOfPages + 1);
int stride = raster.Length / bmp.Height;
convertSamples(raster, bmp.Width, bmp.Height);
for (int i = 0, offset = 0; i < bmp.Height; i++)
{
output.WriteScanline(raster, offset, i, 0);
offset += stride;
}
output.WriteDirectory();
}
}
Process.Start(fileName);
return true;
}
private static void convertSamples(byte[] data, int width, int height)
{
int stride = data.Length / height;
const int samplesPerPixel = 4;
for (int y = 0; y < height; y++)
{
int offset = stride * y;
int strideEnd = offset + width * samplesPerPixel;
for (int i = offset; i < strideEnd; i += samplesPerPixel)
{
byte temp = data[i + 2];
data[i + 2] = data[i];
data[i] = temp;
}
}
}
private static byte[] getImageRasterBytes(Bitmap bmp, PixelFormat format)
{
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
byte[] bits = null;
try
{
// Lock the managed memory
BitmapData bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, format);
// Declare an array to hold the bytes of the bitmap.
bits = new byte[bmpdata.Stride * bmpdata.Height];
// Copy the values into the array.
System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, bits, 0, bits.Length);
// Release managed memory
bmp.UnlockBits(bmpdata);
}
catch
{
return null;
}
return bits;
}
Related
I am new in working with Bitmap and using 16 bits per pixel Format16bppRgb555;
I want to Extract RGB Values from Bitmap Data. Here is my code
static void Main(string[] args)
{
BitmapRGBValues();
Console.ReadKey();
}
static unsafe void BitmapRGBValues()
{
Bitmap cur = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format16bppRgb555);
//Capture Screen
var screenBounds = Screen.PrimaryScreen.Bounds;
using (var gfxScreenshot = Graphics.FromImage(cur))
{
gfxScreenshot.CopyFromScreen(screenBounds.X, screenBounds.Y, 0, 0, screenBounds.Size, CopyPixelOperation.SourceCopy);
}
var curBitmapData = cur.LockBits(new Rectangle(0, 0, cur.Width, cur.Height),
ImageLockMode.ReadWrite, PixelFormat.Format16bppRgb555);
try
{
byte* scan0 = (byte*)curBitmapData.Scan0.ToPointer();
for (int y = 0; y < cur.Height; ++y)
{
ulong* curRow = (ulong*)(scan0 + curBitmapData.Stride * y);
for (int x = 0; x < curBitmapData.Stride / 8; ++x)
{
ulong pixel = curRow[x];
//How to get RGB Values from pixel;
}
}
}
catch
{
}
finally
{
cur.UnlockBits(curBitmapData);
}
}
LockBits can actually convert your image to a desired pixel format, meaning no further conversion should be needed. Just lock the image as Format32bppArgb and you can simply take your colour values from single bytes.
BitmapData curBitmapData = cur.LockBits(new Rectangle(0, 0, cur.Width, cur.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Int32 stride = curBitmapData.Stride;
Byte[] data = new Byte[stride * cur.Height];
Marshal.Copy(curBitmapData.Scan0, data, 0, data.Length);
cur.UnlockBits(curBitmapData);
With this code, you end up with the byte array data, which is filled with your image data in ARGB format, meaning the colour component bytes will be in there in the order [B, G, R, A]. Note that the stride is the amount of bytes to skip to get to a next line on the image, and since this is not always equal to "width * bytes per pixel", it should always be taken into account.
Now you got that, you can do whatever you want with it...
Int32 curRowOffs = 0;
for (Int32 y = 0; y < cur.Height; y++)
{
// Set offset to start of current row
Int32 curOffs = curRowOffs;
for (Int32 x = 0; x < cur.Width; x++)
{
// ARGB = bytes [B,G,R,A]
Byte b = data[curOffs];
Byte g = data[curOffs + 1];
Byte r = data[curOffs + 2];
Byte a = data[curOffs + 3];
Color col = Color.FromArgb(a, r, g, b);
// Do whatever you want with your colour here
// ...
// Increase offset to next colour
curOffs += 4;
}
// Increase row offset
curRowOffs += stride;
}
You can even edit the bytes, and then build a new image from them if you want.
I am trying to combine 3 grayscale bitmaps into one color bitmap. All three grayscale images are the same size (this is based off of data from the Hubble). My logic is:
Load "blue" image and convert to PixelFormat.Format24bppRgb. Based off of that create a new byte array that is 4 times as large as the blue data array length/3 (so it will be one byte for blue, one byte for green, one byte for red, one byte for alpha per pixel since my system is little endian). Populate the "blue" bytes of the array from the "blue" bytes of the blue image (and in this first loop set the alpha byte to 255). I then load the green and red bitmaps, convert them to PixelFormat.Format24bppRgb, and pull the g/r value and add it to the correct place in the data array. The final data array then has the bgra bytes set correctly from what I can tell.
When I have the data array populated, I have used it to:
Create a PixelFormats.Bgra32 BitmapSource then convert that to a Bitmap.
Create a PixelFormat.Format32bppArgb Bitmap using the Bitmap constructor (width, height, stride, PixelForma, IntPtr)
Create a PixelFormat.Format32bppArgb Bitmap using pointers
All three ways of creating a return bitmap result in the image being "skewed" (sorry, I don't know of a better word).
The actual output (of all three ways of generating the final bitmap) is: Actual output
The desired output is something like (this was done in photoshop so it is slightly different): Desired output
The three file names (_blueFileName, _greenFileName, _redFileName) are set in the constructor and I check to make sure the files exist before creating the class. I can post that code if anyone wants it.
Can anyone tell me what I am doing wrong? I am guessing that is is due to the stride or something like that?
Note: I can't post the links to the images I am using as input as I don't have 10 reputation points. Maybe I could send the links via email or something if someone wants them as well.
Here is my code (with some stuff commented out, the comments describe what happens if each commented out block is used instead):
public Bitmap Merge()
{
// Load original "blue" bitmap.
Bitmap tblueBitmap = (Bitmap)Image.FromFile(_blueFileName);
int width = tblueBitmap.Width;
int height = tblueBitmap.Height;
// Convert to 24 bpp rgb (which is bgr on little endian machines)
Bitmap blueBitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
using (Graphics gr = Graphics.FromImage(blueBitmap))
{
gr.DrawImage(tblueBitmap, 0, 0, width, height);
}
tblueBitmap.Dispose();
// Lock and copy to byte array.
BitmapData blueData = blueBitmap.LockBits(new Rectangle(0, 0, blueBitmap.Width, blueBitmap.Height), ImageLockMode.ReadOnly,
blueBitmap.PixelFormat);
int numbBytes = blueData.Stride*blueBitmap.Height;
byte[] blueBytes = new byte[numbBytes];
Marshal.Copy(blueData.Scan0, blueBytes, 0, numbBytes);
blueBitmap.UnlockBits(blueData);
blueData = null;
blueBitmap.Dispose();
int mult = 4;
byte[] data = new byte[(numbBytes/3)*mult];
int count = 0;
// Copy every third byte starting at 0 to the final data array (data).
for (int i = 0; i < data.Length / mult; i++)
{
// Check for overflow
if (blueBytes.Length <= count*3 + 2)
{
continue;
}
// First pass, set Alpha channel.
data[i * mult + 3] = 255;
// Set blue byte.
data[i*mult] = blueBytes[count*3];
count++;
}
// Cleanup.
blueBytes = null;
int generation = GC.GetGeneration(this);
GC.Collect(generation);
Bitmap tgreenBitmap = (Bitmap)Image.FromFile(_greenFileName);
Bitmap greenBitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
using (Graphics gr = Graphics.FromImage(greenBitmap))
{
gr.DrawImage(tgreenBitmap, 0, 0, width, height);
}
tgreenBitmap.Dispose();
BitmapData greenData = greenBitmap.LockBits(new Rectangle(0, 0, greenBitmap.Width, greenBitmap.Height), ImageLockMode.ReadOnly,
greenBitmap.PixelFormat);
numbBytes = greenData.Stride * greenBitmap.Height;
byte[] greenBytes = new byte[numbBytes];
Marshal.Copy(greenData.Scan0, greenBytes, 0, numbBytes);
greenBitmap.UnlockBits(greenData);
greenData = null;
greenBitmap.Dispose();
count = 0;
for (int i = 0; i < data.Length / mult; i++)
{
if (greenBytes.Length <= count * 3 + 1)
{
continue;
}
// Set green byte
data[i * mult + 1] = greenBytes[count * 3 + 1];
count++;
}
greenBytes = null;
generation = GC.GetGeneration(this);
GC.Collect(generation);
Bitmap tredBitmap = (Bitmap)Image.FromFile(_redFileName);
Bitmap redBitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
using (Graphics gr = Graphics.FromImage(redBitmap))
{
gr.DrawImage(tredBitmap, 0, 0, width, height);
}
tredBitmap.Dispose();
BitmapData redData = redBitmap.LockBits(new Rectangle(0, 0, redBitmap.Width, redBitmap.Height), ImageLockMode.ReadOnly,
redBitmap.PixelFormat);
numbBytes = redData.Stride * redBitmap.Height;
byte[] redBytes = new byte[numbBytes];
Marshal.Copy(redData.Scan0, redBytes, 0, numbBytes);
redBitmap.UnlockBits(redData);
redData = null;
redBitmap.Dispose();
count = 0;
for (int i = 0; i < data.Length / mult; i++)
{
if (redBytes.Length <= count * 3+2)
{
count++;
continue;
}
// set red byte
data[i * mult + 2] = redBytes[count * 3 + 2];
count++;
}
redBytes = null;
generation = GC.GetGeneration(this);
GC.Collect(generation);
int stride = (width*32 + 7)/8;
var bi = BitmapSource.Create(width, height, 96, 96, PixelFormats.Bgra32, null, data, stride);
// uncomment out below to see what a bitmap source to bitmap does. So far, it is exactly the same as
// the uncommented out lines below.
// ---------------------------------------------------------------------------------------------------
//return BitmapImage2Bitmap(bi);
unsafe
{
fixed (byte* p = data)
{
IntPtr ptr = (IntPtr)p;
// Trying the commented out lines returns the same bitmap as the uncommented out lines.
// ------------------------------------------------------------------------------------
byte* p2 = (byte*)ptr;
Bitmap retBitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
BitmapData fData = retBitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);
unsafe
{
for (int i = 0; i < fData.Height; i++)
{
byte* imgPtr = (byte*)(fData.Scan0 + (fData.Stride * i));
for (int x = 0; x < fData.Width; x++)
{
for (int ii = 0; ii < 4; ii++)
{
*imgPtr++ = *p2++;
}
//*imgPtr++ = 255;
}
}
}
retBitmap.UnlockBits(fData);
//Bitmap retBitmap = new Bitmap(width, height, GetStride(width, PixelFormat.Format32bppArgb),
// PixelFormat.Format32bppArgb, ptr);
return retBitmap;
}
}
}
private Bitmap BitmapImage2Bitmap(BitmapSource bitmapSrc)
{
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapSrc));
enc.Save(outStream);
Bitmap bitmap = new Bitmap(outStream);
return new Bitmap(bitmap);
}
}
private int GetStride(int width, PixelFormat pxFormat)
{
int bitsPerPixel = ((int)pxFormat >> 8) & 0xFF;
int validBitsPerLine = width * bitsPerPixel;
int stride = ((validBitsPerLine + 31) / 32) * 4;
return stride;
}
You are missing the gap between the lines. The Stride value is not the amount of data in a line, it's the distance between the start of one line to the next. There may be a gap at the end of each line to align the next line on an even address boundary.
The Stride value can even be negative, then the image is stored upside down in memory. To get the data without the gaps and to handle all cases you need to copy one line at a time:
BitmapData blueData = blueBitmap.LockBits(new Rectangle(0, 0, blueBitmap.Width, blueBitmap.Height), ImageLockMode.ReadOnly, blueBitmap.PixelFormat);
int lineBytes = blueBitmap.Width * 3;
int numbBytes = lineBytes * blueBitmap.Height;
byte[] blueBytes = new byte[numbBytes];
for (int y = 0; y < blueBitmap.Height; y++) {
Marshal.Copy(blueData.Scan0 + y * blueData.Stride, blueBytes, y * lineBytes, lineBytes);
}
blueBitmap.UnlockBits(blueData);
blueBitmap.Dispose();
im trying to convert one of fully functional desktop apps to a Windows phone app, i was managed to convert most of the things..but one function is not working due to some syntax error.anyone know replacements for
GetPixel,
FromArgb,
SetPixel,
MemoryStream,
Marshal,
ImageLockMode,
PixelFormat
the code is this
private void tresh()
{
int hight = image1.Source.Height;
int width = image1.Source.Width;
BitmapImage img = new BitmapImage(image1.Source);
BitmapImage newImg = new BitmapImage(width, hight);
int threshold = 0;
for (int i = 0; i < hight; i++)
{
for (int j = 0; j < width; j++)
{
int grayScale = (int)((img.GetPixel(j, i).R * 0.3) + (img.GetPixel(j, i).G * 0.59) + (img.GetPixel(j, i).B * 0.11));
Color nc = Color.FromArgb(grayScale, grayScale, grayScale);
newImg.SetPixel(j, i, nc);
}
}
image1.Source = newImg;
MemoryStream ms = new MemoryStream();
newImg.Save(ms, ImageFormat.Bmp);
byte[] bmpBytes = ms.GetBuffer();
threshold = getOtsuNumber(bmpBytes);
byte[] newBytArr = new byte[bmpBytes.Length];
for (int i = 0; i < bmpBytes.Length; i++)
{
if ((0xFF & bmpBytes[i]) >= threshold)
{
newBytArr[i] = ((byte)255);
}
else
{
newBytArr[i] = ((byte)0);
}
}
BitmapImage oldBmp = newImg;
width = oldBmp.Width;
int height = oldBmp.Height;
BitmapData oldData = oldBmp.LockBits(
new Rectangle(0, 0, oldBmp.Width, oldBmp.Height),
ImageLockMode.WriteOnly,
oldBmp.PixelFormat);
int length = oldData.Stride * oldBmp.Height;
byte[] stream = new byte[length];
Marshal.Copy(oldData.Scan0, stream, 0, length);
oldBmp.UnlockBits(oldData);
BitmapImage bmp = new Bitmap(width, height, oldBmp.PixelFormat);
BitmapData bmpData = bmp.LockBits(
new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly,
bmp.PixelFormat);
for (int n = 0; n < length; n++)
{
if ((0xFF & stream[n]) >= 57)
{
Marshal.WriteByte(bmpData.Scan0, n, ((byte)255));
}
else
{
Marshal.WriteByte(bmpData.Scan0, n, ((byte)0));
}
}
bmp.UnlockBits(bmpData);
image1.Source = bmp;
}
you have to change the type int into byte
By using this WriteableBitmapEx GetPixel and SetPixel method extensions can be used
What is the fastest way to get column of pixels from bitmap?
I don't consider two loops because it could take to long. I will appreciate for any idea. Thanks!
I would suggest to convert your bitmap into a vector of bytes using the following code:
Bitmpa myImage=new Bitmap("myImage.bmp");
BitmapData bmpData1=myImage.LockBits(new Rectangle(0,0,myImage.Width,myImage.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite, myImage.PixelFormat);
byte[] myImageData = new byte[bmpData1.Stride * bmpData1.Height];
System.Runtime.InteropServices.Marshal.Copy(bmpData1.Scan0,myImageData,0
,myImageData.Length);
myImgage.UnlockBits(bmpData1);
Then it becomes easy to retrieve the pixels on the column you want. Just loop through the vector myImageData with a step equals to the number of pixels per rows * the number of bytes per pixel.
Just be careful about the number of bytes per pixel are used for the representation of your bitmap.
This depends on the PixelFormat .
Assuming you only need a single column, the following routines should help you.
First here is the standard solution using verifiable C# code
static Color[] GetPixelColumn(Bitmap bmp, int x)
{
Color[] pixelColumn = new Color[bmp.Height];
for (int i = 0; i < bmp.Height; ++i)
{
pixelColumn[i] = bmp.GetPixel(x, i);
}
return pixelColumn;
}
Here is a faster alternative, but this requires that you enable unsafe support for the C# compiler
static Color[] GetPixelColumnFast(Bitmap bmp, int x)
{
Color[] pixelColumn = new Color[bmp.Height];
BitmapData pixelData = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
unsafe
{
int* pData = (int*)pixelData.Scan0.ToPointer();
pData += x;
for (int i = 0; i < bmp.Height; ++i)
{
pixelColumn[i] = Color.FromArgb(*pData);
pData += bmp.Width;
}
}
bmp.UnlockBits(pixelData);
return pixelColumn;
}
Both functions will return a Color array with the colors of the pixels for a specific column in the bitmap.
Convert it to a array of bytes
private static byte[, ,] BitmapToBytes(Bitmap bitmap)
{
BitmapData bitmapData =
bitmap.LockBits(new Rectangle(new Point(), bitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
byte[] bitmapBytes;
var stride = bitmapData.Stride;
try
{
int byteCount = bitmapData.Stride * bitmap.Height;
bitmapBytes = new byte[byteCount];
Marshal.Copy(bitmapData.Scan0, bitmapBytes, 0, byteCount);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
byte[, ,] result = new byte[3, bitmap.Width, bitmap.Height];
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < bitmap.Width; i++)
{
for (int j = 0; j < bitmap.Height; j++)
{
result[k, i, j] = bitmapBytes[j * stride + i * 3 + k];
}
}
}
return result;
}
struct BitmapDataAccessor
{
private readonly byte[] data;
private readonly int[] rowStarts;
public readonly int Height;
public readonly int Width;
public BitmapDataAccessor(byte[] data, int width, int height)
{
this.data = data;
this.Height = height;
this.Width = width;
rowStarts = new int[height];
for (int y = 0; y < Height; y++)
rowStarts[y] = y * width;
}
public byte this[int x, int y, int color] // Maybe use an enum with Red = 0, Green = 1, and Blue = 2 members?
{
get { return data[(rowStarts[y] + x) * 3 + color]; }
set { data[(rowStarts[y] + x) * 3 + color] = value; }
}
public byte[] Data
{
get { return data; }
}
}
public static byte[, ,] Bitmap2Byte(Bitmap obraz)
{
int h = obraz.Height;
int w = obraz.Width;
byte[, ,] wynik = new byte[w, h, 3];
BitmapData bd = obraz.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
int bytes = Math.Abs(bd.Stride) * h;
byte[] rgbValues = new byte[bytes];
IntPtr ptr = bd.Scan0;
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
BitmapDataAccessor bda = new BitmapDataAccessor(rgbValues, w, h);
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
wynik[j, i, 0] = bda[j, i, 2];
wynik[j, i, 1] = bda[j, i, 1];
wynik[j, i, 2] = bda[j, i, 0];
}
}
obraz.UnlockBits(bd);
return wynik;
}
public static Bitmap Byte2Bitmap(byte[, ,] tablica)
{
if (tablica.GetLength(2) != 3)
{
throw new NieprawidlowyWymiarTablicyException();
}
int w = tablica.GetLength(0);
int h = tablica.GetLength(1);
Bitmap obraz = new Bitmap(w, h, PixelFormat.Format24bppRgb);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
Color kol = Color.FromArgb(tablica[i, j, 0], tablica[i, j, 1], tablica[i, j, 2]);
obraz.SetPixel(i, j, kol);
}
}
return obraz;
}
Now, if I do:
private void btnLoad_Click(object sender, EventArgs e)
{
if (dgOpenFile.ShowDialog() == DialogResult.OK)
{
try
{
Bitmap img = new Bitmap(dgOpenFile.FileName);
byte[, ,] tab = Grafika.Bitmap2Byte(img);
picture.Image = Grafika.Byte2Bitmap(tab);
picture.Size = img.Size;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Most of pictures are handled correctly butsome not.
Example of picture that doesn't work:
(source: ifotos.pl)
It produce following result (this is only fragment of picture) :
(source: ifotos.pl)
Why is that?
You need to account for BitmapData.Stride when you access the data.
EDIT:
Here is a solution that I use to copy a DirectX surface to a Bitmap. The idea is the same, but you'll need to modify it slightly. I copy one scanline of the image at a time with a call to RtlMoveMemory (P/Invoke to kernel32.dll)
//// Snippet
int pitch;
int bytesPerPixel = 4;
Rectangle lockRectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
// Lock the bitmap
GraphicsStream surfacedata = surface.LockRectangle(LockFlags.ReadOnly, out pitch);
BitmapData bitmapdata = bitmap.LockBits(lockRectangle, ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);
// Copy surface to bitmap
for (int scanline = 0; scanline < bitmap.Height; ++scanline)
{
byte* dest = (byte*)bitmapdata.Scan0 + (scanline * bitmap.Width * bytesPerPixel);
byte* source = (byte*)surfacedata.InternalData + (scanline * pitch);
RtlMoveMemory(new IntPtr(dest), new IntPtr(source), (bitmap.Width * bytesPerPixel));
}
////
EDIT #2:
Check this out: Stride/Pitch Tutorial
It is all aimed at DirectX but the concept is the same.
It seems the memory allocated for bitmaps must be aligned on a 32-bit boundary and so there is possibly padding on some of the images due to their size. As you have a 24-bit pixel here then some line widths will end on a 32-bit others will not. You need to use the following formula to work out the padding being used and then account for it:
int padding = bd.Stride - (((w * 24) + 7) / 8);
You might want to load your byte array using GetPixel(x,y) rather than going through the whole transform to byte array before you start reading pixels.
Thanx to #Lazarus and tbridge I managed how to do this.
First we need to calculate padding in Bitmap2Byte:
int padding = bd.Stride - (((w * 24) + 7) / 8);
and pass it to BitmapDataAccessor and modify the line
this.Width = width;
to
this.Width = width + (4-padding)%4;
That's all. Thanx guys.