Attempted to read or write protected memory - image manipulation - c#

I have this code;
BitmapData bdBackground = Background.LockBits(new Rectangle(0, 0, Background.Width,
Background.Height), ImageLockMode.ReadWrite, Background.PixelFormat);
BitmapData bdForeground = videoFrame.LockBits(new Rectangle(0, 0, videoFrame.Width,
videoFrame.Height), ImageLockMode.ReadWrite, videoFrame.PixelFormat);
unsafe
{
for (int x = 0; x < videoFrame.Width; x++)
{
byte* columnBackground = (byte*)bdBackground.Scan0 + (x * bdBackground.Stride);
byte* columnForeground = (byte*)bdForeground.Scan0 + (x * bdForeground.Stride);
for (int y = 0; y < videoFrame.Height; y++)
{
if (columnBackground[x * pixelSize] == columnForeground[x * pixelSize])
{
columnForeground[x] = 0;
}
}
}
}
Background.UnlockBits(bdBackground);
videoFrame.UnlockBits(bdForeground);
it gives me error;
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
in if (columnBackground[x * pixelSize] == columnForeground[x * pixelSize])
what is the reason for that? I take this code from here

First, you need to understand how an image is stored in an array.
Images "usually in most APIs" are row major, meaning they are stored row by row (usually in a one dimensional array).
To loop through a row major image (walk the pixels), the outer loop is usually from 0 to height, and the inner from 0 to width. This makes the loops easier to read, and increases cache hits.
Stride is a very important concept, it represents the number of bytes needed for each row, and is not necessarily equal to the width*bytes per pixel, as padding for alignment reasons is usually present.
Stride is used to access a new row, for example, if I want to access the third row:
third_Row = 3 * image_stride;
If you want to access the 10th pixel of the third row, you just add (10 * bytes per pixel) to third_Row:
third_Row_Tenth_Pixel = 3 * image_stride + 10 * Bytes_per_pixel
NOTE: please mark the above does not apply to any image where bits per pixel are lower than 8, usually 4, 2, or 1 are used.
What you are doing is the reverse, you are multiplying the column number by the stride, instead of the row number, effectively, stepping out of the range of the image.
In short, reverse the x and y loops, making the y one contain the x one(for reasons of increasing cache hits):
unsafe
{
for (int y = 0; y < videoFrame.Height; y++)
{
byte* columnBackground = (byte*)bdBackground.Scan0 + (y * bdBackground.Stride);
byte* columnForeground = (byte*)bdForeground.Scan0 + (y * bdForeground.Stride);
for (int x = 0; x < videoFrame.Width; x++)
{
if (columnBackground[x * pixelSize] == columnForeground[x * pixelSize])
{
columnForeground[x] = 0;
}
}
}
}
Background.UnlockBits(bdBackground);
videoFrame.UnlockBits(bdForeground);

You never use the y variable when accessing the bitmap array. You should be multiplying y by the Stride instead of x. Then add x * pixelSize like you are doing.

Related

incrementing unsigned char *image

