diff options
author | iovar <iovar@f606c939-3180-4ac9-a4b8-4b8779d57d0a> | 2006-10-22 10:21:48 +0000 |
---|---|---|
committer | iovar <iovar@f606c939-3180-4ac9-a4b8-4b8779d57d0a> | 2006-10-22 10:21:48 +0000 |
commit | b085cea3f8a4cf1e9e273cafc058ac19b71faaf9 (patch) | |
tree | ddb78599ea1313208b3eba0f01b026e6410e9508 | |
parent | b97e62f7b25ef160f371d0707c6ca94a1d8b14aa (diff) |
removed obsolete screenshot functionality, added first test of cache_frame
git-svn-id: https://recordmydesktop.svn.sourceforge.net/svnroot/recordmydesktop/trunk@104 f606c939-3180-4ac9-a4b8-4b8779d57d0a
-rw-r--r-- | rMD-exp/configure.ac | 2 | ||||
-rw-r--r-- | rMD-exp/include/recordmydesktop.h | 41 | ||||
-rw-r--r-- | rMD-exp/src/Makefile.am | 4 | ||||
-rw-r--r-- | rMD-exp/src/cache_frame.c | 147 | ||||
-rw-r--r-- | rMD-exp/src/opendev.c | 2 | ||||
-rw-r--r-- | rMD-exp/src/parseargs.c | 26 | ||||
-rw-r--r-- | rMD-exp/src/recordmydesktop.c | 88 | ||||
-rw-r--r-- | rMD-exp/src/zpixmaptobmp.c | 78 |
8 files changed, 227 insertions, 161 deletions
diff --git a/rMD-exp/configure.ac b/rMD-exp/configure.ac index 6850723..02d74d2 100644 --- a/rMD-exp/configure.ac +++ b/rMD-exp/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.59) AC_INIT(src/recordmydesktop.c) -AM_INIT_AUTOMAKE(recordmydesktop,0.2.6,) +AM_INIT_AUTOMAKE(recordmydesktop,0.3.1,) AC_CONFIG_SRCDIR([src/recordmydesktop.c]) AM_CONFIG_HEADER(config.h) diff --git a/rMD-exp/include/recordmydesktop.h b/rMD-exp/include/recordmydesktop.h index 4533b87..9255525 100644 --- a/rMD-exp/include/recordmydesktop.h +++ b/rMD-exp/include/recordmydesktop.h @@ -141,8 +141,6 @@ typedef struct _ProgArgs{ int shared_thres; //threshold to use shared memory int full_shots; //do not poll damage, take full screenshots int no_quick_subsample;//average pixels in chroma planes - int scshot; //take screenshot and exit(default 0) - int scale_shot; //screenshot subscale factor(default 1) int v_bitrate,v_quality,s_quality;//video bitrate,video-sound quality int dropframes; //option for theora encoder }ProgArgs; @@ -231,6 +229,39 @@ typedef struct _ProgData{ snd_pcm_uframes_t periodsize; }ProgData; + +//This is the header of every frame. +//Reconstruction will be correct only if made on +//the same platform. + +//We need the total number of blocks +//and the position number of each of them +//(separately for y,u,v planes). +//The number of the frame compared to the +//number of time expirations at the time of +//caching, will enable us to make up for lost frames. + + +typedef struct _FrameHeader{ + + unsigned int frameno;//number of frame(cached frames) + unsigned int current_total;//number of frames that should have been + //taken at time of caching this one + unsigned short Ynum;//number of changed blocks in the Y plane + unsigned short Unum;//number of changed blocks in the U plane + unsigned short Vnum;//number of changed blocks in the V plane + unsigned char *YBlocks;//identifying number on the grid, starting at top left + unsigned char *UBlocks;// >> >> + unsigned char *VBlocks;// >> >> + unsigned char *YData;//data for the blocks that have changed, + unsigned char *UData;//which have to be remapped on the buffer when reading + unsigned char *VData; + +}FrameHeader; + + + + /**Globals*/ //I've read somewhere that I'll go to hell for using globals... @@ -318,8 +349,8 @@ int capture_busy, (args)->display=NULL;\ (args)->windowid=(args)->x=(args)->y\ =(args)->width=(args)->height=(args)->quietmode\ - =(args)->nosound=(args)->scshot=(args)->full_shots=0;\ - (args)->noshared=(args)->scale_shot=1;\ + =(args)->nosound=(args)->full_shots=0;\ + (args)->noshared=1;\ (args)->dropframes=(args)->nocondshared=0;\ (args)->no_quick_subsample=1;\ (args)->filename=(char *)malloc(8);\ @@ -496,7 +527,6 @@ int GetZPixmap(Display *dpy,Window root,char *data,int x,int y,int width,int hei int ParseArgs(int argc,char **argv,ProgArgs *arg_return); void QueryExtensions(Display *dpy,ProgArgs *args,int *damage_event,int *damage_error); int SetBRWindow(Display *dpy,BRWindow *brwin,DisplaySpecs *specs,ProgArgs *args); -int ZPixmapToBMP(XImage *imgz,BRWindow *brwin,char *fname,int nbytes,int scale); unsigned char *MakeDummyPointer(DisplaySpecs *specs,int size,int color,int type,unsigned char *npxl); void *CaptureSound(void *pdata); void *EncodeSoundBuffer(void *pdata); @@ -504,5 +534,6 @@ snd_pcm_t *OpenDev(const char *pcm_dev,unsigned int *channels,unsigned int *freq void InitEncoder(ProgData *pdata,EncData *enc_data_t); void MakeMatrices(); void SizePack2_8_16(int *start,int *size,int limit); +void *CacheImageBuffer(void *pdata); #endif diff --git a/rMD-exp/src/Makefile.am b/rMD-exp/src/Makefile.am index e56b856..4315ab3 100644 --- a/rMD-exp/src/Makefile.am +++ b/rMD-exp/src/Makefile.am @@ -3,7 +3,6 @@ bin_PROGRAMS = recordmydesktop recordmydesktop_SOURCES= recordmydesktop.c\ - zpixmaptobmp.c\ getzpixmap.c\ parseargs.c\ rectinsert.c\ @@ -20,7 +19,8 @@ recordmydesktop_SOURCES= recordmydesktop.c\ opendev.c\ capture_sound.c\ encode_sound_buffer.c\ - init_encoder.c + init_encoder.c\ + cache_frame.c INCLUDES= $(all_includes) -I../include -I$x_includes diff --git a/rMD-exp/src/cache_frame.c b/rMD-exp/src/cache_frame.c new file mode 100644 index 0000000..f1d3251 --- /dev/null +++ b/rMD-exp/src/cache_frame.c @@ -0,0 +1,147 @@ +/********************************************************************************* +* recordMyDesktop * +********************************************************************************** +* * +* Copyright (C) 2006 John Varouhakis * +* * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the Free Software * +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * +* * +* * +* * +* For further information contact me at johnvarouhakis@gmail.com * +**********************************************************************************/ + +#include <recordmydesktop.h> + +void MakeChecksums(unsigned char *buf,int width,int height,int divisor,unsigned short int *checksums){ + int i,k,j,m; + + for(i=0;i<divisor;i++){ + for(k=0;k<divisor;k++){ + int A=1,B=0; + for(j=0;j<height/divisor;j++){ + for(m=0;m<width/divisor;m++){ + unsigned char cur=buf[i*(width*height/divisor)+j*width+k*width/divisor+m]; + A+=cur; + B+=A+cur; + } + } + A=A%65521; + B=B%65521; + checksums[i*divisor+k]=A+B; + } + } +} + +void *CacheImageBuffer(void *pdata){ + pthread_mutex_t pmut,imut; + pthread_mutex_init(&pmut,NULL); + pthread_mutex_init(&imut,NULL); + yuv_buffer yuv[2]; + + + unsigned short int checksums_y[2][256], + checksums_u[2][64], + checksums_v[2][64]; + int i,current=0,divisor=16,firstrun=1; + + //we want to make sure that each block has a sufficient + //number of bytes, so that the checksum will wrap + //around 65521. + while(((((ProgData *)pdata)->brwin.rgeom.width* + ((ProgData *)pdata)->brwin.rgeom.width ) + /pow(divisor,2)) + <=1024){ + divisor/=2; + if(divisor==2) + break; + } + + + for(i=0;i<2;i++){ + yuv[i].y_width=((ProgData *)pdata)->enc_data->yuv.y_width; + yuv[i].y_height=((ProgData *)pdata)->enc_data->yuv.y_height; + yuv[i].uv_width=((ProgData *)pdata)->enc_data->yuv.uv_width; + yuv[i].uv_height=((ProgData *)pdata)->enc_data->yuv.uv_height; + + yuv[i].y=(unsigned char *)malloc(yuv[i].y_width*yuv[i].y_height); + yuv[i].u=(unsigned char *)malloc(yuv[i].uv_width*yuv[i].uv_height); + yuv[i].v=(unsigned char *)malloc(yuv[i].uv_width*yuv[i].uv_height); + } + + + while(((ProgData *)pdata)->running){ + pthread_cond_wait(&((ProgData *)pdata)->image_buffer_ready,&imut); + if(Paused) + pthread_cond_wait(&((ProgData *)pdata)->pause_cond,&pmut); + pthread_mutex_lock(&((ProgData *)pdata)->yuv_mutex); + + //rotate buffers + current=(current)?0:1; + //copy incoming + memcpy(yuv[current].y,((ProgData *)pdata)->enc_data->yuv.y,yuv[current].y_width*yuv[current].y_height); + memcpy(yuv[current].u,((ProgData *)pdata)->enc_data->yuv.u,yuv[current].uv_width*yuv[current].uv_height); + memcpy(yuv[current].v,((ProgData *)pdata)->enc_data->yuv.v,yuv[current].uv_width*yuv[current].uv_height); + //release main buffer + pthread_mutex_unlock(&((ProgData *)pdata)->yuv_mutex); + //get checksums for new + MakeChecksums(yuv[current].y,yuv[current].y_width,yuv[current].y_height,divisor,checksums_y[current]); + MakeChecksums(yuv[current].u,yuv[current].uv_width,yuv[current].uv_height,divisor/2,checksums_u[current]); + MakeChecksums(yuv[current].v,yuv[current].uv_width,yuv[current].uv_height,divisor/2,checksums_v[current]); + + //find and flush different blocks + if(firstrun){ + firstrun=0; + continue; + } + else{ + int prev=(current)?0:1; + int j; + unsigned short ynum,unum,vnum; + unsigned char yblocks[256],ublocks[64],vblocks[64]; + ynum=unum=vnum=0; + for(j=0;j<pow(divisor,2);j++){ + if(checksums_y[current][j]!=checksums_y[prev][j]){ + ynum++; + yblocks[ynum-1]=j; + } + } + for(j=0;j<pow(divisor/2,2);j++){ + if(checksums_u[current][j]!=checksums_u[prev][j]){ + unum++; + ublocks[unum-1]=j; + } + } + for(j=0;j<pow(divisor/2,2);j++){ + if(checksums_v[current][j]!=checksums_v[prev][j]){ + vnum++; + vblocks[vnum-1]=j; + } + } + ((ProgData *)pdata)->avd+=((ProgData *)pdata)->frametime*2*((ProgData *)pdata)->args.channels; +// fprintf(stderr,"k %d uk %d vk %d\n ",k,uk,vk); + } + } + + //clean up since we're not finished + for(i=0;i<2;i++){ + free(yuv[i].y); + free(yuv[i].u); + free(yuv[i].v); + } + + pthread_exit(&errno); +} diff --git a/rMD-exp/src/opendev.c b/rMD-exp/src/opendev.c index 4b559ec..9f8aa17 100644 --- a/rMD-exp/src/opendev.c +++ b/rMD-exp/src/opendev.c @@ -40,7 +40,7 @@ snd_pcm_t *OpenDev(const char *pcm_dev,unsigned int *channels,unsigned int *freq snd_pcm_hw_params_alloca(&hwparams); snd_pcm_uframes_t buffsize=4096; - if (snd_pcm_open(&mhandle, pcm_dev, SND_PCM_STREAM_CAPTURE, 0)<0){ + if (snd_pcm_open(&mhandle, pcm_dev, SND_PCM_STREAM_CAPTURE, 0x0002)<0){ fprintf(stderr, "Couldn't open PCM device %s\n", pcm_dev); return NULL; } diff --git a/rMD-exp/src/parseargs.c b/rMD-exp/src/parseargs.c index 5280cf2..a335b59 100644 --- a/rMD-exp/src/parseargs.c +++ b/rMD-exp/src/parseargs.c @@ -36,7 +36,7 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){ "\t -v_quality n| -s_quality n| -v_bitrate n| --no-framedrop| -dummy-cursor color|\n" "\t --no-cursor| -freq N(number>0)| -channels N(number>0)| -device SOUND_DEVICE|\n" "\t --nosound| --with-shared| --no-cond-shared| -shared-threshold n| --full-shots|\n" - "\t --quick-subsampling| --scshot| -scale-shot N| -o filename]^filename\n\n\n" + "\t --quick-subsampling| -o filename]^filename\n\n\n" "General Options:\n" "\t-h or --help\t\tPrint this help and exit.\n" @@ -73,8 +73,6 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){ "Misc Options:\n" "\t-delay n[H|h|M|m]\tNumber of secs(default),minutes or hours before capture starts(number can be float)\n" - "\t--scshot\t\tTake a bitmap screenshot(default rmdout.bmp) and exit.\n" - "\t-scale-shot N\t\tFactor by which screenshot is scaled down(1<=number<=64,power of 2).\n" "\t-o filename\t\tName of recorded video(default out.ogg).\n" "\n\tIf no other options are specified, filename can be given without the -o switch.\n\n\n"; @@ -353,24 +351,6 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){ } i++; } - else if(!strcmp(argv[i],"-scale-shot")){ - if(i+1<argc){ - int num=atoi(argv[i+1]); - if((num==1)||(num==2)||(num==4)||(num==8) - ||(num==16)||(num==32)||(num==64)){ - arg_return->scale_shot=num; - } - else{ - fprintf(stderr,"Argument Usage: -scale-shot N(0<number<64,power of 2)\n"); - return 1; - } - } - else{ - fprintf(stderr,"Argument Usage: -scale-shot N(0<number<64,power of 2)\n"); - return 1; - } - i++; - } else if(!strcmp(argv[i],"-device")){ if(i+1<argc){ free(arg_return->device); @@ -397,10 +377,6 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){ arg_return->full_shots=1; arg_return->nocondshared=1; } - else if(!strcmp(argv[i],"--scshot")){ - arg_return->scshot=1; - arg_return->nocondshared=1; - } else if(!strcmp(argv[i],"--quick-subsampling")){ arg_return->no_quick_subsample=0; } diff --git a/rMD-exp/src/recordmydesktop.c b/rMD-exp/src/recordmydesktop.c index 5b7e32b..15292f9 100644 --- a/rMD-exp/src/recordmydesktop.c +++ b/rMD-exp/src/recordmydesktop.c @@ -54,6 +54,7 @@ int main(int argc,char **argv){ pthread_t poll_damage_t, image_capture_t, image_encode_t, + image_cache_t, sound_capture_t, sound_encode_t, flush_to_ogg_t; @@ -76,38 +77,37 @@ int main(int argc,char **argv){ //these are globals, look for them at the header frames_total=frames_lost=encoder_busy=capture_busy=0; - if(!pdata.args.scshot){ - fprintf(stderr,"Initializing...\n"); - MakeMatrices(); - if(pdata.args.have_dummy_cursor){ - pdata.dummy_pointer=MakeDummyPointer(&pdata.specs,16,pdata.args.cursor_color,0,&pdata.npxl); - pdata.dummy_p_size=16; - } + fprintf(stderr,"Initializing...\n"); + MakeMatrices(); + if(pdata.args.have_dummy_cursor){ + pdata.dummy_pointer=MakeDummyPointer(&pdata.specs,16,pdata.args.cursor_color,0,&pdata.npxl); + pdata.dummy_p_size=16; } - if((pdata.args.noshared)||(pdata.args.scshot)) + + if((pdata.args.noshared)) pdata.datamain=(char *)malloc(pdata.brwin.nbytes); - if(!pdata.args.scshot){ - if(pdata.args.noshared) - pdata.datatemp=(char *)malloc(pdata.brwin.nbytes); - pdata.rect_root[0]=pdata.rect_root[1]=NULL; - pthread_mutex_init(&pdata.list_mutex[0],NULL); - pthread_mutex_init(&pdata.list_mutex[1],NULL); - pthread_mutex_init(&pdata.sound_buffer_mutex,NULL); - pthread_mutex_init(&pdata.libogg_mutex,NULL); - pthread_mutex_init(&pdata.yuv_mutex,NULL); - - pthread_cond_init(&pdata.time_cond,NULL); - pthread_cond_init(&pdata.pause_cond,NULL); - pthread_cond_init(&pdata.image_buffer_ready,NULL); - pthread_cond_init(&pdata.sound_buffer_ready,NULL); - pthread_cond_init(&pdata.sound_data_read,NULL); - pdata.list_selector=Paused=Aborted=pdata.avd=0; - pdata.running=1; - time_cond=&pdata.time_cond; - pause_cond=&pdata.pause_cond; - Running=&pdata.running; - } - if((pdata.args.noshared)||(pdata.args.scshot)){ + + if(pdata.args.noshared) + pdata.datatemp=(char *)malloc(pdata.brwin.nbytes); + pdata.rect_root[0]=pdata.rect_root[1]=NULL; + pthread_mutex_init(&pdata.list_mutex[0],NULL); + pthread_mutex_init(&pdata.list_mutex[1],NULL); + pthread_mutex_init(&pdata.sound_buffer_mutex,NULL); + pthread_mutex_init(&pdata.libogg_mutex,NULL); + pthread_mutex_init(&pdata.yuv_mutex,NULL); + + pthread_cond_init(&pdata.time_cond,NULL); + pthread_cond_init(&pdata.pause_cond,NULL); + pthread_cond_init(&pdata.image_buffer_ready,NULL); + pthread_cond_init(&pdata.sound_buffer_ready,NULL); + pthread_cond_init(&pdata.sound_data_read,NULL); + pdata.list_selector=Paused=Aborted=pdata.avd=0; + pdata.running=1; + time_cond=&pdata.time_cond; + pause_cond=&pdata.pause_cond; + Running=&pdata.running; + + if((pdata.args.noshared)){ pdata.image=XCreateImage(pdata.dpy, pdata.specs.visual, pdata.specs.depth, ZPixmap, 0,pdata.datamain,pdata.brwin.rgeom.width, pdata.brwin.rgeom.height, 8, 0); XInitImage(pdata.image); @@ -128,18 +128,6 @@ int main(int argc,char **argv){ } XShmGetImage(pdata.dpy,pdata.specs.root,pdata.shimage,pdata.brwin.rgeom.x,pdata.brwin.rgeom.y,AllPlanes); } - if(pdata.args.scshot){ - if(pdata.args.delay>0){ - fprintf(stderr,"Will sleep for %d seconds now.\n",pdata.args.delay); - sleep(pdata.args.delay); - } - //get a new screenshot - GetZPixmap(pdata.dpy,pdata.specs.root,pdata.image->data,pdata.brwin.rgeom.x,pdata.brwin.rgeom.y, - pdata.brwin.rgeom.width,pdata.brwin.rgeom.height); - ZPixmapToBMP(pdata.image,&pdata.brwin,((!strcmp(pdata.args.filename,"out.ogg"))?"rmdout.bmp":pdata.args.filename),pdata.brwin.nbytes,pdata.args.scale_shot); - fprintf(stderr,"done!\n"); - exit(0); - } if(!pdata.args.nosound){ pdata.sound_handle=OpenDev(pdata.args.device,&pdata.args.channels,&pdata.args.frequency,&pdata.periodsize, &pdata.periodtime,&pdata.hard_pause); if(pdata.sound_handle==NULL){ @@ -147,6 +135,7 @@ int main(int argc,char **argv){ exit(3); } } + InitEncoder(&pdata,&enc_data); for(i=0;i<(pdata.enc_data->yuv.y_width*pdata.enc_data->yuv.y_height);i++) pdata.enc_data->yuv.y[i]=0; @@ -189,12 +178,14 @@ int main(int argc,char **argv){ if(!pdata.args.full_shots) pthread_create(&poll_damage_t,NULL,PollDamage,(void *)&pdata); pthread_create(&image_capture_t,NULL,GetFrame,(void *)&pdata); - pthread_create(&image_encode_t,NULL,EncodeImageBuffer,(void *)&pdata); +// pthread_create(&image_encode_t,NULL,EncodeImageBuffer,(void *)&pdata); + pthread_create(&image_cache_t,NULL,CacheImageBuffer,(void *)&pdata); + if(!pdata.args.nosound){ pthread_create(&sound_capture_t,NULL,CaptureSound,(void *)&pdata); - pthread_create(&sound_encode_t,NULL,EncodeSoundBuffer,(void *)&pdata); +// pthread_create(&sound_encode_t,NULL,EncodeSoundBuffer,(void *)&pdata); } - pthread_create(&flush_to_ogg_t,NULL,FlushToOgg,(void *)&pdata); +// pthread_create(&flush_to_ogg_t,NULL,FlushToOgg,(void *)&pdata); RegisterCallbacks(&pdata.args); @@ -204,24 +195,23 @@ int main(int argc,char **argv){ pthread_join(image_capture_t,NULL); fprintf(stderr,"Shutting down."); - pthread_join(image_encode_t,NULL); +// pthread_join(image_encode_t,NULL); fprintf(stderr,"."); if(!pdata.args.nosound){ pthread_join(sound_capture_t,NULL); fprintf(stderr,"."); - pthread_join(sound_encode_t,NULL); +// pthread_join(sound_encode_t,NULL); fprintf(stderr,"."); } else fprintf(stderr,".."); - pthread_join(flush_to_ogg_t,NULL); +// pthread_join(flush_to_ogg_t,NULL); fprintf(stderr,"."); if(!pdata.args.full_shots) pthread_join(poll_damage_t,NULL); fprintf(stderr,"."); if((!pdata.args.noshared)||(!pdata.args.nocondshared)){ XShmDetach (pdata.dpy, &shminfo); -// XDestroyImage (pdata.image); shmdt (&shminfo.shmaddr); shmctl (shminfo.shmid, IPC_RMID, 0); } diff --git a/rMD-exp/src/zpixmaptobmp.c b/rMD-exp/src/zpixmaptobmp.c deleted file mode 100644 index 0aa9477..0000000 --- a/rMD-exp/src/zpixmaptobmp.c +++ /dev/null @@ -1,78 +0,0 @@ -/********************************************************************************* -* recordMyDesktop * -********************************************************************************** -* * -* Copyright (C) 2006 John Varouhakis * -* * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the Free Software * -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * -* * -* * -* * -* For further information contact me at johnvarouhakis@gmail.com * -**********************************************************************************/ - - -#include <recordmydesktop.h> - -int ZPixmapToBMP(XImage *imgz,BRWindow *brwin,char *fname,int nbytes,int scale){ - FILE *fpbmp; - int i,k; - int siz=52+nbytes/(pow(scale,2)); - int offs=54+1024; - short int rsrvd=0; - int hsiz=40; - int width=brwin->rgeom.width/scale,height=brwin->rgeom.height/scale,nbts=nbytes/(pow(scale,2)); - unsigned short int planes=1; - unsigned short int bpp=24; - unsigned int cmpr=0; - unsigned int ncols=0; - char *dtap=imgz->data; - - /*Write header*/ - fpbmp=fopen(fname,"wb"); - fputc('B',fpbmp); - fputc('M',fpbmp); - fwrite(&siz,4,1,fpbmp); - fwrite(&rsrvd,2,1,fpbmp); - fwrite(&rsrvd,2,1,fpbmp); - fwrite(&offs,4,1,fpbmp); - fwrite(&hsiz,4,1,fpbmp); - fwrite(&(width),4,1,fpbmp); - fwrite(&(height),4,1,fpbmp); - fwrite(&planes,2,1,fpbmp); - fwrite(&bpp,2,1,fpbmp); - fwrite(&cmpr,4,1,fpbmp); - fwrite(&nbts,4,1,fpbmp); - fwrite(&(width),4,1,fpbmp); - fwrite(&(height),4,1,fpbmp); - fwrite(&(ncols),4,1,fpbmp); - fwrite(&(ncols),4,1,fpbmp); - for(i=0;i<1024;i++) - fputc(0,fpbmp); - /*Data*/ - for(k=(nbytes/imgz->bytes_per_line)-1;k>=0;k-=scale){ - for(i=0;i<imgz->bytes_per_line/4;i+=scale){ - fwrite(&dtap[(i*4)+k*(imgz->bytes_per_line)],1,1,fpbmp); - fwrite(&dtap[(i*4)+k*(imgz->bytes_per_line)+1],1,1,fpbmp); - fwrite(&dtap[(i*4)+k*(imgz->bytes_per_line)+2],1,1,fpbmp); - } - } - - fclose(fpbmp); - return 0; -} - - |