This patch allows the user to extract frames from any xanim-playable animation into individual PPM frames. (I created it so I could convert Amiga Moviesetter animations (Eric Schwartz, we love you) into the more portable formats.) Because of my laziness, this will probably bomb on anything other than an 8-bit display. Usage: xanimhacked {otherflags} -s startingframe animfile The ppm files will be written into the current directory using the anim's filename as a prefix and the frame number as the suffix. (Be careful you don't run out of disk space!) -- Chris Baird,, *** xanim2683/xanim.c Fri Jul 1 09:16:47 1994 --- /usr/home/cjb/Code/xanim.c Sat Jun 24 02:19:00 1995 *************** *** 61,64 **** --- 60,65 ---- ULONG fli_pad_kludge; + void Save_Frame(); + void TheEnd(); void TheEnd1(); *************** *** 439,442 **** --- 440,444 ---- XA_PAUSE *xa_pause_hdr=0; + int save_frame; /* *************** *** 732,735 **** --- 734,738 ---- fli_pad_kludge = FALSE; xa_pause_hdr = 0; + save_frame = 99999; XA_Time_Init(); *************** *** 1099,1102 **** --- 1102,1107 ---- } break; + case 's': + j++; save_frame = XA_Read_Float (in,&j); break; case 't': xa_time_flag = opt_on; j++; break; *************** *** 2492,2495 **** --- 2497,2505 ---- XStoreName(theDisp,mainW,xa_title); } + + /* saving frames hack cjb 950531 */ + if (cur_frame >= save_frame) + Save_Frame(); + /* Harry, what time is it? and how much left? default to 1 ms */ t_frame_end = XA_Time_Read() - t_frame_start; *************** *** 3359,3360 **** --- 3369,3480 ---- + /* write an xImage to a PPM-format file + * lifted from the xv-3.01 sources, which in turn lifted it from pbmplus + */ + void Save_Frame() + { + #define CARD8 unsigned char + #define CARD16 unsigned short + #define CARD32 unsigned int + #define byte unsigned char + + /* I'm really proud of this, uhuh.. */ + register int x, y; + unsigned short r, g, b; + char filename[256]; + XColor cpixel; + XImage* img; + FILE *fp; + + int i, j; + CARD8 *bptr, tmpbyte; + CARD16 *sptr, sval; + CARD32 *lptr, lval; + CARD8 *pptr, *lineptr; + int bits_used, bits_per_item, bit_shift, bit_order; + int bits_per_pixel, byte_order; + CARD32 pixvalue, pixmask; + int isLsbMachine, flipBytes; + union { + CARD32 l; + CARD16 s; + CARD8 b[sizeof(CARD32)]; + } sw; + + /* determine byte order of the machine we're running on */ + sw.l = 1; isLsbMachine = (sw.b[0]) ? 1 : 0; + + sprintf (filename, "%s.ppm.%05ld", cur_file->name, cur_frame); + if ((fp = fopen (filename, "w")) == NULL) + { + fprintf (stderr, "MASSIVE FUCK UP!!! File: %s\n", filename); + exit (0); + } + fprintf (stderr, "%s\n", filename); + fprintf(fp, "P6\n"); + fprintf(fp, "%d %d\n", cur_file->imagex, cur_file->imagey); + fprintf(fp, "%d\n", 255); + + img = XGetImage (theDisp, mainW, 0, 0, cur_file->imagex, cur_file->imagey, AllPlanes, ZPixmap); + + bits_per_item = img->bitmap_unit; + bits_used = bits_per_item; + bits_per_pixel = img->bits_per_pixel; + if (bits_per_pixel == 32) pixmask = 0xffffffff; + else pixmask = (((CARD32) 1) << bits_per_pixel) - 1; + bit_order = img->bitmap_bit_order; + byte_order = img->byte_order; + flipBytes = ( isLsbMachine && byte_order != LSBFirst) || (!isLsbMachine && byte_order == LSBFirst); + + for (i=0; iheight; i++) { + lineptr = (byte *) img->data + (i * img->bytes_per_line); + bptr = ((CARD8 *) lineptr) - 1; + sptr = ((CARD16 *) lineptr) - 1; + lptr = ((CARD32 *) lineptr) - 1; + bits_used = bits_per_item; + + for (j=0; jwidth; j++) { + if (bits_used == bits_per_item) { + switch (bits_per_item) { + case 8: bptr++; break; + case 16: sptr++; sval = *sptr; + if (flipBytes) { + sw.s = sval; tmpbyte = sw.b[0]; sw.b[0] = sw.b[1]; + sw.b[1] = tmpbyte; sval = sw.s; + } + break; + case 32: lptr++; lval = *lptr; + if (flipBytes) { + sw.l = lval; tmpbyte = sw.b[0]; sw.b[0] = sw.b[3]; + sw.b[3] = tmpbyte; tmpbyte = sw.b[1]; sw.b[1] = sw.b[2]; + sw.b[2] = tmpbyte; lval = sw.l; + } + break; + } + + bits_used = 0; + if (bit_order == MSBFirst) bit_shift = bits_per_item - bits_per_pixel; + else bit_shift = 0; + } + + switch (bits_per_item) { + case 8: pixvalue = (*bptr >> bit_shift) & pixmask; break; + case 16: pixvalue = ( sval >> bit_shift) & pixmask; break; + case 32: pixvalue = ( lval >> bit_shift) & pixmask; break; + } + + if (bit_order == MSBFirst) bit_shift -= bits_per_pixel; + else bit_shift += bits_per_pixel; + bits_used += bits_per_pixel; + + r = xa_cmap[pixvalue & 255].red >> 8; + g = xa_cmap[pixvalue & 255].green >> 8; + b = xa_cmap[pixvalue & 255].blue >> 8; + fwrite (&r, 1, 1, fp); + fwrite (&g, 1, 1, fp); + fwrite (&b, 1, 1, fp); + } + } + fclose (fp); + XDestroyImage (img); + }