C++ - place multiple images in an array pointer - c++

I have been trying to read ten images stored on the disk into an array pointer using the SOIL library. I would like to then render the resulting data in OpenGL using 3D textures.
The code I wrote to read images from the disk and store them in a buffer throws up Access violation reading location 0x00000000 errors.
Is this the right way of storing multiple images using SOIL into an array pointer?
unsigned char *tex;
int imSize = h*w;
unsigned char *buff = new unsigned char[h * w * slices];
for(int i = 1; i<=10; i++)
{
for(int j = 0; j<imSize; j++)
{
if (i==1)
{
tex = (unsigned char*) SOIL_load_OGL_texture("Data/PA_170090.png",
SOIL_LOAD_AUTO,SOIL_CREATE_NEW_ID,SOIL_FLAG_INVERT_Y);
buff[((i-1)*imSize) + j] = tex[j]; }
if (i==2)
{ tex = (unsigned char*)SOIL_load_OGL_texture("Data/PA_170091.png",
SOIL_LOAD_AUTO,SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
buff[(i-1)*imSize + j] = tex[j]; }
if (i==3)
{ tex = (unsigned char*)SOIL_load_OGL_texture("Data/PA_170092.png",
SOIL_LOAD_AUTO,SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
buff[(i-1)*imSize + j] = tex[j];}
....
.... // up to 10 images
}
}

It seems SOIL_load_OGL_texture, is not returning any buffer. Instead, it returns an Id (of type GLuint , which is unsigned int). If the function fails, the id will be zero. You are casting that integer value to a pointer and dereferencing it, which results in access violation.

Related

pad print line with white space C++

In C++ I am using unsigned char pointers to hold byte arrays so that I can fit 8 bit color codes in each element for a print line.
I have one array holding data, and one array holding white space, and I am using for loops to populate a third array so that the data is at the beginning and white space is at the end.
When the pointer is created, as I monitor memory at runtime, all elements have a default value of 0xCD, which is magenta on color chart. I use a for loop to populate the bytes I want with 0x00, but it will not write over the default array value of the third array.
So, I am stuck with my printer printing magenta instead of white space. Yet I can write over that array just fine with just the data. But not with the whitespace. Im unsure what is the reason for that. Can anyone give me any insight? Here is my code...
PrintLine(unsigned char* pbData, unsigned long ulDataSize, UINT xoffset)
{
if (xoffset > 0)
{ //create pointer to byte array for xoffset
unsigned char* offsetData;
offsetData = new unsigned char[(xoffset / 8)]; //x offset is divided by 8
//to convert pixels to bytes
//create pointer to byte array to hold image data and offset data
unsigned char* finalData;
finalData = new unsigned char[ulDataSize + (xoffset / 8)];
//begin final data with image data passed into the function
for (int count = 0; count < ulDataSize; count++)
{
finalData[count] = pbData[count];
}
//populate offset data with blank bytes
for (int count = 0; count < (xoffset / 8); count++)
{
offsetData[count] = 0x00;
}
//add blank data for offset to finalData
int position = 0;
for (int count = ulDataSize; count < ulDataSize + (xoffset / 8);count++)
{
finalData[ulDataSize] = offsetData[position];//also tried =0x00
position++;
}
//Send data to printer.
if (!(Write(finalData, ulDataSize + (xoffset / 8)))
{
return FALSE;
}
return TRUE;
}
}
At first glance your code don't have errors, but I see something that looks suspicious. I'm talking about the line:
finalData[ulDataSize] = offsetData[position]; //also tried =0x00
I think what you want is:
finalData[count] = offsetData[position];//also tried =0x00
On the other hand you could write your loop like this:
for (int count = 0; count < (xoffset / 8); count++)
{
finalData[ulDataSize + count] = offsetData[count];
}
Making the code much more readable.

AccessVioilationException using BitmapData in c++

Below is my program. I am trying to apply grayscale filter using bitmapdata class in visual c++. I am getting AccessViolationException at 11, tagged by the comment. I have tried using CLR:Safe and CLR:pure but no use. In c# this would be solved by using unsafe block. Any suggestions? None of the other solutions on related questions worked.
Bitmap^ bmp = gcnew Bitmap(pictureBox1->Image);
BitmapData^ data = bmp->LockBits(Rectangle(0,0,bmp->Width,bmp->Height), ImageLockMode::ReadWrite, PixelFormat::Format24bppRgb);
int blue=0, green=0, red=0;
System::IntPtr s = data->Scan0;
int* P = (int*)(void*)s;
for (int i =0; i<bmp->Height;i++)
{
for (int j = 0; j < bmp->Width*3; j++)
{
blue = (int)P[0]; //access violation exception
green =(int )P[1];
red = (int)P[2];
int avg = (int)((blue + green + red) / 3);
P[0] = avg;
P[1] = avg;
P[2] = avg;
P +=3;
}
}
bmp->UnlockBits(data);
pictureBox1->Image = bmp;
You are using an int* when you should be using a byte*. Your pixels are three bytes each, one byte per channel. Your int is (likely) 4 bytes, so p[0] returns an entire pixel plus on byte past it. This is why you get an access violation; you are overrunning the bounds of the image buffer.
When you increment a pointer, you are adding sizeof *p bytes to it. In this case, P += 3 increments the pointer P by 12 bytes. Much too much, and you'll never be able to read a single pixel (or channel) of a 24bpp image with an int*. You are also assuming that your stride is Width * 3, which may or may not be correct (bitmaps are 4 byte aligned.)
Byte* base = (Byte*)data->Scan0;
int stride = data->Stride;
for(int y = 0; y < data->Height; ++y) {
Byte* src = base + y * stride;
for(int x = 0; x < data->Width; ++x, src += 3) {
// bitmaps are stored in BGR order (though not really important here).
// I'm assuming a 24bpp bitmap.
Byte b = src[0];
Byte g = src[1];
Byte r = src[2];
int average = (r + g + b) / 3;
src[0] = src[1] = src[2] = (Byte)average;
}
}

Memory error while using memcpy?

I'm using dcmtk library to modify the pixel data of a multi frame compressed dicom image. So, to do that, at one stage in an for loop I take the pixel data of each decompressed frame and modify them according my wish and try to concatenate each modify pixel data in a big memory buffer frame by frame. This core process of for loop is as below.
The problem is after the first iteration it gives memory at the line of the code where I call the function getUncompressedFrame. I think it's happening because of the line memcpy(fullBuffer+(i*sizeF),newBuffer,sizeF);, as when I remove that line there's no error at that time and the whole for loop works absolutely fine.
Could you please say me if I'm making a mistake in working with memcpy? Thanks.
Uint32 sizeF=828072;// I just wrote it to show what is the data type.
Uint8 * fullBuffer = new Uint8(int(sizeF*numOfFrames));//The big memory buffer
for(int i=0;i<numOfFrames;i++)
{
Uint8 * buffer = new Uint8[int(sizeF)];//Buffer for each frame
Uint8 * newBuffer = new Uint8[int(sizeF)];//Buffer in which the modified frame data is stored
DcmFileCache * cache=NULL;
OFCondition cond=element->getUncompressedFrame(dataset,i,startFragment,buffer,sizeF,decompressedColorModel,cache);
//I get the uncompressed individual frame pixel data
if(buffer != NULL)
{
for(unsigned long y = 0; y < rows; y++)
{
for(unsigned long x = 0; x < cols; x++)
{
if(planarConfiguration==0)
{
if(x>xmin && x<xmax && y>ymin && y<ymax)
{
index=(x + y + y*(cols-1))*samplePerPixel;
if(index<sizeF-2)
{
newBuffer[index] = 0;
newBuffer[index + 1] = 0;
newBuffer[index +2] = 0;
}
}
else
{
index=(x + y + y*(cols-1))*samplePerPixel;
if(index<sizeF-2)
{
newBuffer[index] = buffer[index];
newBuffer[index + 1] = buffer[index + 1];
newBuffer[index + 2] = buffer[index + 2];
}
}
}
}
}
memcpy(fullBuffer+(i*sizeF),newBuffer,sizeF);
//concatenate the modified frame by frame pixel data
}
Change the declaration of fullBuffer to this:
Uint8 * fullBuffer = new Uint8[int(sizeF*numOfFrames)];
Your code didn't allocate an array, it allocated a single Uint8 with the value int(sizeF*numOfFrames).
Uint8 * fullBuffer = new Uint8(int(sizeF*numOfFrames));
This allocates a single byte, giving it an initial value of sizeF*numOfFrames (after truncating it first to int and then to Uint8). You want an array, and you don't want to truncate the size to int:
Uint8 * fullBuffer = new Uint8[sizeF*numOfFrames];
^ ^
or, to fix the likely memory leaks in your code:
std::vector<Uint8> fullBuffer(sizeF*numOfFrames);
If the method getUncompressedFrame is doing an inner memcpy to cache, then it makes sense why, as you are passing a null pointer as argument for the cache, with no memory allocated.

reading TGA files in OpenGl to create a 3d ouse

I have a TGA file and a library that allready has everything that I need to read TGA and use them.
This class has a method called pixels(), that returns a pointer that is pointed to the memory area where pixel are stored as RGBRGBRGB...
My question is, how can I take the pixel value?
Cause if I make something like this:
img.load("foo.tga");
printf ("%i", img.pixels());
It gives back to me what is proprably the address.
I've found this code on this site:
struct Pixel2d
{
static const int SIZE = 50;
unsigned char& operator()( int nCol, int nRow, int RGB)
{
return pixels[ ( nCol* SIZE + nRow) * 3 + RGB];
}
unsigned char pixels[SIZE * SIZE * 3 ];
};
int main()
{
Pixel2d p2darray;
glReadPixels(50,50, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &p.pixels);
for( int i = 0; i < Pixel2d::SIZE ; ++i )
{
for( int j = 0; j < Pixel2d::SIZE ; ++j )
{
unsigned char rpixel = p2darray(i , j , 0);
unsigned char gpixel = p2darray(i , j , 1);
unsigned char bpixel = p2darray(i , j , 2);
}
}
}
I think that It can work great for me, but how can I tell the program to read from my img?
Tga supports different pixel depths. And we don't know what library you're using. But generally speaking pixels() should return a pointer to a buffer containing pixels. Say for sake of argument it unpacks the pixels into 8-bit per channel subpixels, then each pixel is represented by 3 bytes.
So to access a pixel at a given offset in the buffer:
const u8* pixelBuffer = img.pixels():
u8 red = pixelBuffer[(offset*3)+0];
u8 green = pixelBuffer[(offset*3)+1];
u8 blue = pixelBuffer[(offset*3)+2];
If you know the width of the image buffer then you can get a pixel by its x and y coordinates:
u8 red = pixelBuffer[((x+(y*width))*3)+0];

Sometimes I get EXEC_BAD_ACCESS (Access violation) when reversing an array

I am loading an image using the OpenEXR library.
This works fine, except the image is loaded rotated 180 degrees. I use the loop shown below to reverse the array but sometimes the program will quit and xcode will give me an EXEC_BAD_ACCESS error (Which I assume is the same as an access violation in msvc). It does not happen everytime, just once every 5-10 times.
Ideally I'd want to reverse the array in place, although that led to errors everytime and using memcpy would fail but without causing an error, just a blank image. I'd like to know what's causing this problem first.
Here is the code I am using: (Rgba is a struct of 4 "Half"s r, g, b, and a, defined in OpenEXR)
Rgba* readRgba(const char filename[], int& width, int& height){
Rgba* pixelBuffer = new Rgba[width * height];
Rgba* temp = new Rgba[width * height];
// ....EXR Loading code....
// TODO: *Sometimes* the following code results in a bad memory access error. No idea why.
// Flip the image to conform with OpenGL coordinates.
for (int i = 0; i < height; i++){
for(int j = 0; j < width; j++){
temp[(i*width)+j] = pixelBuffer[(width*height)-(i*width)+j];
}
}
delete pixelBuffer;
return temp;
}
Thanks in advance!
Change:
temp[(i*width)+j] = pixelBuffer[(width*height)-(i*width)+j];
to:
temp[(i*width)+j] = pixelBuffer[(width*height)-(i*width)+j - 1];
(Hint: think about what happens when i = 0 and j = 0 !)
And here's how you can optimize this code, to save memory and for cycles:
Rgba* readRgba(const char filename[], int& width, int& height)
{
Rgba* pixelBuffer = new Rgba[width * height];
Rgba tempPixel;
// ....EXR Loading code....
// Flip the image to conform with OpenGL coordinates.
for (int i = 0; i <= height/2; i++)
for(int j = 0; j < width && (i*width + j) <= (height*width/2); j++)
{
tempPixel = pixelBuffer[i*width + j];
pixelBuffer[i*width + j] = pixelBuffer[height*width - (i*width + j) -1];
pixelBuffer[height*width - (i*width + j) -1] = tempPixel;
}
return pixelBuffer;
}
Note that optimal (from a memory usage best practices point of view) would be to pass pixelBuffer* as a parameter and already allocated. It's a good practice to allocate and release the memory in the same piece of code.