void draw(unsigned char *image)
{
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
{
if (someCondition)
{
int red = x * 256 / WIDTH;
int green = 255;
int blue = y * 256 / HEIGHT;
image[0] = (unsigned char)blue;
image[1] = (unsigned char)green;
image[2] = (unsigned char)red;
}
else
{
image[0] = 0;
image[1] = 0;
image[2] = 0;
}
image += 3;
}
}
}
What does incrementing image+=3; actually do here. I'm trying to convert the same c++ code to C#, but unable to achieve this. I'm using byte[] image in C#, now how should I do image+=3 in C#. Is it scaling the image?
From the code it is evident that the pointer points to an element of an array of unsigned char:
[ ][ ][ ][ ] ........... [ ]
^
|
image
Next consider that image[i] is equivalent (really equivalent, that is how it is defined) to *(image + i), ie it increments the pointer by i and dereferences it. You can write image[0] to get the element image points to. You can type image[1] to get the next element in the array.
Lets call the actual array x then you can access its elements via incrementing image like this:
x[0] x[1] x[2] x[3] x[4] x[5]
image[0] image[1] image[2]
(image+3)[0] (image+3)[1] (image+3)[2]
In other words, the author could have used some offset in the outer loop which increments by 3 in each iteration and then instead of image[ i ] they would have used image[ i + offset ]. Instead they choose to increment image which has the same effect.
Here is your code in C# with comments which hopefully help understand what is done.
I highly recommend reading this article about image strides.
I read in the comments that each pixel has 3-byte which is why it is incremented by 3... while this might be true for some images, it is overall wrong. The bytes per pixel are depended on the pixel format of the image. you image can have 1-byte per pixel, 2-byte per pixel, 3-byte per pixel, 4-byte per pixel. The byte per pixel are also known as Color depth.
using System;
using System.Linq;
using System.Drawing;
using System.Drawing.Imaging;
namespace something
{
void draw(Bitmap bmp)
{
BitmapData data = null;
try {
// Returns an object of type BitmapData.
// BitmapData object grants you access
// to the address of the first pixel.
data = bmp.UnlockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadWrite,
bmp.PixelFormat);
unsafe {
// Byte per pixel.
// This is really import!
// By checking how many bytes a pixel consumes
// you know how to increment your raw pixel data.
int bpp = Bitmap.GetPixelFormatSize(data.PixelFormat) / 8;
// Pointer to the first pixel.
byte* ptFirst = (byte*)data.Scan0;
// Using a parallel loop here
// drastically improves performance.
Parallel.For(0, data.Height, y =>
{
// Get the pointer of the first pixel
// in the current stride.
// If you imagine your image as a table with
// rows and columns, then this is the 'index'
// of the row.
// Images are built from multiple strides (rows).
byte* pixel = ptFirst + (y * data.Stride);
// IMPORTANT: Incrementing by byte-per-pixel
// is crucial here as you need to skip n-bytes
// to get to the next pixel.
// The pixel count per stride is the
// width multiplied by byte-per-pixel.
for (int x=0; x<data.Stride; x+=bpp)
{
if (someCondition) {
// Calc some colour values.
byte r = (byte)(x*256/data.Width);
byte g = byte.MaxValue;
byte b = (byte)(y*256/data.Height);
// Assign colour.
pixel[x+2]=r;
pixel[x+1]=g;
pixel[x+0]=b;
}
else {
// Set pixel to black.
pixel[x+2]=0;
pixel[x+1]=0;
pixel[x+0]=0;
}
}
}
}
}
finally {
if (null != data) {
bmp.UnlockBits(data);
}
}
}
}

OpenCV: cv::Mat fails to create a matrix out of seemingly valid data

