XV 3.10a super-patch by Dave Coffin 3/8/2003 Changes made by me: * Fix for Postscript save crashes * Changed "Delete" button to non-destructive "Reject" * Fixed Smooth24() routine * Support for all raw digital camera formats * Compatibility with Red Hat header files * Simulates Protan and Deutan colorblindness Changes made by others: * Support for PNG image format (plus patches by Greg Roelofs) * Compatibility with latest versions of libjpeg and libtiff --- xv-3.10a/Makefile Mon Jan 23 15:20:54 1995 +++ xv-3.10a/Makefile Fri Mar 7 20:25:47 2003 @@ -15,5 +15,5 @@ -CCOPTS = -O +CCOPTS = -O3 @@ -46,13 +46,22 @@ ### on your machine, *COMMENT OUT* the following lines ### JPEG = -DDOJPEG -JPEGDIR = jpeg -JPEGINC = -I$(JPEGDIR) -JPEGLIB = $(JPEGDIR)/libjpeg.a -$(JPEGDIR)/jconfig.h: - cd $(JPEGDIR) ; ./configure CC='$(CC)' -$(JPEGLIB): $(JPEGDIR)/jconfig.h - cd $(JPEGDIR) ; make + + +### +### if, for whatever reason, you're unable to get the PNG library to compile +### on your machine, *COMMENT OUT* the following lines +### +PNG = -DDOPNG +PNGLIB = -lpng + + +### +### if, for whatever reason, you're unable to get the PNG library to compile +### on your machine, *COMMENT OUT* the following lines +### +ZLIBDIR = /usr/local/src/zlib +ZLIBLIB = -lz ### @@ -60,11 +69,6 @@ ### on your machine, *COMMENT OUT* the following lines ### TIFF = -DDOTIFF -TIFFDIR = tiff -TIFFINC = -I$(TIFFDIR) -TIFFLIB = $(TIFFDIR)/libtiff.a -$(TIFFLIB): - ( cd $(TIFFDIR) ; make CC='$(CC)' ) ### @@ -102,7 +106,7 @@ ### for LINUX, uncomment the following line -#MCHN = -DLINUX +MCHN = -DLINUX # For SCO 1.1 (UNIX 3.2v2) machines, uncomment the following: @@ -184,11 +188,11 @@ -CFLAGS = $(CCOPTS) $(JPEG) $(JPEGINC) $(TIFF) $(TIFFINC) $(PDS) \ +CFLAGS = $(CCOPTS) $(JPEG) $(TIFF) $(PDS) \ $(NODIRENT) $(VPRINTF) $(TIMERS) $(UNIX) $(BSDTYPES) $(RAND) \ - $(DXWM) $(MCHN) + $(DXWM) $(MCHN) $(PNG) -LIBS = -lX11 $(JPEGLIB) $(TIFFLIB) -lm +LIBS = -L/usr/X11R6/lib -lX11 -ljpeg -ltiff -lpng -lz -lm OBJS = xv.o xvevent.o xvroot.o xvmisc.o xvimage.o xvcolor.o xvsmooth.o \ xv24to8.o xvgif.o xvpm.o xvinfo.o xvctrl.o xvscrl.o xvalg.o \ @@ -196,7 +200,7 @@ xvdial.o xvgraf.o xvsunras.o xvjpeg.o xvps.o xvpopup.o xvdflt.o \ xvtiff.o xvtiffwr.o xvpds.o xvrle.o xviris.o xvgrab.o vprintf.o \ xvbrowse.o xvtext.o xvpcx.o xviff.o xvtarga.o xvxpm.o xvcut.o \ - xvxwd.o xvfits.o + xvxwd.o xvfits.o xvpng.o xvcrw.o MISC = README INSTALL CHANGELOG IDEAS @@ -267,7 +271,7 @@ xvbrowse.o: bits/br_pcx bits/br_jfif bits/br_tiff bits/br_pds xvbrowse.o: bits/br_ps bits/br_iff bits/br_targa bits/br_xpm xvbrowse.o: bits/br_trash bits/fcurs bits/fccurs bits/fdcurs bits/fcursm -xvbrowse.o: bits/br_xwd +xvbrowse.o: bits/br_xwd bits/br_png xvbutt.o: bits/cboard50 bits/rb_frame bits/rb_frame1 bits/rb_top xvbutt.o: bits/rb_bot bits/rb_dtop bits/rb_dbot bits/rb_body --- xv-3.10a/bits/br_png Tue Jun 30 15:08:02 1998 +++ xv-3.10a/bits/br_png Thu Jun 13 17:32:08 1996 @@ -0,0 +1,28 @@ +#define br_png_width 48 +#define br_png_height 48 +static unsigned char br_png_bits[] = { + 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x81, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0xf8, 0x19, 0xc3, 0x07, 0x02, 0x20, 0x18, 0x3b, 0x63, 0x0c, 0x02, + 0x20, 0x18, 0x3b, 0x33, 0x00, 0x02, 0x20, 0x18, 0x5b, 0x33, 0x00, 0x02, + 0x20, 0xf8, 0x59, 0x33, 0x0f, 0x02, 0x20, 0x18, 0x98, 0x33, 0x0c, 0x02, + 0x20, 0x18, 0x98, 0x33, 0x0c, 0x02, 0x20, 0x18, 0x18, 0x63, 0x0c, 0x02, + 0x20, 0x18, 0x18, 0xc3, 0x0b, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0xff, 0xff, 0xff, 0x3f, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, + }; --- xv-3.10a/jpeg/jconfig.cfg Thu Dec 22 17:35:00 1994 +++ xv-3.10a/jpeg/jconfig.cfg Tue Jun 30 14:59:08 1998 @@ -42,3 +42,5 @@ #undef PROGRESS_REPORT #endif /* JPEG_CJPEG_DJPEG */ + +#define JDCT_DEFAULT JDCT_FLOAT --- xv-3.10a/xv.c Thu Jan 19 13:08:43 1995 +++ xv-3.10a/xv.c Thu Mar 6 22:24:28 2003 @@ -277,6 +277,10 @@ tiffW = (Window) NULL; tiffUp = 0; #endif +#ifdef HAVE_PNG + pngW = (Window) NULL; pngUp = 0; +#endif + imap = ctrlmap = gmap = browmap = cmtmap = 0; ch_offx = ch_offy = p_offx = p_offy = 0; @@ -782,6 +786,10 @@ XSetTransientForHint(theDisp, tiffW, dirW); #endif +#ifdef HAVE_PNG + CreatePNGW(); + XSetTransientForHint(theDisp, pngW, dirW); +#endif LoadFishCursors(); SetCursors(-1); @@ -2539,10 +2547,14 @@ FILE *fp; byte magicno[30]; /* first 30 bytes of file */ + char com[256]; int rv, n; if (!fname) return RFT_ERROR; /* shouldn't happen */ + snprintf (com, 256, "dcraw -i '%s' 2>/dev/null", fname); + if (system(com) == 0) return RFT_CRW; + fp = xv_fopen(fname, "r"); if (!fp) return RFT_ERROR; @@ -2611,6 +2623,11 @@ (magicno[0]=='I' && magicno[1]=='I')) rv = RFT_TIFF; #endif +#ifdef HAVE_PNG + else if (magicno[0]==0x89 && magicno[1]=='P' && + magicno[2]=='N' && magicno[3]=='G') rv = RFT_PNG; +#endif + #ifdef HAVE_PDS else if (strncmp((char *) magicno, "NJPL1I00", (size_t) 8)==0 || strncmp((char *) magicno+2,"NJPL1I", (size_t) 6)==0 || @@ -2651,6 +2668,7 @@ case RFT_GIF: rv = LoadGIF (fname, pinfo); break; case RFT_PM: rv = LoadPM (fname, pinfo); break; case RFT_PBM: rv = LoadPBM (fname, pinfo); break; + case RFT_CRW: rv = LoadCRW (fname, pinfo); break; case RFT_XBM: rv = LoadXBM (fname, pinfo); break; case RFT_SUNRAS: rv = LoadSunRas(fname, pinfo); break; case RFT_BMP: rv = LoadBMP (fname, pinfo); break; @@ -2671,6 +2689,10 @@ case RFT_TIFF: rv = LoadTIFF (fname, pinfo); break; #endif +#ifdef HAVE_PNG + case RFT_PNG: rv = LoadPNG (fname, pinfo); break; +#endif + #ifdef HAVE_PDS case RFT_PDSVICAR: rv = LoadPDS (fname, pinfo); break; #endif @@ -3596,49 +3618,40 @@ /***********************************/ int DeleteCmd() { - /* 'delete' button was pressed. Pop up a dialog box to determine - what should be deleted, then do it. + /* 'Reject' button was pressed. Move the file to ./rejected + without question. returns '1' if THE CURRENTLY VIEWED entry was deleted from the list, in which case the 'selected' filename on the ctrl list is now different, and should be auto-loaded, or something */ - static char *bnames[] = { "\004Disk File", "\nList Entry", "\033Cancel" }; - char str[512]; - int del, i, delnum, rv; + char str[512], *name, *basename; + int i, delnum, rv; /* failsafe */ delnum = nList.selected; if (delnum < 0 || delnum >= numnames) return 0; - sprintf(str,"Delete '%s'?\n\n%s%s", - namelist[delnum], - "'List Entry' deletes selection from list.\n", - "'Disk File' deletes file associated with selection."); - - del = PopUp(str, bnames, 3); - - if (del == 2) return 0; /* cancel */ - - if (del == 0) { /* 'Disk File' */ - char *name; - if (namelist[delnum][0] != '/') { /* prepend 'initdir' */ - name = (char *) malloc(strlen(namelist[delnum]) + strlen(initdir) + 2); - if (!name) FatalError("malloc in DeleteCmd failed\n"); - sprintf(name,"%s/%s", initdir, namelist[delnum]); - } - else name = namelist[delnum]; - - i = unlink(name); - if (i) { - sprintf(str,"Can't delete file '%s'\n\n %s.", name, ERRSTR(errno)); - ErrPopUp(str, "\nPity"); - if (name != namelist[delnum]) free(name); - return 0; - } - - XVDeletedFile(name); + if (namelist[delnum][0] != '/') { /* prepend 'initdir' */ + name = (char *) malloc(strlen(namelist[delnum]) + strlen(initdir) + 2); + if (!name) FatalError("malloc in DeleteCmd failed\n"); + sprintf(name,"%s/%s", initdir, namelist[delnum]); + } + else name = namelist[delnum]; + + mkdir("rejected",0777); + if ( (basename=strrchr(name,'/')+1) == (char *)1 ) + basename=name; + sprintf(str,"rejected/%s",basename); + i = rename(name,str); + if (i) { + sprintf(str,"Can't reject file '%s'\n\n %s.", name, ERRSTR(errno)); + ErrPopUp(str, "\nPity"); if (name != namelist[delnum]) free(name); + return 0; } + + XVDeletedFile(name); + if (name != namelist[delnum]) free(name); deleteFromList(delnum); --- xv-3.10a/xv.h Mon Jan 23 15:22:23 1995 +++ xv-3.10a/xv.h Tue Jun 30 14:59:54 1998 @@ -8,8 +8,8 @@ #include "config.h" -#define REVDATE "Version 3.10a Rev: 12/29/94" -#define VERSTR "3.10a" +#define REVDATE "Version 3.10a Rev: 12/29/94 (PNG patch 1.2)" +#define VERSTR "3.10a(PNG+CRW)" /* * uncomment the following, and modify for your site, but only if you've @@ -115,9 +115,6 @@ #ifndef VMS # include extern int errno; /* SHOULD be in errno.h, but often isn't */ -# ifndef __NetBSD__ - extern char *sys_errlist[]; /* this too... */ -# endif #endif @@ -327,6 +324,10 @@ #define HAVE_TIFF #endif +#ifdef DOPNG +#define HAVE_PNG +#endif + #ifdef DOPDS #define HAVE_PDS #endif @@ -458,24 +459,31 @@ #define F_TIFINC 0 #endif +#ifdef HAVE_PNG +#define F_PNGINC 1 +#else +#define F_PNGINC 0 +#endif + #define F_GIF 0 #define F_JPEG ( 0 + F_JPGINC) #define F_TIFF ( 0 + F_JPGINC + F_TIFINC) -#define F_PS ( 1 + F_JPGINC + F_TIFINC) -#define F_PBMRAW ( 2 + F_JPGINC + F_TIFINC) -#define F_PBMASCII ( 3 + F_JPGINC + F_TIFINC) -#define F_XBM ( 4 + F_JPGINC + F_TIFINC) -#define F_XPM ( 5 + F_JPGINC + F_TIFINC) -#define F_BMP ( 6 + F_JPGINC + F_TIFINC) -#define F_SUNRAS ( 7 + F_JPGINC + F_TIFINC) -#define F_IRIS ( 8 + F_JPGINC + F_TIFINC) -#define F_TARGA ( 9 + F_JPGINC + F_TIFINC) -#define F_FITS (10 + F_JPGINC + F_TIFINC) -#define F_PM (11 + F_JPGINC + F_TIFINC) -#define F_DELIM1 (12 + F_JPGINC + F_TIFINC) /* ----- */ -#define F_FILELIST (13 + F_JPGINC + F_TIFINC) -#define F_MAXFMTS (14 + F_JPGINC + F_TIFINC) /* 15, normally */ +#define F_PNG ( 0 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_PS ( 1 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_PBMRAW ( 2 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_PBMASCII ( 3 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_XBM ( 4 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_XPM ( 5 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_BMP ( 6 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_SUNRAS ( 7 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_IRIS ( 8 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_TARGA ( 9 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_FITS (10 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_PM (11 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_DELIM1 (12 + F_JPGINC + F_TIFINC + F_PNGINC) /* ----- */ +#define F_FILELIST (13 + F_JPGINC + F_TIFINC + F_PNGINC) +#define F_MAXFMTS (14 + F_JPGINC + F_TIFINC + F_PNGINC) /* 17, normally */ @@ -505,6 +513,8 @@ #define RFT_XPM 17 #define RFT_XWD 18 #define RFT_FITS 19 +#define RFT_PNG 20 +#define RFT_CRW 21 /* definitions for page up/down, arrow up/down list control */ #define LS_PAGEUP 0 @@ -645,7 +655,9 @@ #define ALG_PIXEL 10 #define ALG_SPREAD 11 #define ALG_MEDIAN 12 -#define ALG_MAX 13 +#define ALG_PROTAN 13 +#define ALG_DEUTAN 14 +#define ALG_MAX 15 /* indicies into sizeMB */ @@ -765,9 +777,10 @@ typedef struct { Window win; /* window ID */ int x,y,w,h; /* window coords in parent */ int active; /* true if can do anything*/ - int min,max; /* min/max values 'pos' can take */ - int val; /* 'value' of dial */ - int page; /* amt val change on pageup/pagedown */ + double min,max; /* min/max values 'pos' can take */ + double val; /* 'value' of dial */ + double inc; /* amt val change on up/down */ + double page; /* amt val change on pageup/pagedown */ char *title; /* title for this guage */ char *units; /* string appended to value */ u_long fg,bg,hi,lo; /* colors */ @@ -1154,6 +1167,13 @@ #endif +#ifdef HAVE_PNG +/* stuff used for 'png' box */ +WHERE Window pngW; +WHERE int pngUp; /* is pngW mapped, or what? */ +#endif + + #undef WHERE @@ -1465,12 +1485,12 @@ /*************************** XVDIAL.C ***************************/ -void DCreate PARM((DIAL *, Window, int, int, int, int, int, - int, int, int, u_long, u_long, u_long, - u_long, char *, char *)); +void DCreate PARM((DIAL *, Window, int, int, int, int, double, + double, double, double, double, u_long, + u_long, u_long, u_long, char *, char *)); -void DSetRange PARM((DIAL *, int, int, int, int)); -void DSetVal PARM((DIAL *, int)); +void DSetRange PARM((DIAL *, double,double,double,double,double)); +void DSetVal PARM((DIAL *, double)); void DSetActive PARM((DIAL *, int)); void DRedraw PARM((DIAL *)); int DTrack PARM((DIAL *, int, int)); @@ -1552,6 +1572,9 @@ int WritePBM PARM((FILE *, byte *, int, int, int, byte *, byte *, byte *, int, int, int, char *)); +/**************************** XVCRW.C ***************************/ +int LoadCRW PARM((char *, PICINFO *)); + /**************************** XVXBM.C ***************************/ int LoadXBM PARM((char *, PICINFO *)); int WriteXBM PARM((FILE *, byte *, int, int, byte *, byte *, @@ -1612,6 +1635,13 @@ void TIFFDialog PARM((int)); int TIFFCheckEvent PARM((XEvent *)); void TIFFSaveParams PARM((char *, int)); + +/**************************** XVPNG.C ***************************/ +int LoadPNG PARM((char *, PICINFO *)); +void CreatePNGW PARM((void)); +void PNGDialog PARM((int)); +int PNGCheckEvent PARM((XEvent *)); +void PNGSaveParams PARM((char *, int)); /**************************** XVPDS.C ***************************/ int LoadPDS PARM((char *, PICINFO *)); --- xv-3.10a/xvalg.c Thu Dec 22 17:34:47 1994 +++ xv-3.10a/xvalg.c Mon May 21 00:06:38 2001 @@ -26,6 +26,8 @@ static void Pixelize PARM((void)); static void Spread PARM((void)); static void MedianFilter PARM((void)); +static void ProtanFilter PARM((void)); +static void DeutanFilter PARM((void)); static void saveOrigPic PARM((void)); static void doBlurConvolv PARM((byte *,int,int,byte *, int,int,int,int, int)); @@ -119,6 +121,8 @@ case ALG_PIXEL: Pixelize(); break; case ALG_SPREAD: Spread(); break; case ALG_MEDIAN: MedianFilter(); break; + case ALG_PROTAN: ProtanFilter(); break; + case ALG_DEUTAN: DeutanFilter(); break; } algMB.dim[ALG_NONE] = (origPic == (byte *) NULL); @@ -548,6 +552,64 @@ xvbcopy((char *) pic24, (char *) tmpPic, (size_t) (pWIDE*pHIGH*3)); doMedianFilter(pic24, pWIDE,pHIGH, tmpPic, sx,sy,sw,sh, n); + + end24bitAlg(pic24, tmpPic); +} + + + + +/************************/ +static void ProtanFilter() +{ + byte *pic24, *p24, *tmpPic; + int i, j, sx,sy,sw,sh; + + WaitCursor(); + + if (HaveSelection()) GetSelRCoords(&sx,&sy,&sw,&sh); + else { sx = 0; sy = 0; sw = pWIDE; sh = pHIGH; } + CropRect2Rect(&sx,&sy,&sw,&sh, 0,0,pWIDE,pHIGH); + + SetISTR(ISTR_INFO, "Copying green channel to red..."); + + if (start24bitAlg(&pic24, &tmpPic)) return; + xvbcopy((char *) pic24, (char *) tmpPic, (size_t) (pWIDE*pHIGH*3)); + + for (i=sy; iwin,br_xpm_bits, br_xpm_width, br_xpm_height); bfIcons[BF_XWD] =MakePix1(br->win,br_xwd_bits, br_xwd_width, br_xwd_height); bfIcons[BF_FITS]=MakePix1(br->win,br_fits_bits,br_fits_width,br_fits_height); + bfIcons[BF_PNG]=MakePix1(br->win,br_png_bits,br_png_width,br_png_height); /* check that they all got built */ @@ -3020,6 +3023,7 @@ case RFT_XPM: bf->ftype = BF_XPM; break; case RFT_XWD: bf->ftype = BF_XWD; break; case RFT_FITS: bf->ftype = BF_FITS; break; + case RFT_PNG: bf->ftype = BF_PNG; break; } } } @@ -3567,6 +3571,7 @@ case RFT_XPM: strcat(str,"XPM file"); break; case RFT_XWD: strcat(str,"XWD file"); break; case RFT_FITS: strcat(str,"FITS file"); break; + case RFT_PNG: strcat(str,"PNG file"); break; default: strcat(str,"file of unknown type"); break; } --- xv-3.10a/xvcrw.c Wed Dec 31 19:00:00 1969 +++ xv-3.10a/xvcrw.c Fri Mar 7 21:02:05 2003 @@ -0,0 +1,40 @@ +/* + * xvcrw.c - load routine for raw digital camera files + * + * by Dave Coffin (dcoffin@shore.net) 3/6/2003 + * "dcraw" 4.51 or later must be installed for this to work. + * + * LoadCRW(fname, pinfo) - loads the file + */ + +#include "copyright.h" + +#include "xv.h" + +int LoadCRW (char *fname, PICINFO *pinfo) +{ + char com[256]; + FILE *pfp; + + snprintf (com, 256, "dcraw -c '%s'", fname); + pfp = popen (com, "r"); + if (!pfp) { + SetISTR(ISTR_WARNING,"%s: %s", fname, strerror(errno)); + return 0; + } + if (fscanf (pfp, "P6 %d %d 255%*c", &pinfo->w, &pinfo->h) != 2) { + SetISTR(ISTR_WARNING,"%s: %s", fname, "Cannot decode!!"); + return 0; + } + pinfo->pic = (byte *) malloc (pinfo->w * pinfo->h * 3); + if (!pinfo->pic) FatalError("couldn't malloc 'pic'"); + fread (pinfo->pic, pinfo->w * 3, pinfo->h, pfp); + pclose (pfp); + + pinfo->type = PIC24; + pinfo->colType = F_FULLCOLOR; + pinfo->comment = (char *) NULL; + sprintf(pinfo->fullInfo, "Raw digital photo"); + sprintf(pinfo->shrtInfo, "Raw digital photo"); + return 1; +} --- xv-3.10a/xvctrl.c Thu Dec 22 17:34:41 1994 +++ xv-3.10a/xvctrl.c Sun May 20 23:59:46 2001 @@ -124,7 +124,9 @@ "Clear Rotate...\t\244T", "Pixelize...\t\244p", "Spread...\t\244S", - "DeSpeckle...\t\244k"}; + "DeSpeckle...\t\244k", + "Protan", + "Deutan" }; static char *sizeMList[] = { "Normal\tn", "Max Size\tm", @@ -264,7 +266,7 @@ BTCreate(&but[BLOAD], ctrlW, R_BX0, R_BY2, R_BW1, SBUTTH, "Load", BCLS); BTCreate(&but[BSAVE], ctrlW, R_BX0, R_BY3, R_BW1, SBUTTH, "Save", BCLS); BTCreate(&but[BPRINT], ctrlW, R_BX0, R_BY4, R_BW1, SBUTTH, "Print", BCLS); - BTCreate(&but[BDELETE], ctrlW, R_BX0, R_BY5, R_BW1, SBUTTH, "Delete", BCLS); + BTCreate(&but[BDELETE], ctrlW, R_BX0, R_BY5, R_BW1, SBUTTH, "Reject", BCLS); /* expressions for positioning bottom buttons (6x2 array) */ --- xv-3.10a/xvdial.c Tue Jan 3 16:20:31 1995 +++ xv-3.10a/xvdial.c Tue Jun 30 14:45:05 1998 @@ -41,20 +41,21 @@ /* local functions */ -static int whereInDial PARM((DIAL *, int, int)); -static void drawArrow PARM((DIAL *)); -static void drawValStr PARM((DIAL *)); -static void drawButt PARM((DIAL *, int, int)); -static int computeDialVal PARM((DIAL *, int, int)); -static void dimDial PARM((DIAL *)); +static int whereInDial PARM((DIAL *, int, int)); +static void drawArrow PARM((DIAL *)); +static void drawValStr PARM((DIAL *)); +static void drawButt PARM((DIAL *, int, int)); +static double computeDialVal PARM((DIAL *, int, int)); +static void dimDial PARM((DIAL *)); /***************************************************/ -void DCreate(dp, parent, x, y, w, h, minv, maxv, curv, page, +void DCreate(dp, parent, x, y, w, h, minv, maxv, curv, inc, page, fg, bg, hi, lo, title, units) DIAL *dp; Window parent; -int x,y,w,h,minv,maxv,curv,page; +int x,y,w,h; +double minv,maxv,curv,inc,page; unsigned long fg,bg,hi,lo; char *title, *units; { @@ -98,18 +99,18 @@ 1,fg,bg); if (!dp->win) FatalError("can't create dial window"); - DSetRange(dp, minv, maxv, curv, page); + DSetRange(dp, minv, maxv, curv, inc, page); XSelectInput(theDisp, dp->win, ExposureMask | ButtonPressMask); } /***************************************************/ -void DSetRange(dp, minv, maxv, curv, page) -DIAL *dp; -int minv, maxv, curv, page; +void DSetRange(dp, minv, maxv, curv, inc, page) +DIAL *dp; +double minv, maxv, curv, inc, page; { if (maxvmin = minv; dp->max = maxv; dp->page = page; + dp->min = minv; dp->max = maxv; dp->inc = inc; dp->page = page; dp->active = (minv < maxv); DSetVal(dp, curv); @@ -118,8 +119,8 @@ /***************************************************/ void DSetVal(dp, curv) -DIAL *dp; -int curv; +DIAL *dp; +double curv; { RANGE(curv, dp->min, dp->max); /* make sure curv is in-range */ @@ -129,7 +130,7 @@ XSetForeground(theDisp, theGC, dp->bg); drawArrow(dp); - dp->val = curv; + dp->val = (double)((int)(curv / dp->inc + (curv > 0 ? 0.5 : -0.5))) * dp->inc; /* draw new arrow and string */ XSetForeground(theDisp, theGC, dp->fg); @@ -202,7 +203,8 @@ int mx,my; { Window rW,cW; - int rx,ry, x,y, ipos, pos, lit, i, origval; + int rx, ry, x, y, ipos, pos, lit; + double origval; unsigned int mask; lit = 0; @@ -224,9 +226,9 @@ if (ipos != INDIAL) { drawButt(dp, ipos, 1); switch (ipos) { - case INCW1: if (dp->val < dp->max) DSetVal(dp, dp->val+1); break; + case INCW1: if (dp->val < dp->max) DSetVal(dp, dp->val+dp->inc); break; case INCW2: if (dp->val < dp->max) DSetVal(dp, dp->val+dp->page); break; - case INCCW1: if (dp->val > dp->min) DSetVal(dp, dp->val-1); break; + case INCCW1: if (dp->val > dp->min) DSetVal(dp, dp->val-dp->inc); break; case INCCW2: if (dp->val > dp->min) DSetVal(dp, dp->val-dp->page); break; } if (dp->drawobj != NULL) (dp->drawobj)(); @@ -235,8 +237,9 @@ } else { - i = computeDialVal(dp, mx, my); - DSetVal(dp, i); + double v; + v = computeDialVal(dp, mx, my); + DSetVal(dp, v); if (dp->drawobj != NULL) (dp->drawobj)(); } @@ -246,11 +249,11 @@ if (!(mask & Button1Mask)) break; /* button released */ if (ipos == INDIAL) { - int j; - i = computeDialVal(dp, x, y); - j = dp->val; - DSetVal(dp, i); - if (j != dp->val) { + double v, w; + v = computeDialVal(dp, x, y); + w = dp->val; + DSetVal(dp, v); + if (w != dp->val) { /* track whatever dial controls */ if (dp->drawobj != NULL) (dp->drawobj)(); } @@ -266,11 +269,11 @@ if (lit) { switch (ipos) { - case INCW1: if (dp->val < dp->max) DSetVal(dp, dp->val+1); + case INCW1: if (dp->val < dp->max) DSetVal(dp, dp->val+dp->inc); break; case INCW2: if (dp->val < dp->max) DSetVal(dp, dp->val+dp->page); break; - case INCCW1: if (dp->val > dp->min) DSetVal(dp, dp->val-1); + case INCCW1: if (dp->val > dp->min) DSetVal(dp, dp->val-dp->inc); break; case INCCW2: if (dp->val > dp->min) DSetVal(dp, dp->val-dp->page); break; @@ -320,19 +323,20 @@ static void drawArrow(dp) DIAL *dp; { - int i, rad, cx, cy; + int rad, cx, cy; + double v; XPoint arrow[4]; rad = dp->rad; cx = dp->cx; cy = dp->cy; /* map pos (range minv..maxv) into degrees (range 240..-60) */ - i = 240 + (-300 * (dp->val - dp->min)) / (dp->max - dp->min); - arrow[0].x = cx + (int) ((double) rad * .80 * cos(i * DEG2RAD)); - arrow[0].y = cy - (int) ((double) rad * .80 * sin(i * DEG2RAD)); - arrow[1].x = cx + (int) ((double) rad * .33 * cos((i+160) * DEG2RAD)); - arrow[1].y = cy - (int) ((double) rad * .33 * sin((i+160) * DEG2RAD)); - arrow[2].x = cx + (int) ((double) rad * .33 * cos((i-160) * DEG2RAD)); - arrow[2].y = cy - (int) ((double) rad * .33 * sin((i-160) * DEG2RAD)); + v = 240 + (-300 * (dp->val - dp->min)) / (dp->max - dp->min); + arrow[0].x = cx + (int) ((double) rad * .80 * cos(v * DEG2RAD)); + arrow[0].y = cy - (int) ((double) rad * .80 * sin(v * DEG2RAD)); + arrow[1].x = cx + (int) ((double) rad * .33 * cos((v+160) * DEG2RAD)); + arrow[1].y = cy - (int) ((double) rad * .33 * sin((v+160) * DEG2RAD)); + arrow[2].x = cx + (int) ((double) rad * .33 * cos((v-160) * DEG2RAD)); + arrow[2].y = cy - (int) ((double) rad * .33 * sin((v-160) * DEG2RAD)); arrow[3].x = arrow[0].x; arrow[3].y = arrow[0].y; XDrawLines(theDisp, dp->win, theGC, arrow, 4, CoordModeOrigin); @@ -343,23 +347,37 @@ static void drawValStr(dp) DIAL *dp; { - int i, x1, x2; + int tot, i, x1, x2; char foo[60], foo1[60]; /* compute longest string necessary so we can right-align this thing */ - sprintf(foo,"%d",dp->min); x1 = strlen(foo); - sprintf(foo,"%d",dp->max); x2 = strlen(foo); + sprintf(foo,"%d",(int)dp->min); x1 = strlen(foo); + sprintf(foo,"%d",(int)dp->max); x2 = strlen(foo); if (dp->min < 0 && dp->max > 0) x2++; /* put '+' at beginning */ i = x1; if (x2>x1) i = x2; if (dp->units) i += strlen(dp->units); - if (dp->min < 0 && dp->max > 0) sprintf(foo,"%+d", dp->val); - else sprintf(foo,"%d", dp->val); + sprintf(foo,"%g",dp->inc); /* space for decimal values */ + tot = i + strlen(foo) - 1; /* Take away the 0 from the beginning */ + + if (dp->min < 0.0 && dp->max > 0.0) sprintf(foo,"%+g", dp->val); + else sprintf(foo,"%g", dp->val); + + if (dp->inc < 1.0) + { + int j; + + if (dp->val == (double)((int)dp->val)) + strcat(foo,"."); + + for (j = strlen(foo); j < tot; j++) + strcat(foo,"0"); + } if (dp->units) strcat(foo,dp->units); foo1[0] = '\0'; if (strlen(foo) < (size_t) i) { - for (i = i - strlen(foo); i>0; i--) strcat(foo1," "); + for (i-=strlen(foo);i>0;i--) strcat(foo1," "); } strcat(foo1, foo); @@ -411,12 +429,13 @@ /***************************************************/ -static int computeDialVal(dp, x, y) +static double computeDialVal(dp, x, y) DIAL *dp; int x, y; { - int dx, dy, val; - double angle; + int dx, dy; + + double angle, val; /* compute dx, dy (distance from cx, cy). Note: +dy is *up* */ dx = x - dp->cx; dy = dp->cy - y; @@ -436,8 +455,10 @@ if (angle > 270.0) angle -= 360.0; if (angle < -90.0) angle += 360.0; - val = (int) ((dp->max - dp->min) * (240.0 - angle) / 300.0) + dp->min; + val = ((dp->max - dp->min) * (240.0 - angle) / 300.0) + dp->min; + /* round value to be an even multiple of dp->inc */ + val = (double)((int)(val / dp->inc + 0.5)) * dp->inc; return val; } --- xv-3.10a/xvdir.c Tue Jan 3 16:21:39 1995 +++ xv-3.10a/xvdir.c Tue Jun 30 14:45:05 1998 @@ -62,6 +62,9 @@ #ifdef HAVE_TIFF "TIFF", #endif +#ifdef HAVE_PNG + "PNG", +#endif "PostScript", "PBM/PGM/PPM (raw)", "PBM/PGM/PPM (ascii)", @@ -1115,6 +1118,15 @@ } #endif +#ifdef HAVE_PNG + else if (fmt == F_PNG) { /* PNG */ + PNGSaveParams(fullname, col); + PNGDialog(1); /* open PNG Dialog box */ + dbut[S_BOK].lit = 0; BTRedraw(&dbut[S_BOK]); + return 0; /* always 'succeeds' */ + } +#endif + @@ -1168,7 +1180,8 @@ case F_XPM: rv = WriteXPM (fp, thepic, ptype, w, h, rp, gp, bp, nc, col, - fullname, picComments); + fullname, picComments); + break; case F_FITS: rv = WriteFITS (fp, thepic, ptype, w, h, rp, gp, bp, nc, col, picComments); @@ -1380,14 +1393,21 @@ (strcmp(lowsuf,"eps" )==0) || (strcmp(lowsuf,"rgb" )==0) || (strcmp(lowsuf,"tga" )==0) || - (strcmp(lowsuf,"xpm" )==0) || (strcmp(lowsuf,"fits")==0) || (strcmp(lowsuf,"fts" )==0) || +#ifdef HAVE_JPEG (strcmp(lowsuf,"jpg" )==0) || (strcmp(lowsuf,"jpeg")==0) || (strcmp(lowsuf,"jfif")==0) || +#endif +#ifdef HAVE_TIFF (strcmp(lowsuf,"tif" )==0) || - (strcmp(lowsuf,"tiff")==0)) { + (strcmp(lowsuf,"tiff")==0) || +#endif +#ifdef HAVE_PNG + (strcmp(lowsuf,"png" )==0) || +#endif + (strcmp(lowsuf,"xpm" )==0)) { /* found one. set lowsuf = to the new suffix, and tack on to filename */ @@ -1422,6 +1442,10 @@ #ifdef HAVE_TIFF case F_TIFF: strcpy(lowsuf,"tif"); break; +#endif + +#ifdef HAVE_PNG + case F_PNG: strcpy(lowsuf,"png"); break; #endif } --- xv-3.10a/xvevent.c Mon Jan 23 18:20:24 1995 +++ xv-3.10a/xvevent.c Tue Jun 30 14:45:05 1998 @@ -154,7 +154,7 @@ int *donep; { static int wasInfoUp=0, wasCtrlUp=0, wasDirUp=0, wasGamUp=0, wasPsUp=0; - static int wasJpegUp=0, wasTiffUp=0; + static int wasJpegUp=0, wasTiffUp=0, wasPngUp=0; static int mainWKludge=0; /* force first mainW expose after a mainW config to redraw all of mainW */ @@ -233,6 +233,10 @@ if (TIFFCheckEvent(event)) break; /* event has been processed */ #endif +#ifdef HAVE_PNG + if (PNGCheckEvent (event)) break; /* event has been processed */ +#endif + if (GamCheckEvent (event)) break; /* event has been processed */ if (BrowseCheckEvent (event, &retval, &done)) break; /* event eaten */ if (TextCheckEvent (event, &retval, &done)) break; /* event eaten */ @@ -359,6 +363,10 @@ else if (client_event->window == tiffW) TIFFDialog(0); #endif +#ifdef HAVE_PNG + else if (client_event->window == pngW) PNGDialog(0); +#endif + else if (client_event->window == mainW) Quit(0); } } @@ -538,6 +546,10 @@ #ifdef HAVE_TIFF if (wasTiffUp) { TIFFDialog(wasTiffUp); wasTiffUp=0; } #endif + +#ifdef HAVE_PNG + if (wasPngUp) { PNGDialog(wasJpegUp); wasPngUp=0; } +#endif } } } @@ -576,6 +588,10 @@ #ifdef HAVE_TIFF if (tiffUp) { wasTiffUp = tiffUp; TIFFDialog(0); } #endif + +#ifdef HAVE_PNG + if (pngUp) { wasPngUp = pngUp; PNGDialog(0); } +#endif } } } @@ -1147,6 +1163,10 @@ if (TIFFCheckEvent(event)) break; #endif +#ifdef HAVE_PNG + if (PNGCheckEvent (event)) break; +#endif + if (GamCheckEvent (event)) break; if (BrowseCheckEvent (event, &retval, &done)) break; if (TextCheckEvent (event, &retval, &done)) break; @@ -1366,6 +1386,10 @@ if (TIFFCheckEvent(event)) break; #endif +#ifdef HAVE_PNG + if (PNGCheckEvent (event)) break; +#endif + if (GamCheckEvent (event)) break; if (BrowseCheckEvent (event, &retval, &done)) break; if (TextCheckEvent (event, &retval, &done)) break; @@ -2370,6 +2394,10 @@ #ifdef HAVE_TIFF if (tiffUp) TIFFDialog(0); /* close tiff window */ +#endif + +#ifdef HAVE_PNG + if (pngUp) PNGDialog(0); /* close png window */ #endif ClosePopUp(); --- xv-3.10a/xvgam.c Fri Jan 13 14:51:14 1995 +++ xv-3.10a/xvgam.c Tue Jun 30 14:45:05 1998 @@ -265,11 +265,11 @@ BTCreate(&gbut[G_BRNDCOL], cmapF, 5 + 66 + 67 + 2, 189, 66, BUTTH, "Random", infofg, infobg, hicol, locol); - DCreate(&rhDial, cmapF, 5, 215, 66, 100, 0,360,180, 5, + DCreate(&rhDial, cmapF, 5, 215, 66, 100, 0.0, 360.0, 180.0, 1.0, 5.0, infofg, infobg, hicol, locol, "Hue", NULL); - DCreate(&gsDial, cmapF, 72, 215, 66, 100, 0,360,180, 5, + DCreate(&gsDial, cmapF, 72, 215, 66, 100, 0.0, 360.0, 180.0, 1.0, 5.0, infofg, infobg, hicol, locol, "Sat.", NULL); - DCreate(&bvDial, cmapF, 139, 215, 66, 100, 0,360,180, 5, + DCreate(&bvDial, cmapF, 139, 215, 66, 100, 0.0, 360.0, 180.0, 1.0, 5.0, infofg, infobg, hicol, locol, "Value", NULL); rhDial.drawobj = gsDial.drawobj = bvDial.drawobj = dragEditColor; @@ -359,7 +359,7 @@ srcHD.drawobj = dstHD.drawobj = whtHD.drawobj = dragHueDial; - DCreate(&satDial, hsvF, 100, 199, 100, 121, -100, 100, 0, 5, + DCreate(&satDial, hsvF, 100, 199, 100, 121, -100.0, 100.0, 0.0, 1.0, 5.0, infofg, infobg,hicol,locol, "Saturation", "%"); hueRB = RBCreate(NULL, hsvF, 7, 153, "1", @@ -722,7 +722,7 @@ if (whtHD.enabCB.val && whtHD.satval) hsvnonlinear++; - if (satDial.val != 0) hsvnonlinear++; + if (satDial.val != 0.0) hsvnonlinear++; /* check intensity graf */ for (i=0; i<256 && intGraf.func[i]==i; i++); @@ -1291,14 +1291,14 @@ rgb2hsv(rcmap[editColor], gcmap[editColor], bcmap[editColor], &h, &s, &v); if (h<0) h = 0; - DSetVal(&rhDial, (int) h); - DSetVal(&gsDial, (int) (s*100)); - DSetVal(&bvDial, (int) (v*100)); + DSetVal(&rhDial, h); + DSetVal(&gsDial, s*100); + DSetVal(&bvDial, v*100); } else { - DSetVal(&rhDial, rcmap[editColor]); - DSetVal(&gsDial, gcmap[editColor]); - DSetVal(&bvDial, bcmap[editColor]); + DSetVal(&rhDial, (double)rcmap[editColor]); + DSetVal(&gsDial, (double)gcmap[editColor]); + DSetVal(&bvDial, (double)bcmap[editColor]); } } @@ -1310,16 +1310,15 @@ if (hsvmode) { int rv, gv, bv; - hsv2rgb((double) rhDial.val, ((double) gsDial.val) / 100.0, - ((double) bvDial.val) / 100.0, &rv, &gv, &bv); + hsv2rgb(rhDial.val, gsDial.val / 100.0, bvDial.val / 100.0, &rv, &gv, &bv); rcmap[editColor] = rv; gcmap[editColor] = gv; bcmap[editColor] = bv; } else { - rcmap[editColor] = rhDial.val; - gcmap[editColor] = gsDial.val; - bcmap[editColor] = bvDial.val; + rcmap[editColor] = (int)rhDial.val; + gcmap[editColor] = (int)gsDial.val; + bcmap[editColor] = (int)bvDial.val; } } @@ -1561,9 +1560,9 @@ gsDial.title = "Green"; bvDial.title = "Blue"; - DSetRange(&rhDial, 0, 255, rcmap[editColor], 16); - DSetRange(&gsDial, 0, 255, gcmap[editColor], 16); - DSetRange(&bvDial, 0, 255, bcmap[editColor], 16); + DSetRange(&rhDial, 0.0, 255.0, (double)rcmap[editColor], 1.0, 16.0); + DSetRange(&gsDial, 0.0, 255.0, (double)gcmap[editColor], 1.0, 16.0); + DSetRange(&bvDial, 0.0, 255.0, (double)bcmap[editColor], 1.0, 16.0); XClearWindow(theDisp, rhDial.win); DRedraw(&rhDial); XClearWindow(theDisp, gsDial.win); DRedraw(&gsDial); @@ -1581,9 +1580,9 @@ &h, &s, &v); if (h<0.0) h = 0.0; - DSetRange(&rhDial, 0, 360, (int) h, 5); - DSetRange(&gsDial, 0, 100, (int) (s*100), 5); - DSetRange(&bvDial, 0, 100, (int) (v*100), 5); + DSetRange(&rhDial, 0.0, 360.0, h, 1.0, 5.0); + DSetRange(&gsDial, 0.0, 100.0, s*100, 1.0, 5.0); + DSetRange(&bvDial, 0.0, 100.0, v*100, 1.0, 5.0); XClearWindow(theDisp, rhDial.win); DRedraw(&rhDial); XClearWindow(theDisp, gsDial.win); DRedraw(&gsDial); @@ -1891,7 +1890,7 @@ } /* apply satDial value to s */ - s = s + ((double) satDial.val) / 100.0; + s = s + satDial.val / 100.0; if (s<0.0) s = 0.0; if (s>1.0) s = 1.0; @@ -2007,7 +2006,7 @@ gs->hueRBnum = RBWhich(hueRB); - gs->satval = satDial.val; + gs->satval = (int)satDial.val; GetGrafState(&intGraf,&gs->istate); GetGrafState(&rGraf, &gs->rstate); GetGrafState(&gGraf, &gs->gstate); @@ -2064,8 +2063,8 @@ changed++; } - if (gs->satval != satDial.val) { - DSetVal(&satDial,gs->satval); + if (gs->satval != (int)satDial.val) { + DSetVal(&satDial,(double)gs->satval); changed++; } @@ -3200,7 +3199,7 @@ if (whtHD.enabCB.val && whtHD.satval) hsvmod++; - if (satDial.val != 0) hsvmod++; + if (satDial.val != 0.0) hsvmod++; /* check intensity graf */ for (i=0; i<256; i++) { @@ -3284,7 +3283,7 @@ } /* apply satDial value to s */ - s = s + satDial.val; + s = s + (int)satDial.val; if (s< 0) s = 0; if (s>100) s = 100; --- xv-3.10a/xvjpeg.c Thu Jan 5 03:17:13 1995 +++ xv-3.10a/xvjpeg.c Tue Jun 30 15:12:39 1998 @@ -51,11 +51,11 @@ static void clickJD PARM((int, int)); static void doCmd PARM((int)); static void writeJPEG PARM((void)); -METHODDEF void xv_error_exit PARM((j_common_ptr)); -METHODDEF void xv_error_output PARM((j_common_ptr)); -METHODDEF void xv_prog_meter PARM((j_common_ptr)); +METHODDEF(void) xv_error_exit PARM((j_common_ptr)); +METHODDEF(void) xv_error_output PARM((j_common_ptr)); +METHODDEF(void) xv_prog_meter PARM((j_common_ptr)); static unsigned int j_getc PARM((j_decompress_ptr)); -METHODDEF boolean xv_process_comment PARM((j_decompress_ptr)); +METHODDEF(boolean) xv_process_comment PARM((j_decompress_ptr)); static int writeJFIF PARM((FILE *, byte *, int,int,int)); @@ -87,10 +87,10 @@ XSelectInput(theDisp, jpegW, ExposureMask | ButtonPressMask | KeyPressMask); - DCreate(&qDial, jpegW, 10, 10, 80, 100, 1, 100, 75, 5, + DCreate(&qDial, jpegW, 10, 10, 80, 100, 1.0, 100.0, 75.0, 1.0, 5.0, infofg, infobg, hicol, locol, "Quality", "%"); - DCreate(&smDial, jpegW, 120, 10, 80, 100, 0, 100, 0, 5, + DCreate(&smDial, jpegW, 120, 10, 80, 100, 0.0, 100.0, 0.0, 1.0, 5.0, infofg, infobg, hicol, locol, "Smoothing", "%"); BTCreate(&jbut[J_BOK], jpegW, JWIDE-180-1, JHIGH-10-BUTTH-1, 80, BUTTH, @@ -400,7 +400,7 @@ /**************************************************/ -METHODDEF void xv_error_exit(cinfo) +METHODDEF (void) xv_error_exit(cinfo) j_common_ptr cinfo; { my_error_ptr myerr; @@ -412,7 +412,7 @@ /**************************************************/ -METHODDEF void xv_error_output(cinfo) +METHODDEF (void) xv_error_output(cinfo) j_common_ptr cinfo; { my_error_ptr myerr; @@ -426,7 +426,7 @@ /**************************************************/ -METHODDEF void xv_prog_meter(cinfo) +METHODDEF (void) xv_prog_meter(cinfo) j_common_ptr cinfo; { struct jpeg_progress_mgr *prog; @@ -671,7 +671,7 @@ /**************************************************/ -METHODDEF boolean xv_process_comment(cinfo) +METHODDEF (boolean) xv_process_comment(cinfo) j_decompress_ptr cinfo; { int length, hasnull; @@ -759,8 +759,9 @@ jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, qDial.val, TRUE); - cinfo.smoothing_factor = smDial.val; + jpeg_set_quality(&cinfo, (int)qDial.val, TRUE); + cinfo.smoothing_factor = (int)smDial.val; + cinfo.optimize_coding = TRUE; jpeg_start_compress(&cinfo, TRUE); @@ -769,7 +770,7 @@ /*** COMMENT HANDLING ***/ sprintf(xvcmt, "%sXV %s Quality = %d, Smoothing = %d\n", - CREATOR_STR, REVDATE, qDial.val, smDial.val); + CREATOR_STR, REVDATE, (int)qDial.val, (int)smDial.val); if (picComments) { /* append XV comment */ char *sp, *sp1; int done; --- xv-3.10a/xvmisc.c Fri Jan 13 18:41:34 1995 +++ xv-3.10a/xvmisc.c Tue Jun 30 14:45:05 1998 @@ -520,6 +520,10 @@ if (tiffW) XDestroyWindow(theDisp, tiffW); #endif +#ifdef HAVE_PNG + if (pngW) XDestroyWindow(theDisp, pngW); +#endif + /* if NOT using stdcmap for images, free stdcmap */ if (colorMapMode != CM_STDCMAP) { int j; @@ -715,6 +719,10 @@ #ifdef HAVE_TIFF if (tiffW) XDefineCursor(theDisp, tiffW, otherc); +#endif + +#ifdef HAVE_PNG + if (pngW) XDefineCursor(theDisp, pngW, otherc); #endif } --- xv-3.10a/xvpng.c Wed Dec 31 19:00:00 1969 +++ xv-3.10a/xvpng.c Tue May 22 13:28:01 2001 @@ -0,0 +1,991 @@ +/* + * xvpng.c - load and write routines for 'PNG' format pictures + * + * callable functions + * + * CreatePNGW() + * PNGDialog(vis) + * PNGCheckEvent(xev) + * PNGSaveParams(fname, col) + * LoadPNG(fname, pinfo) + */ + +/*#include "copyright.h"*/ +/* (c) 1995 by Alexander Lehmann + * this file is a suplement to xv and is supplied under the same copying + * conditions (except the shareware part) + * Modified by Andreas Dilger to fix + * error handling for bad PNGs, add dialogs for interlacing and + * compression selection, and upgrade to libpng-0.89 + * The copyright will be passed on to JB at some future point if he + * so desires. + */ + +#include "xv.h" + +#ifdef HAVE_PNG + +#include "png.h" + +/*** Stuff for PNG Dialog box ***/ +#define PWIDE 318 +#define PHIGH 215 + +#define DISPLAY_GAMMA 2.20 /* Default display gamma */ +/* Default zlib compression level +#define COMPRESSION Z_BEST_COMPRESSION +*/ +#define COMPRESSION 6 + +#define DWIDE 86 +#define DHIGH 104 +#define PFX PWIDE-93 +#define PFY 44 +#define PFH 20 + +#define P_BOK 0 +#define P_BCANC 1 +#define P_NBUTTS 2 + +#define BUTTH 24 + +#define LF 10 /* a.k.a. '\n' on ASCII machines */ +#define CR 13 /* a.k.a. '\r' on ASCII machines */ + +/*** local functions ***/ +static void drawPD PARM((int, int, int, int)); +static void clickPD PARM((int, int)); +static void doCmd PARM((int)); +static void writePNG PARM((void)); +static int WritePNG PARM((FILE *, byte *, int, int, int, + byte *, byte *, byte *, int)); + +static void png_xv_error PARM((png_structp png_ptr, + png_const_charp message)); +static void png_xv_warning PARM((png_structp png_ptr, + png_const_charp message)); + +/*** local variables ***/ +static char *filename; +static char *fbasename; +static int colorType; +static int read_anything; +static double Display_Gamma = DISPLAY_GAMMA; + +static DIAL cDial, gDial; +static BUTT pbut[P_NBUTTS]; +static CBUTT interCB; +static CBUTT FdefCB, FnoneCB, FsubCB, FupCB, FavgCB, FPaethCB; + +/**************************************************************************/ +/* PNG SAVE DIALOG ROUTINES ***********************************************/ +/**************************************************************************/ + + +/*******************************************/ +void CreatePNGW() +{ + pngW = CreateWindow("xv png", "XVPNG", NULL, + PWIDE, PHIGH, infofg, infobg, 0); + if (!pngW) FatalError("can't create PNG window!"); + + XSelectInput(theDisp, pngW, ExposureMask | ButtonPressMask | KeyPressMask); + + DCreate(&cDial, pngW, 12, 25, DWIDE, DHIGH, (double)Z_NO_COMPRESSION, + (double)Z_BEST_COMPRESSION, COMPRESSION, 1.0, 3.0, + infofg, infobg, hicol, locol, "Compression", NULL); + + DCreate(&gDial, pngW, DWIDE+27, 25, DWIDE, DHIGH, 1.0, 3.5,DISPLAY_GAMMA,0.01,0.2, + infofg, infobg, hicol, locol, "Disp. Gamma", NULL); + + CBCreate(&interCB, pngW, DWIDE+30, DHIGH+3*LINEHIGH+2, "interlace", + infofg, infobg, hicol, locol); + + CBCreate(&FdefCB, pngW, PFX, PFY, "Default", + infofg, infobg, hicol, locol); + FdefCB.val = 1; + + CBCreate(&FnoneCB, pngW, PFX, FdefCB.y + PFH + 4, "none", + infofg, infobg, hicol, locol); + CBCreate(&FsubCB, pngW, PFX, FnoneCB.y + PFH, "sub", + infofg, infobg, hicol, locol); + CBCreate(&FupCB, pngW, PFX, FsubCB.y + PFH, "up", + infofg, infobg, hicol, locol); + CBCreate(&FavgCB, pngW, PFX, FupCB.y + PFH, "average", + infofg, infobg, hicol, locol); + CBCreate(&FPaethCB, pngW, PFX, FavgCB.y + PFH, "Paeth", + infofg, infobg, hicol, locol); + + FnoneCB.val = FsubCB.val = FupCB.val = FavgCB.val = FPaethCB.val = 1; + CBSetActive(&FnoneCB, !FdefCB.val); + CBSetActive(&FsubCB, !FdefCB.val); + CBSetActive(&FupCB, !FdefCB.val); + CBSetActive(&FavgCB, !FdefCB.val); + CBSetActive(&FPaethCB, !FdefCB.val); + + BTCreate(&pbut[P_BOK], pngW, PWIDE-180-1, PHIGH-10-BUTTH-1, 80, BUTTH, + "Ok", infofg, infobg, hicol, locol); + BTCreate(&pbut[P_BCANC], pngW, PWIDE-90-1, PHIGH-10-BUTTH-1, 80, BUTTH, + "Cancel", infofg, infobg, hicol, locol); + + XMapSubwindows(theDisp, pngW); +} + + +/*******************************************/ +void PNGDialog(vis) + int vis; +{ + if (vis) { + CenterMapWindow(pngW, pbut[P_BOK].x + (int) pbut[P_BOK].w/2, + pbut[P_BOK].y + (int) pbut[P_BOK].h/2, + PWIDE, PHIGH); + } + else XUnmapWindow(theDisp, pngW); + pngUp = vis; +} + + +/*******************************************/ +int PNGCheckEvent(xev) + XEvent *xev; +{ + /* check event to see if it's for one of our subwindows. If it is, + deal accordingly, and return '1'. Otherwise, return '0' */ + + int rv; + rv = 1; + + if (!pngUp) return 0; + + if (xev->type == Expose) { + int x,y,w,h; + XExposeEvent *e = (XExposeEvent *) xev; + x = e->x; y = e->y; w = e->width; h = e->height; + + /* throw away excess expose events for 'dumb' windows */ + if (e->count > 0 && (e->window == cDial.win)) {} + + else if (e->window == pngW) drawPD(x, y, w, h); + else if (e->window == cDial.win) DRedraw(&cDial); + else if (e->window == gDial.win) DRedraw(&gDial); + else rv = 0; + } + + else if (xev->type == ButtonPress) { + XButtonEvent *e = (XButtonEvent *) xev; + int x,y; + x = e->x; y = e->y; + + if (e->button == Button1) { + if (e->window == pngW) clickPD(x,y); + else if (e->window == cDial.win) DTrack(&cDial,x,y); + else if (e->window == gDial.win) DTrack(&gDial,x,y); + else rv = 0; + } /* button1 */ + else rv = 0; + } /* button press */ + + else if (xev->type == KeyPress) { + XKeyEvent *e = (XKeyEvent *) xev; + char buf[128]; KeySym ks; + int stlen; + + stlen = XLookupString(e,buf,128,&ks,(XComposeStatus *) NULL); + buf[stlen] = '\0'; + + RemapKeyCheck(ks, buf, &stlen); + + if (e->window == pngW) { + if (stlen) { + if (buf[0] == '\r' || buf[0] == '\n') { /* enter */ + FakeButtonPress(&pbut[P_BOK]); + } + else if (buf[0] == '\033') { /* ESC */ + FakeButtonPress(&pbut[P_BCANC]); + } + } + } + else rv = 0; + } + else rv = 0; + + if (rv==0 && (xev->type == ButtonPress || xev->type == KeyPress)) { + XBell(theDisp, 50); + rv = 1; /* eat it */ + } + + return rv; +} + + +/*******************************************/ +void PNGSaveParams(fname, col) + char *fname; + int col; +{ + filename = fname; + colorType = col; +} + + +/*******************************************/ +static void drawPD(x, y, w, h) + int x, y, w, h; +{ + char *title = "Save PNG file..."; + + char ctitle1[20]; + char *ctitle2 = "Useful range"; + char *ctitle3 = "is 2 - 7."; + char *ctitle4 = "Uncompressed = 0"; + + char *ftitle = "Row Filters:"; + + char gtitle[20]; + + int i; + XRectangle xr; + + xr.x = x; xr.y = y; xr.width = w; xr.height = h; + XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted); + + XSetForeground(theDisp, theGC, infofg); + XSetBackground(theDisp, theGC, infobg); + + for (i=0; ix, bp->y, bp->w, bp->h)) break; + } + + if (ijmpbuf)) { + png_destroy_write_struct(&png_ptr, &info_ptr); + return -1; + } + + png_init_io(png_ptr, fp); + + png_set_compression_level(png_ptr, (int)cDial.val); + + /* Don't bother filtering if we aren't compressing the image */ + if (FdefCB.val) + { + if ((int)cDial.val == 0) + png_set_filter(png_ptr, 0, PNG_FILTER_NONE); + } + else + { + filter = FnoneCB.val ? PNG_FILTER_NONE : 0; + filter |= FsubCB.val ? PNG_FILTER_SUB : 0; + filter |= FupCB.val ? PNG_FILTER_UP : 0; + filter |= FavgCB.val ? PNG_FILTER_AVG : 0; + filter |= FPaethCB.val ? PNG_FILTER_PAETH : 0; + + png_set_filter(png_ptr, 0, filter); + } + + info_ptr->width = w; + info_ptr->height = h; + + info_ptr->interlace_type = interCB.val ? 1 : 0; + + if (colorType == F_FULLCOLOR || colorType == F_REDUCED) { + if(ptype == PIC24) { + linesize = 3*w; + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + info_ptr->bit_depth = 8; + } else { + linesize = w; + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + if(numcols <= 2) + info_ptr->bit_depth = 1; + else + if(numcols <= 4) + info_ptr->bit_depth = 2; + else + if(numcols <= 16) + info_ptr->bit_depth = 4; + else + info_ptr->bit_depth = 8; + + for(i = 0; i < numcols; i++) { + palette[i].red = rmap[i]; + palette[i].green = gmap[i]; + palette[i].blue = bmap[i]; + } + info_ptr->num_palette = numcols; + info_ptr->palette = palette; + info_ptr->valid |= PNG_INFO_PLTE; + } + } + + else if(colorType == F_GREYSCALE || colorType == F_BWDITHER) { + info_ptr->color_type = PNG_COLOR_TYPE_GRAY; + if(colorType == F_BWDITHER) { + /* shouldn't happen */ + if (ptype == PIC24) FatalError("PIC24 and B/W Stipple in WritePNG()"); + + info_ptr->bit_depth = 1; + if(MONO(rmap[0], gmap[0], bmap[0]) > MONO(rmap[1], gmap[1], bmap[1])) { + remap[0] = 1; + remap[1] = 0; + } + else { + remap[0] = 0; + remap[1] = 1; + } + linesize = w; + } + else { + if(ptype == PIC24) { + linesize = w*3; + info_ptr->bit_depth = 8; + } + else { + int low_presc; + + linesize = w; + + for(i = 0; i < numcols; i++) + remap[i] = MONO(rmap[i], gmap[i], bmap[i]); + + for(; i < 256; i++) + remap[i]=0; + + info_ptr->bit_depth = 8; + + /* Note that this fails most of the time because of gamma */ + /* try to adjust to 4 bit prescision grayscale */ + + low_presc=1; + + for(i = 0; i < numcols; i++) { + if((remap[i] & 0x0f) * 0x11 != remap[i]) { + low_presc = 0; + break; + } + } + + if(low_presc) { + for(i = 0; i < numcols; i++) { + remap[i] &= 0xf; + } + info_ptr->bit_depth = 4; + + /* try to adjust to 2 bit prescision grayscale */ + + for(i = 0; i < numcols; i++) { + if((remap[i] & 0x03) * 0x05 != remap[i]) { + low_presc = 0; + break; + } + } + } + + if(low_presc) { + for(i = 0; i < numcols; i++) { + remap[i] &= 3; + } + info_ptr->bit_depth = 2; + + /* try to adjust to 1 bit prescision grayscale */ + + for(i = 0; i < numcols; i++) { + if((remap[i] & 0x01) * 0x03 != remap[i]) { + low_presc = 0; + break; + } + } + } + + if(low_presc) { + for(i = 0; i < numcols; i++) { + remap[i] &= 1; + } + info_ptr->bit_depth = 1; + } + } + } + } + + else + png_error(png_ptr, "Unknown colorstyle in WritePNG"); + + if ((text = (png_textp)malloc(sizeof(png_text)))) { + sprintf(software, "XV %s", REVDATE); + + text->compression = -1; + text->key = "Software"; + text->text = software; + text->text_length = strlen(text->text); + + info_ptr->max_text = 1; + info_ptr->num_text = 1; + info_ptr->text = text; + } + + Display_Gamma = gDial.val; /* Save the current gamma for loading */ + + info_ptr->gamma = 1.0/gDial.val; + info_ptr->valid |= PNG_INFO_gAMA; + + png_write_info(png_ptr, info_ptr); + + if(info_ptr->bit_depth < 8) + png_set_packing(png_ptr); + + pass=png_set_interlace_handling(png_ptr); + + if((png_line = malloc(linesize)) == NULL) + png_error(png_ptr, "cannot allocate temp image line"); + + for(i = 0; i < pass; i++) { + int j; + p = pic; + for(j = 0; j < h; j++) { + if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY) { + int k; + for(k = 0; k < w; k++) + png_line[k] = ptype==PIC24 ? MONO(p[k*3], p[k*3+1], p[k*3+2]) : + remap[p[k]]; + png_write_row(png_ptr, png_line); + } else /* RGB or palette */ + png_write_row(png_ptr, p); + if((j & 0x1f) == 0) WaitCursor(); + p += linesize; + } + } + + free(png_line); + + if (text) + { + if (picComments && strlen(picComments) && + (savecmnt = (char *)malloc((strlen(picComments) + 1)*sizeof(char)))) { + png_textp tp; + char *comment, *key; + + strcpy(savecmnt, picComments); + key = savecmnt; + tp = text; + info_ptr->num_text = 0; + + comment = strchr(key, ':'); + + do { + /* Allocate a larger structure for comments if necessary */ + if (info_ptr->num_text >= info_ptr->max_text) + { + if ((tp = + realloc(text, (info_ptr->num_text + 2)*sizeof(png_text))) == NULL) + { + break; + } + else + { + text = tp; + tp = &text[info_ptr->num_text]; + info_ptr->max_text += 2; + } + } + + /* See if it looks like a PNG keyword from LoadPNG */ + /* GRR: should test for strictly < 80, right? (key = 1-79 chars only) */ + if(comment && comment[1] == ':' && comment - key <= 80) { + *(comment++) = '\0'; + *(comment++) = '\0'; + + /* If the comment is the 'Software' chunk XV writes, we remove it, + since we have already stored one */ + if (strcmp(key, "Software") == 0 && strncmp(comment, "XV", 2) == 0) { + key = strchr(comment, '\n'); + if(key) + key++; /* skip \n */ + comment = strchr(key, ':'); + } + /* We have another keyword and/or comment to write out */ + else { + tp->key = key; + tp->text = comment; + + /* We have to find the end of this comment, and the next keyword + if there is one */ + for (; NULL != (key = comment = strchr(comment, ':')); comment++) + if (key[1] == ':') + break; + + /* It looks like another keyword, go backward to the beginning */ + if (key) { + while(key > tp->text && *key != '\n') + key--; + + if (key > tp->text && comment - key <= 80) { + *key = '\0'; + key++; + } + } + + tp->text_length = strlen(tp->text); + + /* We don't have another keyword, so remove the last newline */ + if (!key && tp->text[tp->text_length - 1] == '\n') + { + tp->text[tp->text_length] = '\0'; + tp->text_length--; + } + + tp->compression = tp->text_length > 640 ? 0 : -1; + info_ptr->num_text++; + tp++; + } + } + /* Just a generic comment: make sure line-endings are valid for PNG */ + else { + char *p=key, *q=key; /* only deleting chars, not adding any */ + + while (*p) { + if (*p == CR) { /* lone CR or CR/LF: EOL either way */ + *q++ = LF; /* LF is the only allowed PNG line-ending */ + if (p[1] == LF) /* get rid of any original LF */ + ++p; + } else if (*p == LF) /* lone LF */ + *q++ = LF; + else + *q++ = *p; + ++p; + } + *q = '\0'; /* unnecessary...but what the heck */ + tp->key = "Comment"; + tp->text = key; + tp->text_length = q - key; + tp->compression = tp->text_length > 750 ? 0 : -1; + info_ptr->num_text++; + key = NULL; + } + } while (key && *key); + } + else + { + info_ptr->num_text = 0; + } + } + info_ptr->text = text; + + png_convert_from_time_t(&(info_ptr->mod_time), time(NULL)); + info_ptr->valid |= PNG_INFO_tIME; + + png_write_end(png_ptr, info_ptr); + fflush(fp); /* just in case we core-dump before finishing... */ + + if (text) + { + free(text); + /* must do this or png_destroy_write_struct() 0.97+ will free text again: */ + info_ptr->text = (png_textp)NULL; + if (savecmnt) + { + free(savecmnt); + savecmnt = (char *)NULL; + } + } + + png_destroy_write_struct(&png_ptr, &info_ptr); + + return 0; +} + + +/*******************************************/ +int LoadPNG(fname, pinfo) + char *fname; + PICINFO *pinfo; +/*******************************************/ +{ + /* returns '1' on success */ + + FILE *fp; + png_struct *png_ptr; + png_info *info_ptr; + png_color_16 my_background; + int i,j; + int linesize; + int filesize; + int pass; + size_t commentsize; + + fbasename = BaseName(fname); + + pinfo->pic = (byte *) NULL; + pinfo->comment = (char *) NULL; + + read_anything=0; + + /* open the file */ + fp = xv_fopen(fname,"r"); + if (!fp) + { + SetISTR(ISTR_WARNING,"%s: can't open file", fname); + return 0; + } + + /* find the size of the file */ + fseek(fp, 0L, 2); + filesize = ftell(fp); + fseek(fp, 0L, 0); + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + png_xv_error, png_xv_warning); + if(!png_ptr) { + fclose(fp); + FatalError("malloc failure in LoadPNG"); + } + + info_ptr = png_create_info_struct(png_ptr); + + if(!info_ptr) { + fclose(fp); + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); + FatalError("malloc failure in LoadPNG"); + } + + if(setjmp(png_ptr->jmpbuf)) { + fclose(fp); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + if(!read_anything) { + if(pinfo->pic) { + free(pinfo->pic); + pinfo->pic = NULL; + } + if(pinfo->comment) { + free(pinfo->comment); + pinfo->comment = NULL; + } + } + return read_anything; + } + + png_init_io(png_ptr, fp); + png_read_info(png_ptr, info_ptr); + + pinfo->w = pinfo->normw = info_ptr->width; + pinfo->h = pinfo->normh = info_ptr->height; + + pinfo->frmType = F_PNG; + + sprintf(pinfo->fullInfo, "PNG, %d bit ", + info_ptr->bit_depth * info_ptr->channels); + + switch(info_ptr->color_type) { + case PNG_COLOR_TYPE_PALETTE: + strcat(pinfo->fullInfo, "palette color"); + break; + + case PNG_COLOR_TYPE_GRAY: + strcat(pinfo->fullInfo, "grayscale"); + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + strcat(pinfo->fullInfo, "grayscale+alpha"); + break; + + case PNG_COLOR_TYPE_RGB: + strcat(pinfo->fullInfo, "truecolor"); + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + strcat(pinfo->fullInfo, "truecolor+alpha"); + break; + } + + sprintf(pinfo->fullInfo + strlen(pinfo->fullInfo), + ", %sinterlaced. (%d bytes)", + info_ptr->interlace_type ? "" : "non-", filesize); + + sprintf(pinfo->shrtInfo, "%dx%d PNG", info_ptr->width, info_ptr->height); + + if (info_ptr->bit_depth < 8) + png_set_packing(png_ptr); + + if (info_ptr->valid & PNG_INFO_gAMA) + png_set_gamma(png_ptr, Display_Gamma, info_ptr->gamma); + else + png_set_gamma(png_ptr, Display_Gamma, 0.45); + + if (info_ptr->valid & PNG_INFO_bKGD) + png_set_background(png_ptr, &info_ptr->background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else { + my_background.red = my_background.green = my_background.blue = + my_background.gray = 0; + png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, + 0, Display_Gamma); + } + + if (info_ptr->bit_depth == 16) + png_set_strip_16(png_ptr); + + if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || + info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (info_ptr->bit_depth == 1) + pinfo->colType = F_BWDITHER; + else + pinfo->colType = F_GREYSCALE; + png_set_expand(png_ptr); + } + + pass=png_set_interlace_handling(png_ptr); + + png_read_update_info(png_ptr, info_ptr); + + if(info_ptr->color_type == PNG_COLOR_TYPE_RGB || + info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { + linesize = pinfo->w * 3; + pinfo->colType = F_FULLCOLOR; + pinfo->type = PIC24; + } else { + linesize = pinfo->w; + pinfo->type = PIC8; + if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || + info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + for(i = 0; i < 256; i++) + pinfo->r[i] = pinfo->g[i] = pinfo->b[i] = i; + } else { + pinfo->colType = F_FULLCOLOR; + for(i = 0; i < info_ptr->num_palette; i++) { + pinfo->r[i] = info_ptr->palette[i].red; + pinfo->g[i] = info_ptr->palette[i].green; + pinfo->b[i] = info_ptr->palette[i].blue; + } + } + } + pinfo->pic = calloc((size_t)(linesize*pinfo->h), (size_t)1); + + if(!pinfo->pic) { + png_error(png_ptr, "can't allocate space for PNG image"); + } + + png_start_read_image(png_ptr); + + for(i = 0; i < pass; i++) { + byte *p = pinfo->pic; + for(j = 0; j < pinfo->h; j++) { + png_read_row(png_ptr, p, NULL); + read_anything = 1; + if((j & 0x1f) == 0) WaitCursor(); + p += linesize; + } + } + + png_read_end(png_ptr, info_ptr); + + if(info_ptr->num_text > 0) { + commentsize = 1; + + for(i = 0; i < info_ptr->num_text; i++) + commentsize += strlen(info_ptr->text[i].key) + 1 + + info_ptr->text[i].text_length + 2; + + if((pinfo->comment = malloc(commentsize)) == NULL) { + png_warning(png_ptr,"can't allocate comment string"); + } + else { + pinfo->comment[0] = '\0'; + for(i = 0; i < info_ptr->num_text; i++) { + strcat(pinfo->comment, info_ptr->text[i].key); + strcat(pinfo->comment, "::"); + strcat(pinfo->comment, info_ptr->text[i].text); + strcat(pinfo->comment, "\n"); + } + } + } + + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + + fclose(fp); + + return 1; +} + + +/*******************************************/ +static void +png_xv_error(png_ptr, message) + png_structp png_ptr; + png_const_charp message; +{ + SetISTR(ISTR_WARNING,"%s: libpng error: %s", fbasename, message); + + longjmp(png_ptr->jmpbuf, 1); +} + + +/*******************************************/ +static void +png_xv_warning(png_ptr, message) + png_structp png_ptr; + png_const_charp message; +{ + if (!png_ptr) + return; + + SetISTR(ISTR_WARNING,"%s: libpng warning: %s", fbasename, message); +} + +#endif --- xv-3.10a/xvpopup.c Thu Jan 19 13:09:31 1995 +++ xv-3.10a/xvpopup.c Tue Jun 30 14:45:05 1998 @@ -200,14 +200,14 @@ if (!padHaveDooDads) { DCreate(&padWDial, popW, 16, puhigh-16-100-1,75,100, - 1, 2048, pWIDE, 10, + 1.0, 2048.0, (double)pWIDE, 1.0, 10.0, infofg, infobg, hicol, locol, "Width", NULL); DCreate(&padHDial, popW, 16+1+75, puhigh-16-100-1,75,100, - 1, 2048, pHIGH, 10, + 1.0, 2048.0, (double)pHIGH, 1.0, 10.0, infofg, infobg, hicol, locol, "Height", NULL); DCreate(&padODial, popW, 16+1+75+75+9, puhigh-16-100-1,75,100, - 0, 100, 100, 10, + 0.0, 100.0, 100.0, 1.0, 10.0, infofg, infobg, hicol, locol, "Opaque", NULL); MBCreate(&padMthdMB, popW, 100-2+44, 10, 140, 19, NULL, @@ -258,9 +258,9 @@ else if (poptyp == ISPAD) { BTSetActive(&bts[0], (int) strlen(gsBuf)); i = pWIDE * 3; RANGE(i,2048,9999); - DSetRange(&padWDial, 1, i, padWDial.val, 10); + DSetRange(&padWDial, 1.0, (double)i, padWDial.val, 1.0, 10.0); i = pHIGH * 3; RANGE(i,2048,9999); - DSetRange(&padHDial, 1, i, padHDial.val, 10); + DSetRange(&padHDial, 1.0, (double)i, padHDial.val, 1.0, 10.0); DSetActive(&padWDial, (padMode!=PAD_LOAD)); /* DSetRange activates dial */ DSetActive(&padHDial, (padMode!=PAD_LOAD)); @@ -465,9 +465,9 @@ changedGSBuf(); /* careful! popW doesn't exist yet! */ if (padHaveDooDads) { - oldW = padWDial.val; - oldH = padHDial.val; - oldO = padODial.val; + oldW = (int)padWDial.val; + oldH = (int)padHDial.val; + oldO = (int)padODial.val; } else { oldW = pWIDE; oldH = pHIGH; oldO = 100; } @@ -486,9 +486,9 @@ } if (rv == 1) { /* cancelled: restore normal values */ - DSetVal(&padWDial, oldW); - DSetVal(&padHDial, oldH); - DSetVal(&padODial, oldO); + DSetVal(&padWDial, (double)oldW); + DSetVal(&padHDial, (double)oldH); + DSetVal(&padODial, (double)oldO); } XUnmapWindow(theDisp, padWDial.win); @@ -498,9 +498,9 @@ /* load up return values */ *pMode = padMode; *pStr = padBuf; - *pWide = padWDial.val; - *pHigh = padHDial.val; - *pOpaque = padODial.val; + *pWide = (int)padWDial.val; + *pHigh = (int)padHDial.val; + *pOpaque = (int)padODial.val; *pOmode = padOMode; return rv; @@ -972,8 +972,8 @@ else if (popUp == ISPAD) { if (PTINRECT(x, y, padDButt.x, padDButt.y, padDButt.w, padDButt.h)) { if (BTTrack(&padDButt)) { - DSetVal(&padWDial, pWIDE); - DSetVal(&padHDial, pHIGH); + DSetVal(&padWDial, (double)pWIDE); + DSetVal(&padHDial, (double)pHIGH); } } --- xv-3.10a/xvps.c Thu Dec 22 17:34:42 1994 +++ xv-3.10a/xvps.c Tue Jun 30 14:59:08 1998 @@ -139,9 +139,9 @@ CBCreate(&encapsCB, psW, 240, 7, "preview", infofg, infobg, hicol, locol); CBCreate(&pscompCB, psW, 331, 7, "compress", infofg, infobg, hicol, locol); - DCreate(&xsDial, psW, 240, 30, 80, 100, 10, 800, 100, 5, + DCreate(&xsDial, psW, 240, 30, 80, 100, 10.0, 800.0, 100.0, 0.5, 5.0, infofg, infobg, hicol, locol, "Width", "%"); - DCreate(&ysDial, psW, 331, 30, 80, 100, 10, 800, 100, 5, + DCreate(&ysDial, psW, 331, 30, 80, 100, 10.0, 800.0, 100.0, 0.5, 5.0, infofg, infobg, hicol, locol, "Height", "%"); xsDial.drawobj = changedScale; ysDial.drawobj = changedScale; @@ -236,10 +236,10 @@ if (rd_int("psres")) { /* xv.psres: default paper resolution */ if (def_int >= 10 && def_int <= 720) { - int i = (int) ((PIX2INCH * 100) / def_int); + double v = (PIX2INCH * 100) / def_int; - DSetVal(&xsDial, i); - DSetVal(&ysDial, i); + DSetVal(&xsDial, v); + DSetVal(&ysDial, v); } } @@ -836,7 +836,7 @@ if (scx < scy) { sz_iny = h * scx; } else { sz_inx = w * scy; } - DSetVal(&xsDial, (int) ((100 * (sz_inx * PIX2INCH) / w) + .5)); + DSetVal(&xsDial, 100 * (sz_inx * PIX2INCH) / w); DSetVal(&ysDial, xsDial.val); sz_inx = (double) w / PIX2INCH * (xsDial.val / 100.0); @@ -891,7 +891,7 @@ int i, j, q, err, rpix, gpix, bpix, nc, ptype; int iw, ih, ox, oy, slen, lwidth, bits, colorps, w, h, pfree; double iwf, ihf; - byte *inpix, *rmap, *gmap, *bmap; + byte *save_inpix, *inpix, *rmap, *gmap, *bmap; slen = bits = colorps = 0; @@ -901,7 +901,8 @@ WaitCursor(); - inpix = GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap); + save_inpix = inpix = + GenSavePic(&ptype, &w, &h, &pfree, &nc, &rmap, &gmap, &bmap); /* printed image will have size iw,ih (in picas) */ @@ -1123,7 +1124,7 @@ fprintf(fp,"origstate restore\n\n"); fprintf(fp,"%%%%Trailer\n"); - if (pfree) free(inpix); + if (pfree) free(save_inpix); if (CloseOutFile(fp, filename, (err==EOF)) == 0) { DirBox(0); --- xv-3.10a/xvsmooth.c Thu Dec 22 17:34:42 1994 +++ xv-3.10a/xvsmooth.c Tue Jun 30 14:59:08 1998 @@ -65,10 +65,13 @@ returns a dwide*dhigh 24bit image, or NULL on failure (malloc) */ /* rmap,gmap,bmap should be 'desired' colors */ + /* DANGER: This code assumes that a right-shift on signed integers is + performed arithmetically, i.e. the sign bit is copied to the right. */ + byte *pic24, *pp; - int *cxtab, *pxtab; - int y1Off, cyOff; - int ex, ey, cx, cy, px, py, apx, apy, x1, y1; + int *pxtab; + int ex, ey, px, py, x0, x1, y0, y1; + int y0off, y1off; int cA, cB, cC, cD; int pA, pB, pC, pD; int retval, bperpix; @@ -98,69 +101,61 @@ else { /* dwide >= swide && dhigh >= shigh */ - /* cx,cy = original pixel in pic824. px,py = relative position - of pixel ex,ey inside of cx,cy as percentages +-50%, +-50%. - 0,0 = middle of pixel */ - - /* we can save a lot of time by precomputing cxtab[] and pxtab[], both - dwide arrays of ints that contain values for the equations: - cx = (ex * swide) / dwide; - px = ((ex * swide * 100) / dwide) - (cx * 100) - 50; */ - - cxtab = (int *) malloc(dwide * sizeof(int)); - if (!cxtab) { free(pic24); return NULL; } + /* px, py = location on original image, in units of 1/256 pixel + We can save time by precomputing all values of px. */ pxtab = (int *) malloc(dwide * sizeof(int)); - if (!pxtab) { free(pic24); free(cxtab); return NULL; } - - for (ex=0; exshigh-1) y1=shigh-1; } + py = ((ey << 8) + 128) * shigh / dhigh - 128; + y0 = py >> 8; /* Put integer part in y0 */ + y1 = y0 + 1; + py &= 255; /* Keep fractional part in py */ + + if (y0 < 0) y0 = y1 = 0; + if (y1 >= shigh) y0 = y1 = shigh-1; - cyOff = cy * swide * bperpix; /* current line */ - y1Off = y1 * swide * bperpix; /* up or down one line, depending */ + y0off = y0 * swide * bperpix; /* current line */ + y1off = y1 * swide * bperpix; /* one line down */ if ((ey&15) == 0) WaitCursor(); - for (ex=0; ex> 8; /* Put integer part in x0 */ + x1 = x0 + 1; + px &= 255; /* Keep fractional part in px */ - if (px<0) { x1 = cx-1; if (x1<0) x1=0; } - else { x1 = cx+1; if (x1>swide-1) x1=swide-1; } + if (x0 < 0) x0 = x1 = 0; + if (x1 >= swide) x0 = x1 = swide-1; if (is24) { - pptr = pic824 + y1Off + x1*bperpix; /* corner pixel */ + pptr = pic824 + y0off + x0*bperpix; /* upper left pixel */ rA = *pptr++; gA = *pptr++; bA = *pptr++; - pptr = pic824 + y1Off + cx*bperpix; /* up/down center pixel */ + pptr = pic824 + y0off + x1*bperpix; /* upper right pixel */ rB = *pptr++; gB = *pptr++; bB = *pptr++; - pptr = pic824 + cyOff + x1*bperpix; /* left/right center pixel */ + pptr = pic824 + y1off + x0*bperpix; /* lower left pixel */ rC = *pptr++; gC = *pptr++; bC = *pptr++; - pptr = pic824 + cyOff + cx*bperpix; /* center pixel */ + pptr = pic824 + y1off + x1*bperpix; /* lower right pixel */ rD = *pptr++; gD = *pptr++; bD = *pptr++; } else { /* 8-bit picture */ - cA = pic824[y1Off + x1]; /* corner pixel */ - cB = pic824[y1Off + cx]; /* up/down center pixel */ - cC = pic824[cyOff + x1]; /* left/right center pixel */ - cD = pic824[cyOff + cx]; /* center pixel */ + cA = pic824[y0off + x0]; /* upper left pixel */ + cB = pic824[y0off + x1]; /* upper right pixel */ + cC = pic824[y1off + x0]; /* lower left pixel */ + cD = pic824[y1off + x1]; /* lower right pixel */ } /* quick check */ @@ -170,38 +165,30 @@ } else { - /* compute weighting factors */ - apx = abs(px); apy = abs(py); - pA = (apx * apy) / 100; - pB = (apy * (100 - apx)) / 100; - pC = (apx * (100 - apy)) / 100; - pD = 100 - (pA + pB + pC); + pA = (256-px)*(256-py); /* compute weighting factors */ + pB = px * (256-py); /* total weight is exactly 2^16 */ + pC = (256-px) * py; + pD = px * py; if (is24) { - *pp++ = ((int) (pA * rA))/100 + ((int) (pB * rB))/100 + - ((int) (pC * rC))/100 + ((int) (pD * rD))/100; - - *pp++ = ((int) (pA * gA))/100 + ((int) (pB * gB))/100 + - ((int) (pC * gC))/100 + ((int) (pD * gD))/100; - - *pp++ = ((int) (pA * bA))/100 + ((int) (pB * bB))/100 + - ((int) (pC * bC))/100 + ((int) (pD * bD))/100; + *pp++ = (pA * rA + pB * rB + pC * rC + pD * rD) + 32768 >> 16; + *pp++ = (pA * gA + pB * gB + pC * gC + pD * gD) + 32768 >> 16; + *pp++ = (pA * bA + pB * bB + pC * bC + pD * bD) + 32768 >> 16; } else { /* 8-bit pic */ - *pp++ = ((int) (pA * rmap[cA]))/100 + ((int)(pB * rmap[cB]))/100 + - ((int) (pC * rmap[cC]))/100 + ((int)(pD * rmap[cD]))/100; + *pp++ = (pA * rmap[cA] + pB * rmap[cB] + pC * rmap[cC] + + pD * rmap[cD]) + 32768 >> 16; - *pp++ = ((int) (pA * gmap[cA]))/100 + ((int)(pB * gmap[cB]))/100 + - ((int) (pC * gmap[cC]))/100 + ((int)(pD * gmap[cD]))/100; + *pp++ = (pA * gmap[cA] + pB * gmap[cB] + pC * gmap[cC] + + pD * gmap[cD]) + 32768 >> 16; - *pp++ = ((int)(pA * bmap[cA]))/100 + ((int)(pB * bmap[cB]))/100 + - ((int)(pC * bmap[cC]))/100 + ((int)(pD * bmap[cD]))/100; + *pp++ = (pA * bmap[cA] + pB * bmap[cB] + pC * bmap[cC] + + pD * bmap[cD]) + 32768 >> 16; } } } } - free(cxtab); free(pxtab); retval = 0; /* okay */ } @@ -369,7 +356,7 @@ lastline = linecnt = 0; - for (i=0, clptr=pic824; i<=shigh; i++, clptr+=swide*bperpix) { + for (i=0, clptr=pic824; ishrtInfo, "%ux%u TIFF.",w,h); + sprintf(pinfo->shrtInfo, "%lux%lu TIFF.",w,h); pic8 = (byte *) malloc((size_t) w*h); if (!pic8) FatalError("loadPalette() - couldn't malloc 'pic8'"); @@ -214,7 +214,7 @@ "???"), filesize); - sprintf(pinfo->shrtInfo, "%ux%u TIFF.",w,h); + sprintf(pinfo->shrtInfo, "%lux%lu TIFF.",w,h); /* allocate 24-bit image */ pic24 = (byte *) malloc((size_t) w*h*3); @@ -301,10 +301,10 @@ static byte **BWmap; static byte **PALmap; -typedef void (*tileContigRoutine) PARM((byte*, u_char*, RGBvalue*, +typedef void (*xvtileContigRoutine) PARM((byte*, u_char*, RGBvalue*, uint32, uint32, int, int)); -typedef void (*tileSeparateRoutine) PARM((byte*, u_char*, u_char*, u_char*, +typedef void (*xvtileSeparateRoutine) PARM((byte*, u_char*, u_char*, u_char*, RGBvalue*, uint32, uint32, int, int)); @@ -366,8 +366,8 @@ static void putcontig8bitYCbCrtile PARM((byte *, u_char *, RGBvalue *, uint32, uint32, int, int)); -static tileContigRoutine pickTileContigCase PARM((RGBvalue *)); -static tileSeparateRoutine pickTileSeparateCase PARM((RGBvalue *)); +static xvtileContigRoutine pickTileContigCase PARM((RGBvalue *)); +static xvtileSeparateRoutine pickTileSeparateCase PARM((RGBvalue *)); /*******************************************/ @@ -641,7 +641,7 @@ u_char *buf; int fromskew, toskew; u_int nrow; - tileContigRoutine put; + xvtileContigRoutine put; put = pickTileContigCase(Map); if (put == 0) return (0); @@ -708,7 +708,7 @@ int tilesize; int fromskew, toskew; u_int nrow; - tileSeparateRoutine put; + xvtileSeparateRoutine put; put = pickTileSeparateCase(Map); if (put == 0) return (0); @@ -779,7 +779,7 @@ { uint32 row, y, nrow; u_char *buf; - tileContigRoutine put; + xvtileContigRoutine put; uint32 rowsperstrip; uint32 imagewidth; int scanline; @@ -832,7 +832,7 @@ u_char *r, *g, *b; uint32 row, y, nrow; int scanline; - tileSeparateRoutine put; + xvtileSeparateRoutine put; uint32 rowsperstrip; uint32 imagewidth; u_int stripsize; @@ -1065,7 +1065,7 @@ int fromskew, toskew; { while (h-- > 0) { - UNROLL8(w,0, *cp++ = PALmap[*pp++][0]); + UNROLL8(w,, *cp++ = PALmap[*pp++][0]); cp += toskew; pp += fromskew; } @@ -1262,7 +1262,7 @@ } } else { while (h-- > 0) { - UNROLL8(w,0, + UNROLL8(w,, *cp++ = pp[0]; *cp++ = pp[1]; *cp++ = pp[2]; @@ -1335,7 +1335,7 @@ } } else { while (h-- > 0) { - UNROLL8(w,0, + UNROLL8(w,, *cp++ = *r++; *cp++ = *g++; *cp++ = *b++; @@ -1489,16 +1489,16 @@ /* * Select the appropriate conversion routine for packed data. */ -static tileContigRoutine pickTileContigCase(Map) +static xvtileContigRoutine pickTileContigCase(Map) RGBvalue* Map; { - tileContigRoutine put = 0; + xvtileContigRoutine put = 0; switch (photometric) { case PHOTOMETRIC_RGB: switch (bitspersample) { - case 8: put = (tileContigRoutine) putRGBcontig8bittile; break; - case 16: put = (tileContigRoutine) putRGBcontig16bittile; break; + case 8: put = putRGBcontig8bittile; break; + case 16: put = (xvtileContigRoutine)putRGBcontig16bittile; break; } break; @@ -1540,16 +1540,16 @@ * NB: we assume that unpacked single channel data is directed * to the "packed routines. */ -static tileSeparateRoutine pickTileSeparateCase(Map) +static xvtileSeparateRoutine pickTileSeparateCase(Map) RGBvalue* Map; { - tileSeparateRoutine put = 0; + xvtileSeparateRoutine put = 0; switch (photometric) { case PHOTOMETRIC_RGB: switch (bitspersample) { - case 8: put = (tileSeparateRoutine) putRGBseparate8bittile; break; - case 16: put = (tileSeparateRoutine) putRGBseparate16bittile; break; + case 8: put = (xvtileSeparateRoutine) putRGBseparate8bittile; break; + case 16: put = (xvtileSeparateRoutine) putRGBseparate16bittile; break; } break; }