-
different data types
So I have a TIFF raster image, which is 1200x959. Using the libtiff library, I get its dimensions and store them in two variables, w (width) and h (height). But both of these are of type uint32, which I'm pretty sure is the same as unsigned long. I want to manipulate the data and store it in some 2d arrays (Red, Grn, Blu). To do this, I need some loops. So my first question is what does the compiler do when I write something like
Code:
for (i=0; i<h; i++)?
How does it go about comparing i (which is int) and h? I guess I'm not really knowledgeable at all about the difference between various types, and how the computer deals with them.
Here is my code
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <tiffio.h>
int main()
{
TIFF *tif;
int i, j;
uint32 w, h, z, npixels;
uint32 *raster;
tif = TIFFOpen("c:\\image1.tif", "r");
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
npixels = w * h;
uint32 Red[h][w]; /*SEGFAULT HERE*/
uint32 Grn[h][w];
uint32 Blu[h][w];
raster = (uint32*) _TIFFmalloc(npixels * sizeof(uint32));
TIFFReadRGBAImage(tif, w, h, raster, 0);
for (i = 0; i<h; i++)
{
for (j = 0; j<w; j++)
{
z = raster[i*w + h];
Red[i][j] = (z & 0xff);
Grn[i][j] = (z>>8) & 0xff;
Blu[i][j] = (z>>16) & 0xff;
}
}
_TIFFfree(raster);
TIFFClose(tif);
return 0;
}
This segfaults, apparently on the line where I declare Red. I know I'm doing something wrong with types, but I'm not sure what. the function TIFFReadRGBAImage takes the image and puts it into raster. Each element of raster holds 4 bytes, One is the amount of Red, and one for Green and one for Blue, (and one for transparency, I think).
Thanks for your time
PS: I know I shouldn't declare Red, Grn, Blu dynamically like that, but I don't want to worry about using malloc and not being sure about my code for that also. I'll change it when everything else is fixed.
-
My guess would be that it would convert 'h' to an integer; therefore, you could lose data. That's only a guess, though.
-
The problem causing the segfault is due to the fact that you cannot dynamically allocate memory to an array in the fashoin you are attempting. Look into the use of malloc, calloc and free functions to allocate memory to the arrays at runtime.
-
Thanks for the reply,bivhitscar, but I think under C99 you can declare arrays dynamically like that, though it isn't "standard." In any event, I've tested declaring them like that in another program, and it works out.
-
Well, I'm not very familiar with VLAs, so I can't really say much about that. But it really does look like the problem to me. *shrug*
[EDIT]
Are you certain the segfault is on that line?
-
Here is the readout from gdb.
Code:
$ gdb prog2
...a bunch of gdb stuff...
(gdb) run
Starting program: /usr/coding/prog2.exe
Program received signal SIGSEGV, Segmentation fault
0x004012e3 in probe()
(gdb) bt
#0 0x004012e3 in probe()
#1 0x00118f50 in ?? ()
#2 0x00401107 in main() at prog2.c:18
I don't know if #0 or #1 mean anything, but line 18 is where I declare the array.
-
> int i, j;
So make them the same type as your w and h
> uint32 Red[h][w];
4603200 == 1200x959x4
That's over 12MB of stack space for those 3 variables!!!
Many systems impose a limit on the amount of stack space a single process is allowed to use, or set a default size.
Which system are you on?
> I don't know if #0 or #1 mean anything,
They're just counting the nesting level of function calls.
You can navigate up and down the nested set of function calls to examine the state within any function currently in the call chain.
-
Thanks for your replies. I'm on Win2k, running cygwin. I have 256 MB memory, if that matters.
Here's some results of messing around. If I comment out the insides of the inner loop, it still segfaults. If I change
to
Code:
uint32 Red[959][1200]
, and the same for the other arrays, it still segfaults. If I comment out the array declarations, it runs fine. Hope this helps
Thanks for your time
-
As salem said you cannot allocate so much space on the stack. stackspace is usually limited to just a few Mb. Allocate the arrays on the heap
Kurt
-
... using malloc(). And don't forget to free the memory when you're done with it.
Do you even need an array? The calculation looks simple enough that you could calculate it on-the-fly when you need a colour value.
-
Okay y'all were completely correct (I think). Here is my new code
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <tiffio.h>
int main()
{
FILE *fp;
fp = fopen("c:\\output.txt", "w");
TIFF *tif;
uint32 i;
uint32 j;
uint32 w, h, z, npixels;
uint32 *raster;
tif = TIFFOpen("c:\\image1.tif", "r");
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
npixels = w * h;
uint32 **Red;
Red = (uint32**) malloc(h*sizeof(uint32*));
if (Red == NULL) printf("no memory");
for (i=0;i<h;i++)
{
Red[i] = (uint32*) malloc(w*sizeof(uint32));
if (Red[i] == NULL) printf("no memory");
}
raster = (uint32*) _TIFFmalloc(npixels * sizeof(uint32));
if (raster == NULL) printf("no memory");
TIFFReadRGBAImage(tif, w, h, raster, 0);
for (i = 0; i<h; i++)
{
for (j = 0; j<w; j++)
{
z = raster[i*w + h];
Red[i][j] = (z & 0xff);
}
}
for (i = 0; i<h; i++)
{
fprintf(fp, "\n");
for (j = 0; j<w; j++)
{
fprintf(fp, "%u \n", Red[i][j]);
}
}
_TIFFfree(raster);
TIFFClose(tif);
free(Red);
fclose(fp);
return 0;
}
I'm just doing things with Red to simplify matters.
Now, when I open c:\output.txt, it should be 1200 lines (I think), but instead it is 4764, but I'm pretty sure this just refelcts a limitation of Notepad's maximum width. But there are little things that look like small boxes, or perhaps small 0's. I think this just is an artifact of printing in "%u" mode.
So I think I'm good for now. But what I want to do is encapsulate the malloc() part in a function. I tried writing one that took a pointer as an argument and allocated memory for it, but that segfaulted. But I would prefer to write one that mimicked malloc, so I could call it by
Code:
Red = create(w*h*sizeof(uint32));
or something like that. Does anyone have any tips?
-
Use a function pointer.
Although, if malloc() really does the work, I don't know why you'd want to hide that fact: people (including you) might mistake create() for something you wrote and forget to free() memory, for instance. It seems like you are complicating things for the sake of doing it.
-
You shouldn't cast malloc(), which was probably mentioned earlier on.
-
Is there any way I can find out how much memory my program is using while its running? I'm looking at the documentation for gdb, but not finding anything
-
Am I making an ass of myself by asking what OS you're using?
If it's windows just run it and look at your process in the task manager.
Yes, I think I am going to look like an ass...
[EDIT]
Note to self: Read previous posts more thoroughly...