madmuppet
Guest
|
|
« on: April 27, 2011, 01:54:15 PM » |
|
I am trying to draw large images with a program I wrote in c along with sdl as the graphic component.
I can generate images up to ~6000 * 4000 but when I tried a much larger image ~ 60,000 * 40,000 my program segment faults ..
the ultimate aim is to print off an image and hang it on the wall .. Im looking at using the golden ratio so the image will be in the region of 1.618 * 1m
I have been looking online for ideas .. there are a lot about drawing the mandelbrot set .. I am still looking for anything related to drawing large images.
Im pretty sure I have reached the limit going in the direction I have been so I need to look elsewhere .. so any ideas on how to go about this is appreciated ..
currently I am looking at using an array to store the colors and write to a file then try and convert to an image ..
hope I am not too vague thanks for any help al.
any questions or if you want to see what I am doing so far np ..:p
|
|
|
Logged
|
|
|
|
bib
|
|
« Reply #1 on: April 27, 2011, 02:11:31 PM » |
|
Iwhen I tried a much larger image ~ 60,000 * 40,000 my program segment faults ..
the ultimate aim is to print off an image and hang it on the wall .. Im looking at using the golden ratio so the image will be in the region of 1.618 * 1m
Why such a large size? To print in 300 dpi and 1,6x1m you need about 19000x12000 pixels.
|
|
|
Logged
|
Between order and disorder reigns a delicious moment. (Paul Valéry)
|
|
|
panzerboy
Fractal Lover
Posts: 242
|
|
« Reply #2 on: April 27, 2011, 03:51:13 PM » |
|
It depends on your printing technology. Colour Lasers can't vary the droplet size so to achieve grays or different levels of colour they have to dither the dots. If thats the case theres no need to supply an image at the maximum resolution calculated by image size X DPI. Some Inkjets can vary the droplet size the following page says of how Epson can achieve 5 different droplet sizes, http://www.epson.com.sg/epson_singapore/explore_epson/innovation/micro_piezo.page5 levels of droplet size plus no droplet is 6 shades, 256/6 is 42.66.. squareroot is about 6.5 so you'd still need a 6.5x6.5 array of dots to give 256 shades 1440/6.5 is 221.5 DPI. At 1mX1.618m thats 8722 X 14,112.
|
|
|
Logged
|
|
|
|
Fractal Ken
Fractal Lover
Posts: 246
Proud to be 2D
|
|
« Reply #3 on: April 27, 2011, 05:25:46 PM » |
|
I can generate images up to ~6000 * 4000 but when I tried a much larger image ~ 60,000 * 40,000 my program segment faults ..
If your program is 32 bit (as opposed to 64 bit), you're probably attempting to address more memory than is possible.
|
|
|
Logged
|
Fortran will rise again
|
|
|
madmuppet
Guest
|
|
« Reply #4 on: April 28, 2011, 05:50:15 AM » |
|
I have a dual boot machine running 32 bit xp and 64 bit lenny debian.
on xp I have a virtualbox debian wheezy 32 bit machine where I have been writing the program. the program works fine on both the virtual machine and the full lenny debian ..
my machine is an amd quad core phenom 2 940 running 4 gig ram and a 1gb 4870 ..
my guess is the graphics card is having problems so anyways ideas on finding a way of representing an image this size appreciated
|
|
|
Logged
|
|
|
|
Softology
|
|
« Reply #5 on: May 01, 2011, 05:35:50 AM » |
|
Don't store the entire image data in memory. Calculate the pixels as normal and write/stream the bytes directly to an image file. I use BMP as the format as it is fairly simple to write the raw bytes header and image data. http://en.wikipedia.org/wiki/BMP_file_formatOnce you have your huge BMP file, you can convert it to JPG/PNG/etc in Photoshop if needed. That method allows huge images and the only limitation is disk space. Jason.
|
|
|
Logged
|
|
|
|
madmuppet
Guest
|
|
« Reply #6 on: May 01, 2011, 10:06:52 AM » |
|
thanks for the info .. I am having a look at it now.
cheers al.
|
|
|
Logged
|
|
|
|
madmuppet
Guest
|
|
« Reply #7 on: May 12, 2011, 01:25:25 AM » |
|
I have been busy learining how to open and write to a bmp file .. I have one question though .. what is the practical limit for a file?
how big can I draw a pic before its too big to open?
thanks for the help al.
|
|
|
Logged
|
|
|
|
zenzero-2001
|
|
« Reply #8 on: May 15, 2011, 03:29:42 AM » |
|
Hi I'm not sure if there is a file size limit on bmp, but I have created files over a Gb in size with no problem. So long as you have enough memory in your computer it will be easy to open the resultant file. If you run out of memory, the computer will use the hard disk as virtual memory and this will be slow - but it should get there eventually. It has been awhile since I coded it, but if I remember correctly, I had a bitmap of one pixel height and the required width in memory and I would append this to the file after calculating each row of the fractal. Here is some old code I wrote: struct BMPHeader { short bfType; // "BM" int bfSize; // Size of file in bytes int bfReserved; // set to 0 int bfOffBits; // Byte offset to actual bitmap data (= 54) int biSize; // Size of BITMAPINFOHEADER, in bytes (= 40) int biWidth; // Width of image, in pixels int biHeight; // Height of images, in pixels short biPlanes; // Number of planes in target device (set to 1) short biBitCount; // Bits per pixel int biCompression; // Type of compression (0 if no compression) int biSizeImage; // Image size, in bytes (0 if no compression) int biXPelsPerMeter; // Resolution in pixels/ meter of display device int biYPelsPerMeter; // Resolution in pixels/ meter of display device int biClrUsed; // Number of colors in the color table (if 0, use maximum allowed by biBitCount) int biClrImportant; // Number of important colors. If 0, all colors are important };
class RenderObject { private: FILE* file; struct BMPHeader bmph; int bytesPerLine;
public: RenderObject(void) { file = NULL; }
bool OpenFile(char* filename, int width, int height) { bytesPerLine = 4 * width;
bmph.bfType = 0x4D42; bmph.bfOffBits = 54; bmph.bfSize = bmph.bfOffBits + bytesPerLine * height; bmph.bfReserved = 0; bmph.biSize = 40; bmph.biWidth = width; bmph.biHeight = -height; bmph.biPlanes = 1; bmph.biBitCount = 32; bmph.biCompression = 0; bmph.biSizeImage = bytesPerLine * height; bmph.biXPelsPerMeter = 0; bmph.biYPelsPerMeter = 0; bmph.biClrUsed = 0; bmph.biClrImportant = 0;
errno_t err = fopen_s(&file, filename, "wb"); if(err != 0) { return false; } fwrite(&bmph.bfType, 2, 1, file); fwrite(&bmph.bfSize, 4, 1, file); fwrite(&bmph.bfReserved, 4, 1, file); fwrite(&bmph.bfOffBits, 4, 1, file); fwrite(&bmph.biSize, 4, 1, file); fwrite(&bmph.biWidth, 4, 1, file); fwrite(&bmph.biHeight, 4, 1, file); fwrite(&bmph.biPlanes, 2, 1, file); fwrite(&bmph.biBitCount, 2, 1, file); fwrite(&bmph.biCompression, 4, 1, file); fwrite(&bmph.biSizeImage, 4, 1, file); fwrite(&bmph.biXPelsPerMeter, 4, 1, file); fwrite(&bmph.biYPelsPerMeter, 4, 1, file); fwrite(&bmph.biClrUsed, 4, 1, file); fwrite(&bmph.biClrImportant, 4, 1, file);
return true; }
void Render(int* ptr) { fwrite(ptr, bytesPerLine, 1, file); }
void CloseFile(void) { fclose(file); } };
I pass a pointer of the bitmap row in memory to the method Render at the end of each row. That way I only have to store a one row bitmap in memory at a time. It is possible to make super high-res images this way and then resize them down in Photoshop or GIMP to obtain "anti-aliasing". Hope this helps! zenzero-2001
|
|
|
Logged
|
|
|
|
zenzero-2001
|
|
« Reply #9 on: May 15, 2011, 01:26:43 PM » |
|
Hi I just did some testing and I have been able to create a 20,000 x 20,000 pixel image and successfully load into GIMP (haven't tried Photoshop). It took a short while though. The file size was 1.5Gb and GIMP used over 1.2Gb memory to load it - I'm lucky, I have 8Gb in my machine I will have a try with some larger images. zenzero-2001
|
|
|
Logged
|
|
|
|
zenzero-2001
|
|
« Reply #10 on: May 15, 2011, 02:10:27 PM » |
|
My program is written in .NET and I have been running it under WINE in Linux, it crashes when trying to create images a bit larger than 20,000 x 20,000 with bad memory allocation. Running natively with Windows, I successfully created a 32,768 x 32,768 image - I was not able to create anything larger because of the 4Gb file size limit with FAT32. The 32,768 x 32,768 image comes to 4Gb exactly. I tried for 64,000 x 48,000, it seemed to be rendering fine until it hit the limit and stopped. I'm just copying the 32,768 x 32,768 file to my usb stick so I can try and open it in my 8Gb Linux machine. My Windows machine only has 1.5Gb, so I don't think I will even try opening it on that zenzero-2001
|
|
|
Logged
|
|
|
|
zenzero-2001
|
|
« Reply #11 on: May 15, 2011, 02:13:04 PM » |
|
By the way a 64,000 x 48,000 32bit bmp image will take up 11.4 Gb disk space!
|
|
|
Logged
|
|
|
|
zenzero-2001
|
|
« Reply #12 on: May 15, 2011, 02:45:41 PM » |
|
I'm using 32 bit bmps in my program, if I used 24bit then the file size would be smaller.
Correction to my earlier statement about 32,768 x 32,768 coming to 4Gb exactly, it is actually a bit larger because of the header - so that would take it over the 4Gb FAT32 limit. I wasn't therefore able to open it due to it being an invalid bmp file.
|
|
|
Logged
|
|
|
|
madmuppet
Guest
|
|
« Reply #13 on: May 26, 2011, 12:35:07 AM » |
|
thanks for all the info zenzero .. I can now write a mandelbrot set to bitmap and view it in my browser .. however when I try and open it in the gimp I get an error reading bmp file header for the image. if anyone wants to look at the code and give some pointers feel free .. #include<stdio.h> #include<stdlib.h> #include<math.h> #include<inttypes.h> #define SMOOTH log( 0.5 * log( window->ESCAPE ))
//prototyping the structures ..
struct window{ int xscreen,yscreen,Nxscreen,Nyscreen; unsigned long long int MAX,ESCAPE; long double ximage,yimage,xoff,yoff; }wdw,*window;
struct bmpfile{ unsigned char magic[2]; }bf,*bfp;
struct fileheader{ uint32_t filesize; uint16_t creator1; uint16_t creator2; uint32_t bmpoffset; }fh,*fhp;
struct bmpinfoheader{ uint32_t headersize; int32_t width; int32_t height; uint16_t nplanes; uint16_t bitsperpixel; uint32_t compressiontype; uint32_t bitmapbytesize; int32_t hres; int32_t vres; uint32_t ncolors; uint32_t nimpcolors; }bh,*bhp;
struct rgb{ unsigned char r; unsigned char g; unsigned char b; };
//prototype the functions ..
struct rgb *color( long long int count,struct window* window, struct rgb* thc, int c ); int multiply(long double real, long double imaginary,struct window* window ); void control( struct window* window, int bpl,struct bmpfile* bfp, struct fileheader* fhp,struct bmpinfoheader* bhp ); void start(); //color gives four values for color red green blue .. struct rgb *color( long long int count, struct window* window, struct rgb* thc,int x ){ int d, r, c = 1,cn, red = 0, green = 0, blue = 0; cn = count % 512;
//if the count is over the max then the color should be black ..
if(count == window->MAX){ thc[x].b = 0; thc[x].g = 0; thc[x].r = 0; return( thc ); } //otherwise find a color .. while(( cn % 256 ) != 0 ){ d = cn / 256; r = cn % 256; switch( c ){ case 1: red = r; break; case 2: green = r; break; case 3: blue = r; break; default:printf("shit happens\n"); } cn = d; ++c; } //put color into struct array .. single dimension array of screen width size .. //will write a single line ( row ) at a time.
thc[x].b = blue * 4; thc[x].g = green * 8; thc[x].r = red * 16; return(thc); } // multiply is an iterative process which returns a count which is // converted into a color. int multiply(long double real, long double imaginary, struct window* window ){
unsigned long long int count = 1; long double x,y,z = 0,xx,yy,tempr = real,tempi = imaginary; //made some significant speed gains in control function by trying to use less division //so tried it here z is computed once used 3 times ..
while( count < window->MAX && abs( z ) < window->ESCAPE ){ x = tempr * tempr; y = tempi * tempi; z = tempr * tempi;
xx = x - y; yy = 2 * z; z = x + y;
tempr = real + xx; tempi = imaginary + yy; count++; } if(count >= window->MAX ){ return count; } return ( count - ( log( 0.5 * log( z )) - SMOOTH ) / log( 2 )); } void control( struct window* window, int bpl,struct bmpfile* bfp, struct fileheader* fhp,struct bmpinfoheader* bhp ){
//create the array to hold each line colors .. int x,y,count; long double real,imaginary, convx,convy;
struct rgb array[ bpl ]; struct rgb *thc; thc = array; FILE *fp;
printf("control\n");
//zero array .. for(count = 0; count < window->Nxscreen -1; count++ ){ array[x].b = 0; array[x].g = 0; array[x].r = 0; // array[x].reserve = 50; } //write the headers for the bitmap ..
fp = fopen("image-01.bmp","wb"); fwrite(bfp,sizeof(bf),1,fp); fwrite(fhp,sizeof(fh),1,fp); fwrite(bhp,sizeof(bh),1,fp); //save time divide once use many times .. // numbers give an imaginary number for each pixel ..
convx = window->ximage / window->Nxscreen; convy = window->yimage / window->Nyscreen;
for( y = window->Nyscreen; y < 0; y++ ){ for( x = 1; x < window->Nxscreen; x++ ){ real = convx * x - window->xoff; imaginary = window->yoff - ( convy * y ); count = multiply( real, imaginary, window ); color( count, window, thc, x ); } //should have a full array here .. write it out .. I know the bitmap starts from //bottom left to top right but all I want at this stage is something close to mandelbrot set. //I have tried to accomadate this by starting y at max and reducing to zero. fwrite(&array,sizeof(array),1,fp); } fclose( fp ); } void start( ){ //setting the conditions for the bitmap .. also screen size and image size. int bpl; bfp = &bf; fhp = &fh; bhp = &bh; window = &wdw; window->MAX = 128;//can and will change these later window->ESCAPE = 4;
window->xscreen = 809; window->yscreen = -500;
window->Nxscreen = window->xscreen; window->Nyscreen = window->yscreen; //make sure the screen is divisible by 4 .. bpl = window->Nxscreen; while(bpl % 4 != 0){ bpl++; } window->ximage = 3.2; //I am going to draw small set with sdl .. when I see something I like window->yimage = 2.0; //I will draw it with this program .. so these conditions will change .. window->xoff = 2.2; //a data struct in my sdl program holds the info and writes it out for me. window->yoff = 1.0;
bfp->magic[0] = 'B'; bfp->magic[1] = 'M'; fhp->filesize = fhp->bmpoffset + abs(window->Nyscreen * bpl);//being lazy I do not want to compute these each //time. fhp->bmpoffset = 54; fhp->creator1 = 0; fhp->creator2 = 0; bhp->width = bpl; bhp->height = - window->Nyscreen; bhp->nplanes = 1; bhp->bitsperpixel = 24; bhp->compressiontype = 0; bhp->bitmapbytesize = bpl * bhp->height; bhp->hres = 2835; bhp->vres = 2835; bhp->ncolors = 0; bhp->nimpcolors = 0; bhp->headersize = bhp->bitsperpixel + bhp->bitmapbytesize; control( window,bpl,bfp,fhp,bhp ); } int main( int argc, char * argv[] ){ printf("main\n");
start(); //GO!! return(0); }
|
|
|
Logged
|
|
|
|
madmuppet
Guest
|
|
« Reply #14 on: May 28, 2011, 12:50:20 PM » |
|
finally got it working .. currently in process of testing a 27,000 x 15,000 pixel mandelbrot set ..
adjusted the headersize in my last program and brought together two of the strutures .. it works in my webrowser and gimp as well .. yay!
no to come up with a good color scheme .. any ideas?
|
|
|
Logged
|
|
|
|
|