/** ** ** NUMPIC.POC - Ways to convert a numbered sequence of picture files ** to a flic and back. Also a way to delete the numbered sequence of ** pictures when you're done. ** **/ #pragma poco library "pdracces.poe" // extended picture I/O library #include #define NO_DIALOG 0 // Parameter to pdraccess options routine #define DO_DIALOG 1 // Parameter to pdraccess options routine /*---------------------------------------------------------------------------- * dialog strings, menu choices, etc... *--------------------------------------------------------------------------*/ char basename_prompt[] = "Base name of numbered pictures?"; char rgbname_prompt[] = "Name of (RGB) pic to load?"; char replace_changes_prompt[] = "Okay to discard current flic?\n" "(You have %d unsaved changes)" ; char change_flic_size_prompt[] = "Force flic size to picture size?\n\n" "(Current flic size is %d x %d,\n" "input picture size is %d x %d.)\n" ; char menu_prompt[] = "Convert between Flic and Pictures"; char *menu_choices[] = { " Save Flic as Pics", " Load Pics as Flic", " Delete Numbered files", " Load Single (RGB) Pic", " Exit", }; enum {MU_EXIT, MU_SAVE, MU_LOAD, MU_DELETE, MU_LOAD1}; char load_prompt[] = "Found %d pictures.\n\n" "The pictures may be appended to the end of the " "current flic, inserted following the current frame, " "or entirely replace the current flic. " "\n\n" "Please select load option:\n" ; char *load_choices[] = {"Append", "Insert", "Replace", "Cancel"}; enum {LOAD_APPEND=1, LOAD_INSERT, LOAD_REPLACE, LOAD_CANCEL}; char pdr_prompt[] = "Please select output format:"; char *pdr_choices[] = {"GIF", "PCX", "TIFF", "TARGA", "Cancel"}; char *pdr_names[] = {"GIF.PDR", "PCX.PDR", "TIFF.PDR", "TARGA.PDR"}; char *start_of_final_digits(char *pt) /*********************************************************************** * returns pointer to the start of the ending number in the string. ***********************************************************************/ { char c; int len; int i; i = len = strlen(pt); pt += len; while (--i >= 0) { c = *(--pt); if (!(c >= '0' && c <= '9')) return(pt+1); } return pt; } int get_num_name(char *name) /*********************************************************************** * Return the number embedded in the "file" portion of a file-name * (as opposed to the directory or the suffix.) Return -1 if none. ***********************************************************************/ { char *pt; char dev[4],dir[70],file[10],suff[5]; fnsplit(name,dev,dir,file,suff); if ((pt = start_of_final_digits(file)) == file) return(-1); return(atoi(pt)); } int count_digits(int num) /*********************************************************************** * Return number of digits (base 10) in number. ***********************************************************************/ { int digits = 1; while (num > 10) { ++digits; num /= 10; } return(digits); } void make_num_name(char *buf, char *name, int num, int digits) /*********************************************************************** * Given a full file name (device, path, file, suffix), a number, * and a minimum count of digits, make a name with the number * embedded in the last parts of the 'file' portion of the name. * Parameters: * char *buf; where to put the numbered name * char *name; the original name. * int num; the number. * int digits; minimum amount of digits to use. * Example: * make_num_name(buf, "c:\pics\sample.gif", 16, 3) * leaves "c:\pics\sampl016.gif" in buf. ***********************************************************************/ { char dev[4],dir[70],file[10],suff[5]; char nfile[10]; int diglen; char *pt; fnsplit(name,dev,dir,file,suff); // split file into component parts if (count_digits(num)>digits) // if number too big override digits digits = count_digits(num); pt = start_of_final_digits(file); diglen = strlen(pt); // find out how many digits already in file name if (diglen < digits) { // if less than needed truncate file name file[8-digits] = 0; diglen = digits; } else { // Otherwise truncate at first digit *pt = 0; } sprintf(nfile,"%s%0*d", file, diglen, num); fnmerge(buf,dev,dir,nfile,suff); } ErrCode set_up_for_output(char *name) /*********************************************************************** * find and load the pdr to handle the output format, get output options. * we try to figure out the pdr name from the basename filetype, but * if that doesn't work (eg, if there is no suffix on the basename), * we prompt the user for the output format using Qmenu. * after a pdr is loaded to handle the output, we check whether output * options are supported by the pdr, and if so, we call the pdr's * options preset dialog. **********************************************************************/ { ErrCode err; int thechoice; char *pdrname; if (Success > (err = PicDriverFindLoad(name))) { thechoice = Qmenu(pdr_choices, Array_els(pdr_choices), pdr_prompt); if (--thechoice < 0) // convert choice # to array index, return Err_abort; // if < 0, user picked Cancel or right-clicked if (Success > (err = PicDriverLoad(pdr_names[thechoice]))) { return Qerror(err, "Cannot load picture driver %s",pdr_names[thechoice]); } } if (PicPdrHasOptions()) { if (Success > (err = PicPdrOptionsPreset(DO_DIALOG, 0))) return err; } return Success; } void save_pics(char *name) /*********************************************************************** * Save one picture for each frame in current flic. ***********************************************************************/ { int i; int count; char nbuf[PATH_SIZE]; ErrCode err; int min, max; // Go load the appropriate pdr for outputting the pictures... if (Success > (err = set_up_for_output(name))) { return; } // Set up the loop control... count = GetFrameCount(); if ((min = get_num_name(name)) < 0) min = 1; max = min + count - 1; // Output the pictures... for (i = min; i <= max; ++i) { make_num_name(nbuf,name,i,count_digits(max)); // make up file name printf("Saving %s", nbuf); // Put up status line if (Success > (err = PicSave(nbuf, NULL))) { Qerror(err, "Couldn't save %s", nbuf); return; } NextFrame(); } unprintf(); // Get rid of status line } Boolean fexists(char *name) /*********************************************************************** * See whether a file exists. ***********************************************************************/ { FILE *f; if ((f = fopen(name, "rb")) != NULL) { fclose(f); return TRUE; } else return FALSE; } int count_files(char *base_name) /*********************************************************************** * Count up the number of files starting at base_name and * numbered sequentially. ***********************************************************************/ { char nbuf[PATH_SIZE]; int count = 0; int base = get_num_name(base_name); for (;;) { make_num_name(nbuf, base_name,base+count,0); if (!fexists(nbuf)) break; ++count; } return count; } void load_pics(char *base_name) /*********************************************************************** * Load up a bunch of consecutively numbered files into the flic. ***********************************************************************/ { int i; int count; int curframe; int thechoice; char nbuf[PATH_SIZE]; int base; int flicw, flich; int picw, pich, picdepth; ErrCode err; int temp; base = get_num_name(base_name); count = count_files(base_name); // Get the picture size info for the first pic. This ensures that the // file exists, and that a pdr can be found by the pdraccess routines to // process the pictures. if (Success > (err = PicGetSize(base_name, &picw, &pich, &picdepth))) { Qerror(err, "Cannot load %s", base_name); return; } // Tell the user how many pictures we found to be loaded, and ask for // the input option (replace/append/insert). If the replace option is // choosen, allow the user to change the size of the new flic, if the size // of the pictures differs from the current flic size. thechoice = Qchoice(load_choices, Array_els(load_choices), load_prompt, count); switch (thechoice) { case LOAD_REPLACE: if (0 != (i = GetChangeCount())) { if (!Qquestion(replace_changes_prompt, i)) return; } GetSize(&flicw, &flich); if (flicw != picw || flich != pich) { if (Qquestion(change_flic_size_prompt,flicw,flich,picw,pich)) { flicw = picw; flich = pich; } } ResizeReset(flicw, flich); SetFrameCount(count); break; case LOAD_APPEND: SetFrame(GetFrameCount()-1); // move to end of flic /* fall thru */ case LOAD_INSERT: InsertFrames(count); // insert enough frames for pics NextFrame(); // move to first of inserted frames break; default: return; // User selected Cancel or right-clicked } // If rgb/truecolor data was found in the picture, ask the user for the // rgb processing option via the pdracces preset dialog. The choosen // option will remain in effect throughout the load sequence. if (picdepth > 8) { if (Success > (err = PicRgbOptionsPreset(DO_DIALOG,0))) return; } curframe = 1+GetFrame(); // Load the pictures... for (i=0; i < count;) { make_num_name(nbuf, base_name, base+i, 0); printf("Loading %s into frame %d", nbuf, curframe); if (Success > (err = PicLoad(nbuf,NULL))) { Qerror(err, "Can't load %s (%d of %d)", nbuf, i+1, count); temp = count - i - 1; if (temp > 0) { if (!Qquestion("Continue loading other %d Pics?", temp)) return; } } if (++i < count) { // don't advance after last picture NextFrame(); // (makes multiple insert sequences ++curframe; // easier for the user) } } unprintf(); // all done, get rid of top status info line } void delete_files(char *base_name) /*********************************************************************** * Delete a bunch of consecutively numbered files. ***********************************************************************/ { char nbuf[PATH_SIZE]; int count; int i; int base; base = get_num_name(base_name); count = count_files(base_name); // make extra sure the user wants to do this... if (!Qquestion("Delete numbered files starting with %s ???", base_name)) return; if (!Qquestion("Are you sure you want to delete all %d" " files starting with:\n %s?", count, base_name)) return; // okay, go for it. for (i=0; i < count; ++i) { make_num_name(nbuf, base_name, base+i, 0); DosDelete(nbuf); } } Boolean do_one_set(char *base_name) /********************************************************************** * Put up main program menu and respond to choices. Return FALSE if * user selects Exit, TRUE after other commands. **********************************************************************/ { int choice; ErrCode err; char *what; choice = Qmenu(menu_choices, Array_els(menu_choices), menu_prompt); if (choice == MU_LOAD1) /* It's pretty easy to load one pic. */ { if (Qfile(".TGA;.TIF", "Load", base_name, base_name, FALSE, rgbname_prompt)) { if (Success > (err = PicLoad(base_name,NULL))) Qerror(err, "Can't load %s", base_name); } } else { // Figure out what to put on the file selector action button... switch (choice) { case MU_SAVE: what = "Save"; break; case MU_LOAD: what = "Load"; break; case MU_DELETE: what = "Delete"; break; default: return FALSE; // User has chosen Exit or right-clicked. } // Ask user for the base file name... if (!Qfile(".*", what, base_name, base_name, FALSE, basename_prompt)) return TRUE; // Quit this command, but not program. // Invoke the requested action... switch (choice) { case MU_SAVE: save_pics(base_name); break; case MU_LOAD: load_pics(base_name); break; case MU_DELETE: delete_files(base_name); break; } } return TRUE; } void main(void) /*********************************************************************** * Call menu routine above until Exit/Cancel. **********************************************************************/ { static char last_path[PATH_SIZE] = ""; GlobalVarGet("numpic_lastpath",last_path); while (do_one_set(last_path)) ; GlobalVarSet("numpic_lastpath",last_path); }