I am using OpenCV for android in my project to process a YUV420 (https://wiki.videolan.org/YUV/#NV12) image. As the rest of the project is in C#, I am using GCHandles to copy an array of bytes to the C++ code. I have made sure that the data are OK in C++ by making a sum of all the bytes both in C# and C++ and comparing them. However, when I try this:
int foo(unsigned char * inputPtr, int width, int height) {
cv::InputArray input_image = cv::Mat(height + height /2, width, CV_8UC1, inputPtr);
int res = 0;
for (int y = 0; y < input_image.rows(); y++) {
for (int x = 0; x < input_image.cols(); x++) {
res += (int)input_image.getMat().ptr(x + y * input_image.cols());
}
}
return res;
}
, zero is returned every time (the C# count still returns correct numbers). The sum of all bytes that returns correct values looks like this:
int foo(unsigned char * inputPtr, int width, int height) {
int res = 0;
for (int i = 0; i < width * height * 1.5f; i++) {
res += (int)inputPtr[i];
}
return res;
}
The cv::Mat() arguments should be correct based on this question: Converting from YUV colour space to RGB using OpenCV
What reason could OpenCV have to decide not to create a matrix out of seemingly valid data?
EDIT: Forgot to add that the inputPtr pointer points to a C# byte[] with the size of (int)(camBytes.Width * camBytes.Height * 1.5f).
Ptr return pointer but no value. Use at():
res += (int)input_image.getMat().at<uchar>(y, x);

Out of memory exception in reading a 1.5 GB tile-base Tiff file using LibTiff.Net

I tried to read and write a 1.5 GB tiled Tiff file using LibTiff.Net library as it's declared that support BigTiff (>4 GB) image files. I wrote the code below but get an error in line "buffer[tiles]..." which throws out of memory exception. I would appreciate developers who can help me to solve this problem.
using (Tiff input = Tiff.Open(#"E:\active folder\Sample_04.tif", "r"))
{
int width = input.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
int height = input.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
int tileWidth = input.GetField(TiffTag.TILEWIDTH)[0].ToInt();
int tileLentgh = input.GetField(TiffTag.TILELENGTH)[0].ToInt();
int samplesPerPixel = input.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt();
int bitsPerSample = input.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt();
int photo = input.GetField(TiffTag.PHOTOMETRIC)[0].ToInt();
int tiles = 0;
int tileSize = input.TileSize();
byte[][] buffer = new byte[tileSize][];
for (int y = 0; y < height; y += tileLentgh)
{
for (int x = 0; x < width; x += tileWidth)
{
buffer[tiles] = new byte[tileSize];
input.ReadTile(buffer[tiles], 0, x, y, 0, 0);
tiles++;
}
}
// writing
using (Tiff output = Tiff.Open("output.tif", "w"))
{
output.SetField(TiffTag.SAMPLESPERPIXEL, samplesPerPixel);
output.SetField(TiffTag.IMAGEWIDTH, width );
output.SetField(TiffTag.IMAGELENGTH, height);
output.SetField(TiffTag.BITSPERSAMPLE, bitsPerSample);
output.SetField(TiffTag.ROWSPERSTRIP, output.DefaultStripSize(0));
output.SetField(TiffTag.PHOTOMETRIC, photo);
output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
int c = 0;
for (int y = 0; y < height; y += tileLentgh)
{
for (int x = 0; x < width; x += tileWidth)
{
output.WriteTile(buffer[c], x, y, 0, 0);
c++;
}
}
}
}
System.Diagnostics.Process.Start("output.tif");
}
The problem is not the library not supporting BigTiff files, the error is thrown when you try to allocate a huge array. The code you wrote tries to allocate the array in the memory of your computer, expecting that there is enough space there to do so and it seems that there is not.
Handling data with sizes comparable to the available memory on the target system always requires extra attention (that's why you can see BigTiff support emphasized in the library's description).
Fortunately for you, this is not a new problem and there are solutions for this: see some answers here or here.
Basically, the idea behind these solutions is to use your hard drive (or other storage device) to store the data and provide an interface for you to swap the neccessary parts to the memory when needed (just like virtual memory).

Faster way to fill a 160x43 byte array from colors of Bitmap class

What's the faster way to effectively fill an array of bytes where each byte represents a pixel (black or white: < 125 = black, > 125 = white) from a Bitmap class?
I used this for colored images: Better/faster way to fill a big array in C#
However now I'm looking for something different (I can even use a single color like Red to fill this, it doesn't matter is just something I should choose), because the array format changed.
Any suggestion? Actually I'm using this code, which is obviusly not the best idea
for (int x = 0; x < LgLcd.NativeConstants.LGLCD_BMP_WIDTH; ++x)
{
for (int y = 0; y < LgLcd.NativeConstants.LGLCD_BMP_HEIGHT; ++y)
{
tmp = bmp.GetPixel(x, y);
array[y * LgLcd.NativeConstants.LGLCD_BMP_WIDTH + x] = (byte)((tmp.R == 255 && tmp.G == 255 && tmp.B == 255) ? 0 : 255);
//array[y * x] = (byte)0;
}
}
My idea was parallelizing everything (yea, 1 thread per line maybe? (or per column)), it should help I think.
EDIT:
Ok, first, I need a way to have the possibility to access different bytes of the image at the same time, Brandon Moretz is suggesting maybe the correct way to access bytes with lockbits. I would like to avoid, however, unsafe code. Does Lockbits involves necessarily unsafe code?
Second, my idea of parallelization was to use Parallel.For. This method should use the ThreadPool class, which will use an amount of threads not greater than cores of your cpu, and they are pre-allocated.
This method will be called a lot of times, so I think it's not a big trouble, because the threadpool will be used a lot after first call.
Is what I'm saying correct?
Is using "unsafe" code blocks an option? You can use LockBits on a Bitmap to get it's BitmapData, then use Scan0 & Stride properties to iterate over it.
If it's 255 colors I'm assuming a byte per pixel, so so something like:
*( ( ( byte* )bmpData.Scan0 ) + ( y * bmpData.Stride ) + x ) = (byte)((tmp.R == 255 && tmp.G == 255 && tmp.B == 255) ? 0 : 255);
General approach is to divide the image into regions then process. i.e. you can use:
Thread 1) for (int x = 0; x < LGLCD_BMP_WIDTH /2; ++x) { ... }
Thread 2) for (int x = LGLCD_BMP_WIDTH / 2; x < LGLCD_BMP_WIDTH; ++x) { ... }
where you would have two halves of the image be processed by different threads. You can divide further into 4, 8, etc. pieces as you wish. A thread per line would be excess, as thread creation overhead would overwhelm the benefits by a large margin.
I found the answer by myself, working with lockbits and Marshal.ReadByte with a really nice and fast result:
public void SetPixels(Bitmap image)
{
byte[] array = Pixels;
var data = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Parallel.For(0, data.Height, new Action<int>(i =>
{
byte tmp;
int pixel4bpp, pixelPerbpp;
pixelPerbpp = data.Stride / data.Width;
for (pixel4bpp = 0; pixel4bpp < data.Stride; pixel4bpp += pixelPerbpp)
{
tmp = (byte)((
Marshal.ReadByte(data.Scan0, 0 + (data.Stride * i) + pixel4bpp)
+ Marshal.ReadByte(data.Scan0, 1 + (data.Stride * i) + pixel4bpp)
+ Marshal.ReadByte(data.Scan0, 2 + (data.Stride * i) + pixel4bpp)
+ Marshal.ReadByte(data.Scan0, 3 + (data.Stride * i) + pixel4bpp)
) / pixelPerbpp);
array[i * data.Width + (pixel4bpp / pixelPerbpp)] = tmp;
}
}));
image.UnlockBits(data);
}

