bool WriteJpeg( const char * destinationFile, const unsigned char * rgbxBuffer, int width, int height ) { tjhandle tj = tjInitCompress(); unsigned char * jpegBuf = NULL; unsigned long jpegSize = 0; const int r = tjCompress2( tj, ( unsigned char * )rgbxBuffer, // TJ isn't const correct... width, width * 4, height, TJPF_RGBX, &jpegBuf, &jpegSize, TJSAMP_444 /* TJSAMP_422 */, 90 /* jpegQual */, 0 /* flags */ ); if ( r != 0 ) { LOG_TJ( "tjCompress2 returned %s for %s", tjGetErrorStr(), destinationFile ); return false; } FILE * f = fopen( destinationFile, "wb" ); if ( f != NULL ) { fwrite( jpegBuf, jpegSize, 1, f ); fclose( f ); } else { LOG_TJ( "WriteJpeg failed to write to %s", destinationFile ); return false; } tjFree( jpegBuf ); tjDestroy( tj ); return true; }
JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIIIII_3BIII (JNIEnv *env, jobject obj, jintArray src, jint x, jint y, jint width, jint stride, jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual, jint flags) { tjhandle handle=0; unsigned long jpegSize=0; jsize arraySize=0, actualStride; unsigned char *srcBuf=NULL, *jpegBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 || stride<0) _throw("Invalid argument in compress()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throw("Mismatch between Java and C API"); if(tjPixelSize[pf]!=sizeof(jint)) _throw("Pixel format must be 32-bit when compressing from an integer buffer."); actualStride=(stride==0)? width:stride; arraySize=(y+height-1)*actualStride + x+width; if((*env)->GetArrayLength(env, src)<arraySize) _throw("Source buffer is not large enough"); jpegSize=tjBufSize(width, height, jpegSubsamp); if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize) _throw("Destination buffer is not large enough"); bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjCompress2(handle, &srcBuf[(y*actualStride + x)*sizeof(int)], width, stride*sizeof(jint), height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual, flags|TJFLAG_NOREALLOC)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); jpegBuf=srcBuf=NULL; _throw(tjGetErrorStr()); } bailout: if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return (jint)jpegSize; }
static Shared<Buffer> save_to_buffer(const LayoutT & layout, const Byte * input, int format, std::uint32_t quality) { std::size_t output_size = 0; Byte * output_data = NULL; //!< Memory is allocated by tjCompress2 if _jpegSize == 0 tjhandle compressor = tjInitCompress(); tjCompress2(compressor, input, static_cast<int>(layout.size[WIDTH]), static_cast<int>(layout.stride[0]), static_cast<int>(layout.size[HEIGHT]), TJPF_RGBX, &output_data, &output_size, TJSAMP_444, quality, TJFLAG_FASTDCT); tjDestroy(compressor); if (output_data) { return shared<ForeignBuffer<Byte, tjFree>>(output_data, output_size); } else { return nullptr; } }
JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII (JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual, jint flags) { tjhandle handle=0; unsigned long jpegSize=0; jsize arraySize=0; unsigned char *srcBuf=NULL, *jpegBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 || pitch<0) _throw("Invalid argument in compress()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throw("Mismatch between Java and C API"); arraySize=(pitch==0)? width*tjPixelSize[pf]*height:pitch*height; if((*env)->GetArrayLength(env, src)<arraySize) _throw("Source buffer is not large enough"); jpegSize=tjBufSize(width, height, jpegSubsamp); if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize) _throw("Destination buffer is not large enough"); bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjCompress2(handle, srcBuf, width, pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual, flags|TJFLAG_NOREALLOC)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); jpegBuf=srcBuf=NULL; _throw(tjGetErrorStr()); } bailout: if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return (jint)jpegSize; }
static jint TJCompressor_compress (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint x, jint y, jint width, jint pitch, jint height, jint pf, jbyteArray dst, jint jpegSubsamp, jint jpegQual, jint flags) { tjhandle handle=0; unsigned long jpegSize=0; jsize arraySize=0, actualPitch; unsigned char *srcBuf=NULL, *jpegBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 || pitch<0) _throwarg("Invalid argument in compress()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throwarg("Mismatch between Java and C API"); actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch; arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf]; if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize) _throwarg("Source buffer is not large enough"); jpegSize=tjBufSize(width, height, jpegSubsamp); if((*env)->GetArrayLength(env, dst)<(jsize)jpegSize) _throwarg("Destination buffer is not large enough"); bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(ProcessSystemProperties(env)<0) goto bailout; if(tjCompress2(handle, &srcBuf[y*actualPitch + x*tjPixelSize[pf]], width, pitch, height, pf, &jpegBuf, &jpegSize, jpegSubsamp, jpegQual, flags|TJFLAG_NOREALLOC)==-1) _throwtj(); bailout: if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, jpegBuf, 0); if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return (jint)jpegSize; }
void WriteJpeg( const char * fullName, const unsigned char * rgbxBuffer, int width, int height ) { tjhandle tj = tjInitCompress(); unsigned char * jpegBuf = NULL; unsigned long jpegSize = 0; const int r = tjCompress2( tj, ( unsigned char * )rgbxBuffer, // TJ isn't const correct... width, width * 4, height, TJPF_RGBX, &jpegBuf, &jpegSize, TJSAMP_444 /* TJSAMP_422 */, 90 /* jpegQual */, 0 /* flags */ ); if ( r != 0 ) { LOG( "tjCompress2 returned %s for %s", tjGetErrorStr(), fullName ); return; } MemBuffer toFile( jpegBuf, jpegSize ); toFile.WriteToFile( fullName ); tjFree( jpegBuf ); tjDestroy( tj ); }
QByteArray ImageJpegCompressor::computeJpeg(const ImageWrapper& sourceImage, const QRect& imageRegion) { // tjCompress API is incorrect and takes a non-const input buffer, even // though it does not modify it. It can "safely" be cast to non-const // pointer to comply to the incorrect API. unsigned char* tjSrcBuffer = (unsigned char*)sourceImage.data; tjSrcBuffer += imageRegion.y() * sourceImage.width * sourceImage.getBytesPerPixel(); tjSrcBuffer += imageRegion.x() * sourceImage.getBytesPerPixel(); const int tjWidth = imageRegion.width(); // assume imageBuffer isn't padded const int tjPitch = sourceImage.width * sourceImage.getBytesPerPixel(); const int tjHeight = imageRegion.height(); const int tjPixelFormat = getTurboJpegFormat(sourceImage.pixelFormat); unsigned char* tjJpegBuf = 0; unsigned long tjJpegSize = 0; const int tjJpegSubsamp = TJSAMP_444; const int tjJpegQual = sourceImage.compressionQuality; const int tjFlags = 0; // or: TJFLAG_BOTTOMUP int err = tjCompress2(_tjHandle, tjSrcBuffer, tjWidth, tjPitch, tjHeight, tjPixelFormat, &tjJpegBuf, &tjJpegSize, tjJpegSubsamp, tjJpegQual, tjFlags); if (err != 0) { std::cerr << "libjpeg-turbo image conversion failure" << std::endl; return QByteArray(); } // move the JPEG buffer to a byte array const QByteArray jpegData((char*)tjJpegBuf, tjJpegSize); // free the libjpeg-turbo allocated memory tjFree(tjJpegBuf); return jpegData; }
void BEJPEG::compress ( void ) { tjhandle jpeg_compressor = tjInitCompress(); if ( NULL != jpeg_compressor ) { unsigned long image_size = width * height * tjPixelSize[pixel_format]; std::vector<unsigned char> image ( image_size ); unsigned char * compressed_image = &image[0]; int error = tjCompress2 ( jpeg_compressor, &data[0], width, 0, height, pixel_format, &compressed_image, &image_size, chrominance_subsampling, compression_level, 0 ); tjDestroy ( jpeg_compressor ); // error = if ( 0 == error ) { image.resize ( image_size ); data = image; } else { throw BEPlugin_Exception ( kJPEGCompressionError, tjGetErrorStr() ); } } else { throw BEPlugin_Exception ( kJPEGInitCcompressorError, tjGetErrorStr() ); } }
{ #ifdef LIVRE_USE_LIBJPEGTURBO uint8_t* tjSrcBuffer = const_cast< uint8_t* >(rawData); const int32_t pixelFormat = TJPF_BGRA; const int32_t color_components = 4; // Color Depth const int32_t tjPitch = width * color_components; const int32_t tjPixelFormat = pixelFormat; uint8_t* tjJpegBuf = 0; const int32_t tjJpegSubsamp = TJSAMP_444; const int32_t tjJpegQual = 100; // Image Quality const int32_t tjFlags = TJXOP_ROT180; const int32_t success = tjCompress2( _compressor, tjSrcBuffer, width, tjPitch, height, tjPixelFormat, &tjJpegBuf, &dataSize, tjJpegSubsamp, tjJpegQual, tjFlags); if(success != 0) { LBERROR << "libjpeg-turbo image conversion failure" << std::endl; return 0; } return static_cast<uint8_t *>(tjJpegBuf); #else if( !_compressor ) // just to silence unused private field warning return nullptr; return nullptr; #endif }
void dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual, char *filename) { char tempstr[1024], tempstr2[80]; FILE *file=NULL; tjhandle handle=NULL; unsigned char **jpegbuf=NULL, *tmpbuf=NULL, *srcptr, *srcptr2; double start, elapsed; int totaljpegsize=0, row, col, i, tilew=w, tileh=h, retval=0; unsigned long *jpegsize=NULL; int ps=tjPixelSize[pf], ntilesw=1, ntilesh=1, pitch=w*ps; if(yuv==YUVENCODE) {dotestyuv(srcbuf, w, h, subsamp, filename); return;} if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL) _throwunix("allocating temporary image buffer"); if(!quiet) printf(">>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", pixFormatStr[pf], (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp], jpegqual); for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2) { if(tilew>w) tilew=w; if(tileh>h) tileh=h; ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) *ntilesw*ntilesh))==NULL) _throwunix("allocating JPEG tile array"); memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh); if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long) *ntilesw*ntilesh))==NULL) _throwunix("allocating JPEG size array"); memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh); if((flags&TJFLAG_NOREALLOC)!=0) for(i=0; i<ntilesw*ntilesh; i++) { if((jpegbuf[i]=(unsigned char *)malloc(tjBufSize(tilew, tileh, subsamp)))==NULL) _throwunix("allocating JPEG tiles"); } /* Compression test */ if(quiet==1) printf("%s\t%s\t%s\t%d\t", pixFormatStr[pf], (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp], jpegqual); for(i=0; i<h; i++) memcpy(&tmpbuf[pitch*i], &srcbuf[w*ps*i], w*ps); if((handle=tjInitCompress())==NULL) _throwtj("executing tjInitCompress()"); /* Execute once to preload cache */ if(tjCompress2(handle, srcbuf, tilew, pitch, tileh, pf, &jpegbuf[0], &jpegsize[0], subsamp, jpegqual, flags)==-1) _throwtj("executing tjCompress2()"); /* Benchmark */ for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++) { int tile=0; totaljpegsize=0; for(row=0, srcptr=srcbuf; row<ntilesh; row++, srcptr+=pitch*tileh) { for(col=0, srcptr2=srcptr; col<ntilesw; col++, tile++, srcptr2+=ps*tilew) { int width=min(tilew, w-col*tilew); int height=min(tileh, h-row*tileh); if(tjCompress2(handle, srcptr2, width, pitch, height, pf, &jpegbuf[tile], &jpegsize[tile], subsamp, jpegqual, flags)==-1) _throwtj("executing tjCompress()2"); totaljpegsize+=jpegsize[tile]; } } } if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); handle=NULL; if(quiet==1) printf("%-4d %-4d\t", tilew, tileh); if(quiet) { printf("%s%c%s%c", sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024), quiet==2? '\n':'\t', sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80), quiet==2? '\n':'\t'); } else { printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", tilew, tileh); printf("C--> Frame rate: %f fps\n", (double)i/elapsed); printf(" Output image size: %d bytes\n", totaljpegsize); printf(" Compression ratio: %f:1\n", (double)(w*h*ps)/(double)totaljpegsize); printf(" Source throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)i/elapsed); printf(" Output bit stream: %f Megabits/sec\n", (double)totaljpegsize*8./1000000.*(double)i/elapsed); } if(tilew==w && tileh==h) { snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, subName[subsamp], jpegqual); if((file=fopen(tempstr, "wb"))==NULL) _throwunix("opening reference image"); if(fwrite(jpegbuf[0], jpegsize[0], 1, file)!=1) _throwunix("writing reference image"); fclose(file); file=NULL; if(!quiet) printf("Reference image written to %s\n", tempstr); } /* Decompression test */ if(decomptest(srcbuf, jpegbuf, jpegsize, tmpbuf, w, h, subsamp, jpegqual, filename, tilew, tileh)==-1) goto bailout; for(i=0; i<ntilesw*ntilesh; i++) { if(jpegbuf[i]) free(jpegbuf[i]); jpegbuf[i]=NULL; } free(jpegbuf); jpegbuf=NULL; free(jpegsize); jpegsize=NULL; if(tilew==w && tileh==h) break; } bailout: if(file) {fclose(file); file=NULL;} if(jpegbuf) { for(i=0; i<ntilesw*ntilesh; i++) { if(jpegbuf[i]) free(jpegbuf[i]); jpegbuf[i]=NULL; } free(jpegbuf); jpegbuf=NULL; } if(jpegsize) {free(jpegsize); jpegsize=NULL;} if(tmpbuf) {free(tmpbuf); tmpbuf=NULL;} if(handle) {tjDestroy(handle); handle=NULL;} return; }
int fullTest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual, char *filename) { char tempstr[1024], tempstr2[80]; FILE *file=NULL; tjhandle handle=NULL; unsigned char **jpegbuf=NULL, *yuvbuf=NULL, *tmpbuf=NULL, *srcptr, *srcptr2; double start, elapsed, elapsedEncode; int totaljpegsize=0, row, col, i, tilew=w, tileh=h, retval=0; int iter, yuvsize=0; unsigned long *jpegsize=NULL; int ps=tjPixelSize[pf]; int ntilesw=1, ntilesh=1, pitch=w*ps; const char *pfStr=pixFormatStr[pf]; if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL) _throwunix("allocating temporary image buffer"); if(!quiet) printf(">>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", pfStr, (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp], jpegqual); for(tilew=dotile? 8:w, tileh=dotile? 8:h; ; tilew*=2, tileh*=2) { if(tilew>w) tilew=w; if(tileh>h) tileh=h; ntilesw=(w+tilew-1)/tilew; ntilesh=(h+tileh-1)/tileh; if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *) *ntilesw*ntilesh))==NULL) _throwunix("allocating JPEG tile array"); memset(jpegbuf, 0, sizeof(unsigned char *)*ntilesw*ntilesh); if((jpegsize=(unsigned long *)malloc(sizeof(unsigned long) *ntilesw*ntilesh))==NULL) _throwunix("allocating JPEG size array"); memset(jpegsize, 0, sizeof(unsigned long)*ntilesw*ntilesh); if((flags&TJFLAG_NOREALLOC)!=0) for(i=0; i<ntilesw*ntilesh; i++) { if((jpegbuf[i]=(unsigned char *)tjAlloc(tjBufSize(tilew, tileh, subsamp)))==NULL) _throwunix("allocating JPEG tiles"); } /* Compression test */ if(quiet==1) printf("%-4s (%s) %-5s %-3d ", pfStr, (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp], jpegqual); for(i=0; i<h; i++) memcpy(&tmpbuf[pitch*i], &srcbuf[w*ps*i], w*ps); if((handle=tjInitCompress())==NULL) _throwtj("executing tjInitCompress()"); if(doyuv) { yuvsize=tjBufSizeYUV2(tilew, yuvpad, tileh, subsamp); if((yuvbuf=(unsigned char *)malloc(yuvsize))==NULL) _throwunix("allocating YUV buffer"); memset(yuvbuf, 127, yuvsize); } /* Benchmark */ iter=-warmup; elapsed=elapsedEncode=0.; while(1) { int tile=0; totaljpegsize=0; start=gettime(); for(row=0, srcptr=srcbuf; row<ntilesh; row++, srcptr+=pitch*tileh) { for(col=0, srcptr2=srcptr; col<ntilesw; col++, tile++, srcptr2+=ps*tilew) { int width=min(tilew, w-col*tilew); int height=min(tileh, h-row*tileh); if(doyuv) { double startEncode=gettime(); if(tjEncodeYUV3(handle, srcptr2, width, pitch, height, pf, yuvbuf, yuvpad, subsamp, flags)==-1) _throwtj("executing tjEncodeYUV3()"); if(iter>=0) elapsedEncode+=gettime()-startEncode; if(tjCompressFromYUV(handle, yuvbuf, width, yuvpad, height, subsamp, &jpegbuf[tile], &jpegsize[tile], jpegqual, flags)==-1) _throwtj("executing tjCompressFromYUV()"); } else { if(tjCompress2(handle, srcptr2, width, pitch, height, pf, &jpegbuf[tile], &jpegsize[tile], subsamp, jpegqual, flags)==-1) _throwtj("executing tjCompress2()"); } totaljpegsize+=jpegsize[tile]; } } iter++; if(iter>=1) { elapsed+=gettime()-start; if(elapsed>=benchtime) break; } } if(doyuv) elapsed-=elapsedEncode; if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); handle=NULL; if(quiet==1) printf("%-5d %-5d ", tilew, tileh); if(quiet) { if(doyuv) printf("%-6s%s", sigfig((double)(w*h)/1000000.*(double)iter/elapsedEncode, 4, tempstr, 1024), quiet==2? "\n":" "); printf("%-6s%s", sigfig((double)(w*h)/1000000.*(double)iter/elapsed, 4, tempstr, 1024), quiet==2? "\n":" "); printf("%-6s%s", sigfig((double)(w*h*ps)/(double)totaljpegsize, 4, tempstr2, 80), quiet==2? "\n":" "); } else { printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", tilew, tileh); if(doyuv) { printf("Encode YUV --> Frame rate: %f fps\n", (double)iter/elapsedEncode); printf(" Output image size: %d bytes\n", yuvsize); printf(" Compression ratio: %f:1\n", (double)(w*h*ps)/(double)yuvsize); printf(" Throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)iter/elapsedEncode); printf(" Output bit stream: %f Megabits/sec\n", (double)yuvsize*8./1000000.*(double)iter/elapsedEncode); } printf("%s --> Frame rate: %f fps\n", doyuv? "Comp from YUV":"Compress ", (double)iter/elapsed); printf(" Output image size: %d bytes\n", totaljpegsize); printf(" Compression ratio: %f:1\n", (double)(w*h*ps)/(double)totaljpegsize); printf(" Throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)iter/elapsed); printf(" Output bit stream: %f Megabits/sec\n", (double)totaljpegsize*8./1000000.*(double)iter/elapsed); } if(tilew==w && tileh==h) { snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, subName[subsamp], jpegqual); if((file=fopen(tempstr, "wb"))==NULL) _throwunix("opening reference image"); if(fwrite(jpegbuf[0], jpegsize[0], 1, file)!=1) _throwunix("writing reference image"); fclose(file); file=NULL; if(!quiet) printf("Reference image written to %s\n", tempstr); } /* Decompression test */ if(!componly) { if(decomp(srcbuf, jpegbuf, jpegsize, tmpbuf, w, h, subsamp, jpegqual, filename, tilew, tileh)==-1) goto bailout; } for(i=0; i<ntilesw*ntilesh; i++) { if(jpegbuf[i]) tjFree(jpegbuf[i]); jpegbuf[i]=NULL; } free(jpegbuf); jpegbuf=NULL; free(jpegsize); jpegsize=NULL; if(doyuv) { free(yuvbuf); yuvbuf=NULL; } if(tilew==w && tileh==h) break; } bailout: if(file) {fclose(file); file=NULL;} if(jpegbuf) { for(i=0; i<ntilesw*ntilesh; i++) { if(jpegbuf[i]) tjFree(jpegbuf[i]); jpegbuf[i]=NULL; } free(jpegbuf); jpegbuf=NULL; } if(yuvbuf) {free(yuvbuf); yuvbuf=NULL;} if(jpegsize) {free(jpegsize); jpegsize=NULL;} if(tmpbuf) {free(tmpbuf); tmpbuf=NULL;} if(handle) {tjDestroy(handle); handle=NULL;} return retval; }