Fractals/Computer graphic techniques/2D/gfile
Graphic files
One can :
- directly create graphic file
- open existing graphic file
Types of graphic files :
Static images
Raster files
raster files
- ppm files :
- Here are various programs for creating pbm file [1]
- PPM file in c by Mukund
- ppm files in c by JOSEPH THOMAS
- PGM file and C++ program by Ilya Voyager
- Load and draw ppm/pgm files using glut by Lori L Scarlatos
- bmp files :
Assembler
; create a ppmb file by ker2x ; http://www.fractalforums.com/programming/an-absolute-beginner-to-x64-asm-on-linux/ : yasm -f elf64 ppmb.asm ; gcc -o ppmb ppmb.o ; ./ppmb | hexdump segment .data header: db 'P6 4 4 255', 0x0a headerlen: equ $-header image: db 255,0,0, 0,255,0, 0,0,255, 255,255,255 imagelen: equ $-image segment .text global main main: mov eax, 4 mov ebx, 1 mov ecx, header mov edx, headerlen int 0x80 mov eax, 4 mov ebx, 1 mov ecx, image mov edx, imagelen int 0x80 mov eax, 4 int 0x80 mov eax, 4 int 0x80 mov eax, 4 int 0x80 ; Call sys_exit(0) mov eax, 1 xor ebx, ebx int 0x80
C
Static array for one color
Code in C for creating pgm text file :
#include <stdio.h> int main(){ int iX,iY; const int iXmax = 300; const int iYmax = 300; /* color is coded from 0 to 255 */ /* it is 8 bit color RGB file */ const int MaxColorComponentValue=255; FILE * fp; char *filename="m.pgm"; char *comment="# this is my new text pgm file "; /* comment should start with # */ static unsigned char color; /*create new file,give it a name and open it in text mode */ fp= fopen(filename,"w"); /* text mode */ /*write ASCII header to the file*/ fprintf(fp,"P2\n%s\n%d %d\n%d\n",comment,iXmax,iYmax,MaxColorComponentValue); /*write image data bytes to the file*/ for(iY=0;iY<iYmax;++iY){ for(iX=0;iX<iXmax;++iX){ color=150; /* compute pixel color (8 bit = 1 byte) */ fprintf(fp," %d ", color); /*write color to the file*/ } fprintf(fp," \n "); } fclose(fp); printf("OK\n"); getchar(); return 0; }
To compile it :
gcc m.c
To run it :
./a.out
Remember that :
- fwrite is used for binary files
- fprintf is used for binary and text files
so if you want to use fwrite then you will get binary file ( even if you will open it in text mode ):
Static 2D array for whole image
#include <stdio.h> int main(){ int iX,iY; const int iXmax = 100; const int iYmax = 100; unsigned char data[iYmax][iXmax]; /* 2D array for colors ( shades of gray ) */ const int MaxColorComponentValue=255; /* color component is coded from 0 to 255 ; it is 8 bit color file */ FILE * fp; char *filename="n.pgm"; char *comment="# this is my new binary pgm file";/* comment should start with # */ /* fill the data array */ for(iY=0;iY<iYmax;++iY){ for(iX=0;iX<iXmax;++iX){ data[iY][iX]=255; } } } /* write the whole data array to ppm file in one step */ fp= fopen(filename,"wb"); /*create new file,give it a name and open it in binary mode */ fprintf(fp,"P5\n %s\n %d %d\n %d\n",comment,iXmax,iYmax,MaxColorComponentValue); /*write header to the file*/ fwrite(data,sizeof data,1,fp); /*write image data bytes to the file*/ fclose(fp); printf("OK - file %s saved\n", filename); return 0; }
Virtual 2D array and dynamic 1D array
Here image is a virtual 2D array, but in program we use 1D array.
Relations between indexes :
i = ix + iy*iWidth; // index of 1D array ix = i % iWidth; iy = (i- ix) / iWidth;
Here is whole program where we only check ranges of array's indexes without using explicit array :
#include <stdio.h> /* --------- global variables ----------------- */ // 2D array // Indexes of array starts from 0 not 1 unsigned int ix, iy; unsigned int ixMin = 0; unsigned int ixMax = 3; // unsigned int iWidth ; // = (ixMax -ixMin + 1) = 4 unsigned int iyMin = 0; unsigned int iyMax = 3; // unsigned int iHeight ; //= (iyMax -iyMin + 1) = 4 // The size of array has to be a positive constant integer unsigned int i2Dsize ; // = iWidth*iHeight = 16 // 1D array unsigned int i; // index of 1D array unsigned int iMin = 0; // Indexes of array starts from 0 not 1 so the highest elements of an array is = array_name[size-1]. unsigned int iMax ; // = i2Dsize-1; // = 15 // The size of array has to be a positive constant integer unsigned int i1Dsize ; // = i2Dsize = (iMax -iMin + 1) = 16 ; 1D array with the same size as 2D array /* ---------- functions ----------------*/ /* gives position of 2D point (iX,iY) in 1D array ; uses also global variable iWidth */ unsigned int f(unsigned int ix, unsigned int iy) { return ix + iy*iWidth; } /* ---------------------- main ------------------*/ int main() { iWidth = (ixMax -ixMin + 1); // iHeight = (iyMax -iyMin + 1); // i2Dsize = iWidth*iHeight; // number of points in array iMax = i2Dsize-1; // Indexes of array starts from 0 not 1 so the highest elements of an array is = array_name[size-1]. i1Dsize = i2Dsize; // 1D array with the same size as 2D array // first method using 1D index i for (i=iMin; i<i1Dsize; ++i) printf(" %d \n", i ); // from 0 to 15 // second method using 1D index i for (i=iMin; i<=iMax ; ++i) printf(" %d \n", i ); // from 0 to 15 // check second method using 1D index i for (i=iMin; i<=iMax ; ++i) // i from 0 to 15 { ix = i % iWidth; iy = ( i- ix) / iWidth; // inversion of f function printf(" ix = %d ; iy = %d ; i = %d \n",ix , iy , i );} // using 2D indexes : iy and ix for(iy=iyMin;iy<=iyMax;++iy) for(ix=ixMin;ix<=ixMax;++ix) printf(" ix = %d ; iy = %d ; i = %d \n", ix, iy, f(ix,iy) ); return 0; }
Lua
Lua code for binary B@W PBM file :
-- The Computer Language Shootout -- http://shootout.alioth.debian.org/ -- contributed by Mike Pall local width = tonumber(arg and arg[1]) or 100 local height, wscale = width, 2/width local m, limit2 = 50, 4.0 local write, char = io.write, string.char write("P4\n", width, " ", height, "\n") for y=0,height-1 do local Ci = 2*y / height - 1 for xb=0,width-1,8 do local bits = 0 local xbb = xb+7 for x=xb,xbb < width and xbb or width-1 do bits = bits + bits local Zr, Zi, Zrq, Ziq = 0.0, 0.0, 0.0, 0.0 local Cr = x * wscale - 1.5 for i=1,m do local Zri = Zr*Zi Zr = Zrq - Ziq + Cr Zi = Zri + Zri + Ci Zrq = Zr*Zr Ziq = Zi*Zi if Zrq + Ziq > limit2 then bits = bits + 1 break end end end if xbb >= width then for x=width,xbb do bits = bits + bits + 1 end end write(char(255-bits)) end end
Octave
Octave code that creates array ( memory image) and saves it to the file[2]
# octave m-file based on the m-file by Chris King # http://www.dhushara.com/DarkHeart/Viewers/source/siegel.m # an MyImage here is a matrix for 24 bit (3 byte) colors # load packages pkg load image; # imwrite pkg load miscellaneous; # waitbar # constan values nx = 480; ny = 480; MyImage = zeros(ny,nx,3); # 2D matrix filled with zeros magc=0.65; dSide=1/magc; Zxmin = -dSide; Zxmax = dSide; Zymin = -dSide; Zymax = dSide; stepy = (Zymax - Zymin)/(ny - 1); stepx = (Zxmax - Zxmin)/(nx - 1); # computations waitbar(0,'Please wait...'); # info for iy = 1:ny Zy = Zymax - iy*stepy; # invert y axis for ix= 1:nx Zx = Zxmin + ix*stepx; if(Zy>0 && Zx>0) # first quadrant should be in upper right position MyImage(iy,ix,2)=255-MyImage(iy,ix,2); endif; end # for ix waitbar(iy/ny); end # for iy # image(MyImage); # display image imwrite(MyImage,'s.png' ); # save image to the file
Special files
Dot files
Dot files are text files describing graphs in dot language. Example file :
digraph "BinaryAddingMachine" {
a [shape=circle]
b [shape=circle]
a -> a [label="1/1",color=red];
a -> a [label="2/2",color=blue];
b -> a [label="1/2",color=red];
b -> b [label="2/1",color=blue];
}
This file can be coverted to other formats using command line program dot. For example to svg :
dot -Tsvg b.dot -o b.svg
Parameter files
"Fractint uses Parameter files to save/restore all options and settings,[5] required to recreate particular images. The parameters required to describe an image require very little disk space, especially compared with saving the image itself. " [6]
Most important settigs are :
- plane description - par files
- fractal type ( formula) - see also frm files
- color gradient - see map files
Example file :
{ ; quite good spirals
reset=2000 type=mandel passes=1
corners=-0.6014129278/-0.5990935452/0.427747516/0.429487053
params=0/0 float=y maxiter=1000 inside=0 outside=15
distest=1/10/320/200
}
To use it :
- Save file to fractint main directory.
- Run fractint.
- press 2 key
- press F6 key
- select file
Reset causes Fractint to reset all calculation related parameters to their default values. Non-calculation parameters such as "printer=", "sound=", and "savename=" are not affected. [7]The reset=1730 in the parameter file shows that it was created with 17.3 version of Fractint. [8]
Video
Animated gif
Convert pgm ( or other ) static files into animated gif using BASH and Image Magic : [10]
#!/bin/bash # script file for BASH # which bash # save this file as g # chmod +x g # ./g # for all pgm files in this directory for file in *.pgm ; do # b is name of file without extension b=$(basename $file .pgm) # convert from pgm to gif and add text ( level ) using ImageMagic convert $file -pointsize 100 -annotate +10+100 $b ${b}.gif echo $file done # convert gif files to animated gif convert -delay 100 -loop 0 %d.gif[0-24] a24.gif echo OK # end
Dont forget about : 12.5MP limit = 500 x 500 x 50 frames = 600 x 600 x 34 frames = 1000 x 1000 x 12 frames
MPEG
Steps from pgm to video using Image Magic convert :
- pgm files to gif files
- gif files to video
convert -delay 100 -loop 0 %d.gif[0-25] a25.mpg
Ogv
#!/bin/bash # script file for BASH # which bash # save this file as g # chmod +x g # ./g i=0 # for all pgm files in this directory for file in *.pgm ; do # b is name of file without extension b=$(basename $file .pgm) # change file name to integers and count files ((i= i+1)) # convert from pgm to gif and add text ( Cx from name of file ) using ImageMagic convert $file -pointsize 50 -annotate +10+100 $b ${i}.gif echo $file done echo convert all gif files to one ogv file ffmpeg2theora %d.gif --framerate 12 --videoquality 9 -o output129.ogv echo b${i} OK # end
WebM
One can made a video from images. For examp
e creating WebM video files using ffmpeg [11][12]
ffmpeg -i x%08d.png -r 24 tifa.webm
or ffmpeg2theora[13]:
ffmpeg2theora %d.gif --framerate 5 --videoquality 9 -f webm --artist "your name" -o otput.webm
If you use files names containing parameter ( here Cx ), then it would be easy to sort files and make video :
char name [10]; /* name of file */ i = sprintf(name,"%2.7f",Cx); /* result (is saved in i) but is not used */ char *filename =strcat(name,".pgm"); /* new name thru concatenate of strings */
Viewer for programmers
This programm opens ppm/pgm binary files. It can be used to check image by checking output in console as mouse moves. Add your code to Motion function and update Zxmin and Zymin ( world coordinate).
/* * image.c * * read in a PPM or PGM binary image and display it, full size Based on code by : Dr. Lori L. Scarlatos Stony Brook University http://ms.cc.sunysb.edu/~lscarlatos/ "I do not have a license for image.c; it was created as an example for my students. Please feel free to use it. Best regards, Lori" * ---------------------------- * it does not opens asci versions of these files * examples files : * http://people.sc.fsu.edu/~jburkardt/data/data.html gcc i.c -lm -lGLU -lglut -Wall ./a.out p.pgm */ //#include <Windows.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> /* fabs*/ //#include <malloc.h> /* Global variables */ #define MAXLINE 80 /* maximum length of a line of text */ GLint ImageWidth, ImageHeight; /* size of the Image in pixels */ GLint iYmax,iXmax; GLubyte *Picture; /* Array of colors (GLubyte) */ const double ZyMin=-1.5; const double ZxMin=-1.5; const double PixelHeight=0.005008347; const double PixelWidth=0.005008347; int filetype; enum {P2, P3, P5, P6}; /* possible file types */ /* gives position of point (iX,iY) in 1D array ; uses also global variables */ unsigned int f(unsigned int _iX, unsigned int _iY) {return (_iX + (iYmax-_iY-1)*iXmax );} /* * Read from a PPM or PGM (binary) file * Output is a array of GLubyte */ void readPPM (char *filename, GLubyte **pic) { FILE *fp; char line[MAXLINE]; int i, j, size, rowsize; GLubyte *ptr; /* Read in file type */ fp = fopen(filename, "r"); /* in Unix rb = r */ if (fp==NULL) printf("I can't open %s file' !\n", filename); else printf("File %s has been opened !\n", filename); /* Each file starts with aa two-byte magic number (in ASCII) that explains : * - the type of file it is (PBM, PGM, and PPM) * - its encoding (ASCII or binary). * The magic number is a capital P followed by a single digit number. */ fgets (line, MAXLINE, fp); /* 1st line : Magic Number */ switch (line[1]) { case '2': filetype = P2; printf("This is PGM text file (P2) !\n"); break; case '3' : filetype = P3; printf("This is PPM text file (P3) !\n"); break; case '5': filetype = P5; printf("This is PGM binary file (P5) !\n"); break; case '6' : filetype = P6; printf("This is PPM binary file (P6) !\n"); break; default : printf("Error: need PPM or PGM file as input!\n"); exit(1); } /* if this is a comment, read next line. Maybe in binary files ther is no comment ?*/ /* there maybe more then one line of comment */ //fgets (line, MAXLINE, fp); //if (line[0]=='#') /* 2nd line : comment, not used */ /* Read in width and height, & allocate space */ /* these 2 numbers should be in one line with space between them */ fgets (line, MAXLINE, fp); /* 3nd line: width and height */ sscanf(line, "%d %d", &ImageWidth, &ImageHeight); printf ("iWidth = %d\n", ImageWidth); printf ("iHeight = %d\n", ImageHeight); iXmax=ImageWidth-1; iYmax=ImageHeight-1; if (filetype == P5) { size = ImageHeight * ImageWidth; /* greymap: 1 byte per pixel */ rowsize = ImageWidth; } else /* filetype == P6 */ { size = ImageHeight * ImageWidth * 3; /* pixmap: 3 bytes per pixel */ rowsize = ImageWidth * 3; } *pic = (GLubyte *)malloc (size); /* create dynamic array */ /* Read in maximum value (ignore) */ fgets (line, MAXLINE, fp); /* 3rd line */ if (filetype==P5 || filetype==P6){ /* Read in the pixel array row-by-row: 1st row = top scanline */ ptr = *pic + (ImageHeight-1) * rowsize; for (i = ImageHeight; i > 0; i--) { /* For binary File I/O you use fread and fwrite */ j = fread((void *)ptr, 1, rowsize, fp); ptr -= rowsize; } printf("File %s has been read !\n", filename); } else printf("Error: I can't read %s file !\n", filename); fclose(fp); printf("File %s has been closed !\n", filename); } /* Draw the picture on the screen */ void Draw(void) { /* black background of GLUT window */ glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on) glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations glFlush(); // Flush the OpenGL buffers to the window glRasterPos2i(0, 0); switch (filetype){ case P5 : /* greymap: use as illumination values */ glDrawPixels(ImageWidth, ImageHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, Picture); printf("Image has been drawn !\n"); break; case P6 : glDrawPixels(ImageWidth, ImageHeight, GL_RGB, GL_UNSIGNED_BYTE, Picture); printf("Image has been drawn !\n"); break; default : printf("Error: There is no image to draw !\n"); } } void Motion(int x, int y) { double Zx,Zy; int index; GLubyte Gray; /* invert y axis */ y = glutGet(GLUT_WINDOW_HEIGHT) - y; index=f(x,y); Gray=Picture[index]; /* convert pixel/screen coordinate to world/double coordinate */ Zy=ZyMin + y*PixelHeight; if (fabs(Zy)<PixelHeight/2) Zy=0.0; Zx=ZxMin + x*PixelWidth; /* prints to console */ if ((filetype==P5 || filetype==P6) && -1<x && x< ImageWidth && y<ImageHeight) printf("iX=%3d iY=%3d Zx=%2.9f Zy= %2.9f Gray=%3d \n", x, y,Zx,Zy,Gray); } static void Key(unsigned char key, int x, int y) { switch (key) { case 27: /* esc */ case 'q': case 'Q':exit(1); default: return ; } } /* Resize the picture */ void Reshape(GLint w, GLint h) { /* the viewport is the rectangular region of the window where the image is drawn */ glViewport(0, 0, ImageWidth-1, ImageHeight-1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, ImageWidth-1, 0, ImageHeight-1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /* Initialization: create window */ void MyInit(void) { glutInitWindowPosition(0, 0); glutInitWindowSize(ImageWidth, ImageHeight); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); if (glutCreateWindow("Image") == GL_FALSE) exit(1); } /* ------------------ Main program ---------------------------------------*/ int main(int argc, char **argv) { char filename[MAXLINE]; /* Read in the file (allocates space for Picture) */ if (argc < 2) { printf ("Enter the name of a PPM or PGM file: "); scanf("%s", filename); readPPM ((char *)filename, &Picture); } else { readPPM (argv[1], &Picture); } glutInit(&argc, argv); MyInit(); glutPassiveMotionFunc(Motion); glutReshapeFunc(Reshape); glutDisplayFunc(Draw); glutKeyboardFunc(Key); glutMainLoop(); return 0; }
See also
- Underhanded C: The Leaky Redaction by John Meacham
- ppm file in Haskell from University of Melbourne
- PPM in Haskell by Ryan Lothian
- Image processing in Haskell using PPM by Daniel Díaz
References
- ↑ The Computer Language Benchmarks Game
- ↑ Sigel disc in Matlab by Chris King
- ↑ A short Introducion to PAR Files by Laurent Chabin
- ↑ julian haight : filmer instructions
- ↑ Fractint doc index
- ↑ Fractint par files by Rupert Russell
- ↑ fractint Image Calculation Parameters
- ↑ [Fractint] FOTD 27-07-11 (Bad Moon on the Rise [No Rating])
- ↑ Gnu Parallel
- ↑ Moebius transformation animated GIFs by Fritz Mueller
- ↑ How this video was made by Mukund
- ↑ mini-fract in Lisp by Yannick Gingras
- ↑ wikibooks help about converting video : ffmpeg2theora