Reading byte array vs int array and bit shifting - what's faster?

Is one of these decidedly faster?
var scan0 = (uint*)bitmapData.Scan0;
int length = pixels.Length;
for (int i = 0; i < length; i++)
{
uint j = scan0[i];
float a = (j >> 24) / 255f;
pixels[i] = new Vector(
(j >> 16 & 0xff) * a / 255,
(j >> 8 & 0xff) * a / 255,
(j & 0xff) * a / 255);
}
versus
var scan0 = (byte*)bitmapData.Scan0;
int length = pixels.Length * 4;
for (int i = 0; i < length; i += 4)
{
float a = scan0[i + 3] / 255f;
pixels[i / 4] = new Vector(
scan0[i + 2] * a / 255,
scan0[i + 1] * a / 255,
scan0[i] * a / 255);
}
In a 32 bit application, the second is about 2.5 times faster than the first. In a 64 bit application, the second is about 25% faster than the first.
Note that there is a bug in your second code. As you are adding four in each iteration, you will place the objects in every fourth item in the pixels array, and cause an IndexOutOfRangeException exception when it runs out of array.
Slightly faster (about 5%) than the second is to move the pointer for each pixel:
byte* scan0 = (byte*)bitmapData.Scan0;
for (int i = 0; i < pixels.Length; i++) {
float a = scan0[3] / 255f;
pixels[i] = new Vector(
scan0[2] * a / 255,
scan0[1] * a / 255,
scan0[0] * a / 255
);
scan0 += 4;
}
Note also that if you are reading data from a Bitmap image, it is not stored as a continuous array of pixel data. There may be padding between the scan lines, so the code can only read pixels from a single scan line, it can not safely read data from an entire image.
Edit:
Also, I just realised that you put the length of the array in a variable and used that in the loop. That will just make the code slower instead of faster, as the compiler can't optimise away the range check on the array accesses.
I think the bit shift "Your first solution" is faster. however you can test it by using Stopwatch. Start the stopwatch before the call the method, run the method multiple time, and then stop the watch and check its ElapcedMilliseconds. Like:
System.Diagnostics.Stopwatch watch = Stopwatch.StartNew();
//run your method that want to test its executable time multi time
for (int testIndex = 0; testIndex < 100; testIndex++)
{
TestWithShift();
}
watch.Stop();
Console.WriteLine("Test with shift time: {0}", watch.ElapcedMilliseconds);
And repeat the test for the other method. Hope that helps.

Categories