/* Decompression test */ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf, unsigned long *jpegsize, unsigned char *dstbuf, int w, int h, int subsamp, int jpegqual, char *filename, int tilew, int tileh) { char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr; FILE *file=NULL; tjhandle handle=NULL; int row, col, i, dstbufalloc=0, retval=0; double start, elapsed; int ps=tjPixelSize[pf]; int yuvsize=tjBufSizeYUV(w, h, subsamp), bufsize; int scaledw=(yuv==YUVDECODE)? w : TJSCALED(w, sf); int scaledh=(yuv==YUVDECODE)? h : TJSCALED(h, sf); int pitch=scaledw*ps; int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh; unsigned char *dstptr, *dstptr2; if(jpegqual>0) { snprintf(qualstr, 6, "_Q%d", jpegqual); qualstr[5]=0; } if((handle=tjInitDecompress())==NULL) _throwtj("executing tjInitDecompress()"); bufsize=(yuv==YUVDECODE? yuvsize:pitch*h); if(dstbuf==NULL) { if((dstbuf=(unsigned char *)malloc(bufsize)) == NULL) _throwunix("allocating image buffer"); dstbufalloc=1; } /* Set the destination buffer to gray so we know whether the decompressor attempted to write to it */ memset(dstbuf, 127, bufsize); /* Execute once to preload cache */ if(yuv==YUVDECODE) { if(tjDecompressToYUV(handle, jpegbuf[0], jpegsize[0], dstbuf, flags)==-1) _throwtj("executing tjDecompressToYUV()"); } else if(tjDecompress2(handle, jpegbuf[0], jpegsize[0], dstbuf, scaledw, pitch, scaledh, pf, flags)==-1) _throwtj("executing tjDecompress2()"); /* Benchmark */ for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++) { int tile=0; if(yuv==YUVDECODE) { if(tjDecompressToYUV(handle, jpegbuf[0], jpegsize[0], dstbuf, flags)==-1) _throwtj("executing tjDecompressToYUV()"); } else for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch*tileh) { for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, dstptr2+=ps*tilew) { int width=dotile? min(tilew, w-col*tilew):scaledw; int height=dotile? min(tileh, h-row*tileh):scaledh; if(tjDecompress2(handle, jpegbuf[tile], jpegsize[tile], dstptr2, width, pitch, height, pf, flags)==-1) _throwtj("executing tjDecompress2()"); } } } if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); handle=NULL; if(quiet) { printf("%s\n", sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024)); } else { printf("D--> Frame rate: %f fps\n", (double)i/elapsed); printf(" Dest. throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)i/elapsed); } if(yuv==YUVDECODE) { snprintf(tempstr, 1024, "%s_%s%s.yuv", filename, subName[subsamp], qualstr); if((file=fopen(tempstr, "wb"))==NULL) _throwunix("opening YUV image for output"); if(fwrite(dstbuf, yuvsize, 1, file)!=1) _throwunix("writing YUV image"); fclose(file); file=NULL; } else { if(sf.num!=1 || sf.denom!=1) snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom); else if(tilew!=w || tileh!=h) snprintf(sizestr, 20, "%dx%d", tilew, tileh); else snprintf(sizestr, 20, "full"); if(decomponly) snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, ext); else snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subName[subsamp], qualstr, sizestr, ext); if(savebmp(tempstr, dstbuf, scaledw, scaledh, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1) _throwbmp("saving bitmap"); ptr=strrchr(tempstr, '.'); snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext); if(srcbuf && sf.num==1 && sf.denom==1) { if(!quiet) printf("Compression error written to %s.\n", tempstr); if(subsamp==TJ_GRAYSCALE) { int index, index2; for(row=0, index=0; row<h; row++, index+=pitch) { for(col=0, index2=index; col<w; col++, index2+=ps) { int rindex=index2+tjRedOffset[pf]; int gindex=index2+tjGreenOffset[pf]; int bindex=index2+tjBlueOffset[pf]; int y=(int)((double)srcbuf[rindex]*0.299 + (double)srcbuf[gindex]*0.587 + (double)srcbuf[bindex]*0.114 + 0.5); if(y>255) y=255; if(y<0) y=0; dstbuf[rindex]=abs(dstbuf[rindex]-y); dstbuf[gindex]=abs(dstbuf[gindex]-y); dstbuf[bindex]=abs(dstbuf[bindex]-y); } } } else { for(row=0; row<h; row++) for(col=0; col<w*ps; col++) dstbuf[pitch*row+col] =abs(dstbuf[pitch*row+col]-srcbuf[pitch*row+col]); } if(savebmp(tempstr, dstbuf, w, h, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1) _throwbmp("saving bitmap"); } } bailout: if(file) {fclose(file); file=NULL;} if(handle) {tjDestroy(handle); handle=NULL;} if(dstbuf && dstbufalloc) {free(dstbuf); dstbuf=NULL;} return retval; }
int main(int argc, char *argv[]) { unsigned char *srcbuf=NULL; int w=0, h=0, i, j; int minqual=-1, maxqual=-1; char *temp; int minarg=2, retval=0, subsamp=-1; if((scalingfactors=tjGetScalingFactors(&nsf))==NULL || nsf==0) _throwtj("executing tjGetScalingFactors()"); if(argc<minarg) usage(argv[0]); temp=strrchr(argv[1], '.'); if(temp!=NULL) { if(!strcasecmp(temp, ".bmp")) ext="bmp"; if(!strcasecmp(temp, ".jpg") || !strcasecmp(temp, ".jpeg")) decomponly=1; } printf("\n"); if(!decomponly) { minarg=3; if(argc<minarg) usage(argv[0]); if((minqual=atoi(argv[2]))<1 || minqual>100) { puts("ERROR: Quality must be between 1 and 100."); exit(1); } if((temp=strchr(argv[2], '-'))!=NULL && strlen(temp)>1 && sscanf(&temp[1], "%d", &maxqual)==1 && maxqual>minqual && maxqual>=1 && maxqual<=100) {} else maxqual=minqual; } if(argc>minarg) { for(i=minarg; i<argc; i++) { if(!strcasecmp(argv[i], "-tile")) { dotile=1; xformopt|=TJXOPT_CROP; } if(!strcasecmp(argv[i], "-fastupsample")) { printf("Using fast upsampling code\n\n"); flags|=TJFLAG_FASTUPSAMPLE; } if(!strcasecmp(argv[i], "-fastdct")) { printf("Using fastest DCT/IDCT algorithm\n\n"); flags|=TJFLAG_FASTDCT; } if(!strcasecmp(argv[i], "-accuratedct")) { printf("Using most accurate DCT/IDCT algorithm\n\n"); flags|=TJFLAG_ACCURATEDCT; } if(!strcasecmp(argv[i], "-rgb")) pf=TJPF_RGB; if(!strcasecmp(argv[i], "-rgbx")) pf=TJPF_RGBX; if(!strcasecmp(argv[i], "-bgr")) pf=TJPF_BGR; if(!strcasecmp(argv[i], "-bgrx")) pf=TJPF_BGRX; if(!strcasecmp(argv[i], "-xbgr")) pf=TJPF_XBGR; if(!strcasecmp(argv[i], "-xrgb")) pf=TJPF_XRGB; if(!strcasecmp(argv[i], "-cmyk")) pf=TJPF_CMYK; if(!strcasecmp(argv[i], "-bottomup")) flags|=TJFLAG_BOTTOMUP; if(!strcasecmp(argv[i], "-quiet")) quiet=1; if(!strcasecmp(argv[i], "-qq")) quiet=2; if(!strcasecmp(argv[i], "-scale") && i<argc-1) { int temp1=0, temp2=0, match=0; if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)==2) { for(j=0; j<nsf; j++) { if((double)temp1/(double)temp2 == (double)scalingfactors[j].num/(double)scalingfactors[j].denom) { sf=scalingfactors[j]; match=1; break; } } if(!match) usage(argv[0]); } else usage(argv[0]); } if(!strcasecmp(argv[i], "-hflip")) xformop=TJXOP_HFLIP; if(!strcasecmp(argv[i], "-vflip")) xformop=TJXOP_VFLIP; if(!strcasecmp(argv[i], "-transpose")) xformop=TJXOP_TRANSPOSE; if(!strcasecmp(argv[i], "-transverse")) xformop=TJXOP_TRANSVERSE; if(!strcasecmp(argv[i], "-rot90")) xformop=TJXOP_ROT90; if(!strcasecmp(argv[i], "-rot180")) xformop=TJXOP_ROT180; if(!strcasecmp(argv[i], "-rot270")) xformop=TJXOP_ROT270; if(!strcasecmp(argv[i], "-grayscale")) xformopt|=TJXOPT_GRAY; if(!strcasecmp(argv[i], "-custom")) customFilter=dummyDCTFilter; if(!strcasecmp(argv[i], "-nooutput")) xformopt|=TJXOPT_NOOUTPUT; if(!strcasecmp(argv[i], "-benchtime") && i<argc-1) { double temp=atof(argv[++i]); if(temp>0.0) benchtime=temp; else usage(argv[0]); } if(!strcasecmp(argv[i], "-warmup") && i<argc-1) { int temp=atoi(argv[++i]); if(temp>=0) { warmup=temp; printf("Warmup runs = %d\n\n", warmup); } else usage(argv[0]); } if(!strcmp(argv[i], "-?")) usage(argv[0]); if(!strcasecmp(argv[i], "-alloc")) flags&=(~TJFLAG_NOREALLOC); if(!strcasecmp(argv[i], "-bmp")) ext="bmp"; if(!strcasecmp(argv[i], "-yuv")) { printf("Testing YUV planar encoding/decoding\n\n"); doyuv=1; } if(!strcasecmp(argv[i], "-yuvpad") && i<argc-1) { int temp=atoi(argv[++i]); if(temp>=1) yuvpad=temp; } if(!strcasecmp(argv[i], "-subsamp") && i<argc-1) { i++; if(toupper(argv[i][0])=='G') subsamp=TJSAMP_GRAY; else { int temp=atoi(argv[i]); switch(temp) { case 444: subsamp=TJSAMP_444; break; case 422: subsamp=TJSAMP_422; break; case 440: subsamp=TJSAMP_440; break; case 420: subsamp=TJSAMP_420; break; case 411: subsamp=TJSAMP_411; break; } } } if(!strcasecmp(argv[i], "-componly")) componly=1; } } if((sf.num!=1 || sf.denom!=1) && dotile) { printf("Disabling tiled compression/decompression tests, because those tests do not\n"); printf("work when scaled decompression is enabled.\n"); dotile=0; } if((flags&TJFLAG_NOREALLOC)==0 && dotile) { printf("Disabling tiled compression/decompression tests, because those tests do not\n"); printf("work when dynamic JPEG buffer allocation is enabled.\n\n"); dotile=0; } if(!decomponly) { if(loadbmp(argv[1], &srcbuf, &w, &h, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1) _throwbmp("loading bitmap"); temp=strrchr(argv[1], '.'); if(temp!=NULL) *temp='\0'; } if(quiet==1 && !decomponly) { printf("All performance values in Mpixels/sec\n\n"); printf("Bitmap JPEG JPEG %s %s ", dotile? "Tile ":"Image", dotile? "Tile ":"Image"); if(doyuv) printf("Encode "); printf("Comp Comp Decomp "); if(doyuv) printf("Decode"); printf("\n"); printf("Format Subsamp Qual Width Height "); if(doyuv) printf("Perf "); printf("Perf Ratio Perf "); if(doyuv) printf("Perf"); printf("\n\n"); } if(decomponly) { decompTest(argv[1]); printf("\n"); goto bailout; } if(subsamp>=0 && subsamp<TJ_NUMSAMP) { for(i=maxqual; i>=minqual; i--) fullTest(srcbuf, w, h, subsamp, i, argv[1]); printf("\n"); } else { if(pf!=TJPF_CMYK) { for(i=maxqual; i>=minqual; i--) fullTest(srcbuf, w, h, TJSAMP_GRAY, i, argv[1]); printf("\n"); } for(i=maxqual; i>=minqual; i--) fullTest(srcbuf, w, h, TJSAMP_420, i, argv[1]); printf("\n"); for(i=maxqual; i>=minqual; i--) fullTest(srcbuf, w, h, TJSAMP_422, i, argv[1]); printf("\n"); for(i=maxqual; i>=minqual; i--) fullTest(srcbuf, w, h, TJSAMP_444, i, argv[1]); printf("\n"); } bailout: if(srcbuf) free(srcbuf); return retval; }
int main(int argc, char *argv[]) { unsigned char *srcbuf=NULL; int w, h, i, j; int minqual=-1, maxqual=-1; char *temp; int minarg=2; int retval=0; if((scalingfactors=tjGetScalingFactors(&nsf))==NULL || nsf==0) _throwtj("executing tjGetScalingFactors()"); if(argc<minarg) usage(argv[0]); temp=strrchr(argv[1], '.'); if(temp!=NULL) { if(!strcasecmp(temp, ".bmp")) ext="bmp"; if(!strcasecmp(temp, ".jpg") || !strcasecmp(temp, ".jpeg")) decomponly=1; } printf("\n"); if(argc>minarg) { for(i=minarg; i<argc; i++) { if(!strcasecmp(argv[i], "-yuvencode")) { printf("Testing YUV planar encoding\n\n"); yuv=YUVENCODE; maxqual=minqual=100; } if(!strcasecmp(argv[i], "-yuvdecode")) { printf("Testing YUV planar decoding\n\n"); yuv=YUVDECODE; } } } if(!decomponly && yuv!=YUVENCODE) { minarg=3; if(argc<minarg) usage(argv[0]); if((minqual=atoi(argv[2]))<1 || minqual>100) { puts("ERROR: Quality must be between 1 and 100."); exit(1); } if((temp=strchr(argv[2], '-'))!=NULL && strlen(temp)>1 && sscanf(&temp[1], "%d", &maxqual)==1 && maxqual>minqual && maxqual>=1 && maxqual<=100) {} else maxqual=minqual; } if(argc>minarg) { for(i=minarg; i<argc; i++) { if(!strcasecmp(argv[i], "-tile")) { dotile=1; xformopt|=TJXOPT_CROP; } if(!strcasecmp(argv[i], "-forcesse3")) { printf("Forcing SSE3 code\n\n"); flags|=TJFLAG_FORCESSE3; } if(!strcasecmp(argv[i], "-forcesse2")) { printf("Forcing SSE2 code\n\n"); flags|=TJFLAG_FORCESSE2; } if(!strcasecmp(argv[i], "-forcesse")) { printf("Forcing SSE code\n\n"); flags|=TJFLAG_FORCESSE; } if(!strcasecmp(argv[i], "-forcemmx")) { printf("Forcing MMX code\n\n"); flags|=TJFLAG_FORCEMMX; } if(!strcasecmp(argv[i], "-fastupsample")) { printf("Using fast upsampling code\n\n"); flags|=TJFLAG_FASTUPSAMPLE; } if(!strcasecmp(argv[i], "-rgb")) pf=TJPF_RGB; if(!strcasecmp(argv[i], "-rgbx")) pf=TJPF_RGBX; if(!strcasecmp(argv[i], "-bgr")) pf=TJPF_BGR; if(!strcasecmp(argv[i], "-bgrx")) pf=TJPF_BGRX; if(!strcasecmp(argv[i], "-xbgr")) pf=TJPF_XBGR; if(!strcasecmp(argv[i], "-xrgb")) pf=TJPF_XRGB; if(!strcasecmp(argv[i], "-bottomup")) flags|=TJFLAG_BOTTOMUP; if(!strcasecmp(argv[i], "-quiet")) quiet=1; if(!strcasecmp(argv[i], "-qq")) quiet=2; if(!strcasecmp(argv[i], "-scale") && i<argc-1) { int temp1=0, temp2=0, match=0; if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)==2) { for(j=0; j<nsf; j++) { if(temp1==scalingfactors[j].num && temp2==scalingfactors[j].denom) { sf=scalingfactors[j]; match=1; break; } } if(!match) usage(argv[0]); } else usage(argv[0]); } if(!strcasecmp(argv[i], "-hflip")) xformop=TJXOP_HFLIP; if(!strcasecmp(argv[i], "-vflip")) xformop=TJXOP_VFLIP; if(!strcasecmp(argv[i], "-transpose")) xformop=TJXOP_TRANSPOSE; if(!strcasecmp(argv[i], "-transverse")) xformop=TJXOP_TRANSVERSE; if(!strcasecmp(argv[i], "-rot90")) xformop=TJXOP_ROT90; if(!strcasecmp(argv[i], "-rot180")) xformop=TJXOP_ROT180; if(!strcasecmp(argv[i], "-rot270")) xformop=TJXOP_ROT270; if(!strcasecmp(argv[i], "-grayscale")) xformopt|=TJXOPT_GRAY; if(!strcasecmp(argv[i], "-benchtime") && i<argc-1) { double temp=atof(argv[++i]); if(temp>0.0) benchtime=temp; else usage(argv[0]); } if(!strcmp(argv[i], "-?")) usage(argv[0]); if(!strcasecmp(argv[i], "-alloc")) flags&=(~TJFLAG_NOREALLOC); if(!strcasecmp(argv[i], "-bmp")) ext="bmp"; } } if((sf.num!=1 || sf.denom!=1) && dotile) { printf("Disabling tiled compression/decompression tests, because those tests do not\n"); printf("work when scaled decompression is enabled.\n"); dotile=0; } if(yuv && dotile) { printf("Disabling tiled compression/decompression tests, because those tests do not\n"); printf("work when YUV encoding or decoding is enabled.\n\n"); dotile=0; } if(!decomponly) { if(loadbmp(argv[1], &srcbuf, &w, &h, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1) _throwbmp("loading bitmap"); temp=strrchr(argv[1], '.'); if(temp!=NULL) *temp='\0'; } if(quiet==1 && !decomponly) { printf("All performance values in Mpixels/sec\n\n"); printf("Bitmap\tBitmap\tJPEG\tJPEG\t%s %s \tComp\tComp\tDecomp\n", dotile? "Tile ":"Image", dotile? "Tile ":"Image"); printf("Format\tOrder\tSubsamp\tQual\tWidth Height\tPerf \tRatio\tPerf\n\n"); } if(decomponly) { dodecomptest(argv[1]); printf("\n"); goto bailout; } for(i=maxqual; i>=minqual; i--) dotest(srcbuf, w, h, TJ_GRAYSCALE, i, argv[1]); printf("\n"); for(i=maxqual; i>=minqual; i--) dotest(srcbuf, w, h, TJ_420, i, argv[1]); printf("\n"); for(i=maxqual; i>=minqual; i--) dotest(srcbuf, w, h, TJ_422, i, argv[1]); printf("\n"); for(i=maxqual; i>=minqual; i--) dotest(srcbuf, w, h, TJ_444, i, argv[1]); printf("\n"); bailout: if(srcbuf) free(srcbuf); return retval; }
/* Decompression test */ int decomp(unsigned char *srcbuf, unsigned char **jpegbuf, unsigned long *jpegsize, unsigned char *dstbuf, int w, int h, int subsamp, int jpegqual, char *filename, int tilew, int tileh) { char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr; FILE *file=NULL; tjhandle handle=NULL; int row, col, iter=0, dstbufalloc=0, retval=0; double elapsed, elapsedDecode; int ps=tjPixelSize[pf]; int scaledw=TJSCALED(w, sf); int scaledh=TJSCALED(h, sf); int pitch=scaledw*ps; int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh; unsigned char *dstptr, *dstptr2, *yuvbuf=NULL; if(jpegqual>0) { snprintf(qualstr, 6, "_Q%d", jpegqual); qualstr[5]=0; } if((handle=tjInitDecompress())==NULL) _throwtj("executing tjInitDecompress()"); if(dstbuf==NULL) { if((dstbuf=(unsigned char *)malloc(pitch*scaledh))==NULL) _throwunix("allocating destination buffer"); dstbufalloc=1; } /* Set the destination buffer to gray so we know whether the decompressor attempted to write to it */ memset(dstbuf, 127, pitch*scaledh); if(doyuv) { int width=dotile? tilew:scaledw; int height=dotile? tileh:scaledh; int yuvsize=tjBufSizeYUV2(width, yuvpad, height, subsamp); if((yuvbuf=(unsigned char *)malloc(yuvsize))==NULL) _throwunix("allocating YUV buffer"); memset(yuvbuf, 127, yuvsize); } /* Benchmark */ iter=-warmup; elapsed=elapsedDecode=0.; while(1) { int tile=0; double start=gettime(); for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch*tileh) { for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, dstptr2+=ps*tilew) { int width=dotile? min(tilew, w-col*tilew):scaledw; int height=dotile? min(tileh, h-row*tileh):scaledh; if(doyuv) { double startDecode; if(tjDecompressToYUV2(handle, jpegbuf[tile], jpegsize[tile], yuvbuf, width, yuvpad, height, flags)==-1) _throwtj("executing tjDecompressToYUV2()"); startDecode=gettime(); if(tjDecodeYUV(handle, yuvbuf, yuvpad, subsamp, dstptr2, width, pitch, height, pf, flags)==-1) _throwtj("executing tjDecodeYUV()"); if(iter>=0) elapsedDecode+=gettime()-startDecode; } else if(tjDecompress2(handle, jpegbuf[tile], jpegsize[tile], dstptr2, width, pitch, height, pf, flags)==-1) _throwtj("executing tjDecompress2()"); } } iter++; if(iter>=1) { elapsed+=gettime()-start; if(elapsed>=benchtime) break; } } if(doyuv) elapsed-=elapsedDecode; if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); handle=NULL; if(quiet) { printf("%-6s%s", sigfig((double)(w*h)/1000000.*(double)iter/elapsed, 4, tempstr, 1024), quiet==2? "\n":" "); if(doyuv) printf("%s\n", sigfig((double)(w*h)/1000000.*(double)iter/elapsedDecode, 4, tempstr, 1024)); else if(quiet!=2) printf("\n"); } else { printf("%s --> Frame rate: %f fps\n", doyuv? "Decomp to YUV":"Decompress ", (double)iter/elapsed); printf(" Throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)iter/elapsed); if(doyuv) { printf("YUV Decode --> Frame rate: %f fps\n", (double)iter/elapsedDecode); printf(" Throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)iter/elapsedDecode); } } if(sf.num!=1 || sf.denom!=1) snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom); else if(tilew!=w || tileh!=h) snprintf(sizestr, 20, "%dx%d", tilew, tileh); else snprintf(sizestr, 20, "full"); if(decomponly) snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, ext); else snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subName[subsamp], qualstr, sizestr, ext); if(savebmp(tempstr, dstbuf, scaledw, scaledh, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1) _throwbmp("saving bitmap"); ptr=strrchr(tempstr, '.'); snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext); if(srcbuf && sf.num==1 && sf.denom==1) { if(!quiet) printf("Compression error written to %s.\n", tempstr); if(subsamp==TJ_GRAYSCALE) { int index, index2; for(row=0, index=0; row<h; row++, index+=pitch) { for(col=0, index2=index; col<w; col++, index2+=ps) { int rindex=index2+tjRedOffset[pf]; int gindex=index2+tjGreenOffset[pf]; int bindex=index2+tjBlueOffset[pf]; int y=(int)((double)srcbuf[rindex]*0.299 + (double)srcbuf[gindex]*0.587 + (double)srcbuf[bindex]*0.114 + 0.5); if(y>255) y=255; if(y<0) y=0; dstbuf[rindex]=abs(dstbuf[rindex]-y); dstbuf[gindex]=abs(dstbuf[gindex]-y); dstbuf[bindex]=abs(dstbuf[bindex]-y); } } } else { for(row=0; row<h; row++) for(col=0; col<w*ps; col++) dstbuf[pitch*row+col] =abs(dstbuf[pitch*row+col]-srcbuf[pitch*row+col]); } if(savebmp(tempstr, dstbuf, w, h, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1) _throwbmp("saving bitmap"); } bailout: if(file) fclose(file); if(handle) tjDestroy(handle); if(dstbuf && dstbufalloc) free(dstbuf); if(yuvbuf) free(yuvbuf); return retval; }