/*! * bbufferReadStdin() * * Input: &data (<return> binary data read in) * &nbytes (<return>) * Return: 0 if OK; 1 on error * * Notes: * (1) This can be used to capture data piped in from stdin. * For example, you can read an image from stdin into memory * using shell redirection, with one of these: * cat <imagefile> | readprog * readprog < <imagefile> * where readprog is: * bbufferReadStdin(&data, &nbytes); // l_uint8*, size_t * Pix *pix = pixReadMem(data, nbytes); */ l_int32 bbufferReadStdin(l_uint8 **pdata, size_t *pnbytes) { l_int32 navail, nadd, nread; BBUFFER *bb; PROCNAME("bbufferReadStdin"); if (!pdata) return ERROR_INT("&data not defined", procName, 1); if (!pnbytes) return ERROR_INT("&nbytes not defined", procName, 1); bb = bbufferCreate(NULL, 4096); while (1) { navail = bb->nalloc - bb->n; if (navail < 4096) { nadd = L_MAX(bb->nalloc, 4096); bbufferExtendArray(bb, nadd); } nread = fread((void *)(bb->array + bb->n), 1, 4096, stdin); bb->n += nread; if (nread != 4096) break; } *pdata = bb->array; *pnbytes = bb->n; bb->array = NULL; bbufferDestroy(&bb); return 0; }
/*! * \brief pixWriteMemGif() * * \param[out] pdata data of gif compressed image * \param[out] psize size of returned data * \param[in] pix * \return 0 if OK, 1 on error * * <pre> * Notes: * (1) See comments in pixReadMemGif() * (2) For Giflib version >= 5.1, this uses the EGifOpen() buffer * interface. No temp files are required. * </pre> */ l_int32 pixWriteMemGif(l_uint8 **pdata, size_t *psize, PIX *pix) { #if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5 int giferr; l_int32 result; GifFileType *gif; L_BBUFFER *buffer; #else char *fname; #endif /* 5.1 and beyond */ PROCNAME("pixWriteMemGif"); if (!pdata) return ERROR_INT("&data not defined", procName, 1 ); *pdata = NULL; if (!psize) return ERROR_INT("&size not defined", procName, 1 ); *psize = 0; if (!pix) return ERROR_INT("&pix not defined", procName, 1 ); #if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5 if((buffer = bbufferCreate(NULL, 0)) == NULL) { return ERROR_INT("failed to create buffer", procName, 1); } if ((gif = EGifOpen((void*)buffer, gifWriteFunc, NULL)) == NULL) { bbufferDestroy(&buffer); return ERROR_INT("failed to create GIF image handle", procName, 1); } result = pixToGif(pix, gif); EGifCloseFile(gif, &giferr); if(result == 0) { *pdata = bbufferDestroyAndSaveData(&buffer, psize); } else { bbufferDestroy(&buffer); } return result; #else L_INFO("writing to a temp file, not directly to memory\n", procName); /* Write to a temp file */ fname = l_makeTempFilename(NULL); pixWrite(fname, pix, IFF_GIF); /* Read back into memory */ *pdata = l_binaryRead(fname, psize); lept_rmfile(fname); LEPT_FREE(fname); return 0; #endif }
/*! * \brief pixWriteMemGif() * * \param[out] pdata data of gif compressed image * \param[out] psize size of returned data * \param[in] pix * \return 0 if OK, 1 on error * * <pre> * Notes: * (1) See comments in pixReadMemGif() * </pre> */ l_int32 pixWriteMemGif(l_uint8 **pdata, size_t *psize, PIX *pix) { int giferr; l_int32 result; GifFileType *gif; L_BBUFFER *buffer; PROCNAME("pixWriteMemGif"); /* 5.1+ and not 5.1.2 */ #if (GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0)) L_ERROR("Require giflib-5.1 or later\n", procName); return 1; #endif /* < 5.1 */ #if GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 1 && GIFLIB_RELEASE == 2 /* 5.1.2 */ L_ERROR("Can't use giflib-5.1.2; suggest 5.1.3 or later\n", procName); return 1; #endif /* 5.1.2 */ if (!pdata) return ERROR_INT("&data not defined", procName, 1 ); *pdata = NULL; if (!psize) return ERROR_INT("&size not defined", procName, 1 ); *psize = 0; if (!pix) return ERROR_INT("&pix not defined", procName, 1 ); if ((buffer = bbufferCreate(NULL, 0)) == NULL) return ERROR_INT("failed to create buffer", procName, 1); if ((gif = EGifOpen((void*)buffer, gifWriteFunc, NULL)) == NULL) { bbufferDestroy(&buffer); return ERROR_INT("failed to create GIF image handle", procName, 1); } result = pixToGif(pix, gif); EGifCloseFile(gif, &giferr); if (result == 0) { *pdata = bbufferDestroyAndSaveData(&buffer, psize); } else { bbufferDestroy(&buffer); } return result; }
/*! * zlibCompress() * * Input: datain (byte buffer with input data) * nin (number of bytes of input data) * &nout (<return> number of bytes of output data) * Return: dataout (compressed data), or null on error * * Notes: * (1) We repeatedly read in and fill up an input buffer, * compress the data, and read it back out. zlib * uses two byte buffers internally in the z_stream * data structure. We use the bbuffers to feed data * into the fixed bufferin, and feed it out of bufferout, * in the same way that a pair of streams would normally * be used if the data were being read from one file * and written to another. This is done iteratively, * compressing L_BUF_SIZE bytes of input data at a time. */ l_uint8 * zlibCompress(l_uint8 *datain, size_t nin, size_t *pnout) { l_uint8 *dataout; l_int32 status; l_int32 flush; size_t nbytes; l_uint8 *bufferin, *bufferout; BBUFFER *bbin, *bbout; z_stream z; PROCNAME("zlibCompress"); if (!datain) return (l_uint8 *)ERROR_PTR("datain not defined", procName, NULL); /* Set up fixed size buffers used in z_stream */ if ((bufferin = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL) return (l_uint8 *)ERROR_PTR("bufferin not made", procName, NULL); if ((bufferout = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL) return (l_uint8 *)ERROR_PTR("bufferout not made", procName, NULL); /* Set up bbuffers and load bbin with the data */ if ((bbin = bbufferCreate(datain, nin)) == NULL) return (l_uint8 *)ERROR_PTR("bbin not made", procName, NULL); if ((bbout = bbufferCreate(NULL, 0)) == NULL) return (l_uint8 *)ERROR_PTR("bbout not made", procName, NULL); z.zalloc = (alloc_func)0; z.zfree = (free_func)0; z.opaque = (voidpf)0; z.next_in = bufferin; z.avail_in = 0; z.next_out = bufferout; z.avail_out = L_BUF_SIZE; status = deflateInit(&z, ZLIB_COMPRESSION_LEVEL); if (status != Z_OK) return (l_uint8 *)ERROR_PTR("deflateInit failed", procName, NULL); do { if (z.avail_in == 0) { z.next_in = bufferin; bbufferWrite(bbin, bufferin, L_BUF_SIZE, &nbytes); #if DEBUG fprintf(stderr, " wrote %d bytes to bufferin\n", nbytes); #endif /* DEBUG */ z.avail_in = nbytes; } flush = (bbin->n) ? Z_SYNC_FLUSH : Z_FINISH; status = deflate(&z, flush); #if DEBUG fprintf(stderr, " status is %d, bytesleft = %d, totalout = %d\n", status, z.avail_out, z.total_out); #endif /* DEBUG */ nbytes = L_BUF_SIZE - z.avail_out; if (nbytes) { bbufferRead(bbout, bufferout, nbytes); #if DEBUG fprintf(stderr, " read %d bytes from bufferout\n", nbytes); #endif /* DEBUG */ } z.next_out = bufferout; z.avail_out = L_BUF_SIZE; } while (flush != Z_FINISH); deflateEnd(&z); bbufferDestroy(&bbin); dataout = bbufferDestroyAndSaveData(&bbout, pnout); FREE(bufferin); FREE(bufferout); return dataout; }
/*! * zlibUncompress() * * Input: datain (byte buffer with compressed input data) * nin (number of bytes of input data) * &nout (<return> number of bytes of output data) * Return: dataout (uncompressed data), or null on error * * Notes: * (1) See zlibCompress(). */ l_uint8 * zlibUncompress(l_uint8 *datain, size_t nin, size_t *pnout) { l_uint8 *dataout; l_uint8 *bufferin, *bufferout; l_int32 status; size_t nbytes; BBUFFER *bbin, *bbout; z_stream z; PROCNAME("zlibUncompress"); if (!datain) return (l_uint8 *)ERROR_PTR("datain not defined", procName, NULL); if ((bufferin = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL) return (l_uint8 *)ERROR_PTR("bufferin not made", procName, NULL); if ((bufferout = (l_uint8 *)CALLOC(L_BUF_SIZE, sizeof(l_uint8))) == NULL) return (l_uint8 *)ERROR_PTR("bufferout not made", procName, NULL); if ((bbin = bbufferCreate(datain, nin)) == NULL) return (l_uint8 *)ERROR_PTR("bbin not made", procName, NULL); if ((bbout = bbufferCreate(NULL, 0)) == NULL) return (l_uint8 *)ERROR_PTR("bbout not made", procName, NULL); z.zalloc = (alloc_func)0; z.zfree = (free_func)0; z.next_in = bufferin; z.avail_in = 0; z.next_out = bufferout; z.avail_out = L_BUF_SIZE; inflateInit(&z); for ( ; ; ) { if (z.avail_in == 0) { z.next_in = bufferin; bbufferWrite(bbin, bufferin, L_BUF_SIZE, &nbytes); /* fprintf(stderr, " wrote %d bytes to bufferin\n", nbytes); */ z.avail_in = nbytes; } if (z.avail_in == 0) break; status = inflate(&z, Z_SYNC_FLUSH); /* fprintf(stderr, " status is %d, bytesleft = %d, totalout = %d\n", status, z.avail_out, z.total_out); */ nbytes = L_BUF_SIZE - z.avail_out; if (nbytes) { bbufferRead(bbout, bufferout, nbytes); /* fprintf(stderr, " read %d bytes from bufferout\n", nbytes); */ } z.next_out = bufferout; z.avail_out = L_BUF_SIZE; } inflateEnd(&z); bbufferDestroy(&bbin); dataout = bbufferDestroyAndSaveData(&bbout, pnout); FREE(bufferin); FREE(bufferout); return dataout; }
main(int argc, char **argv) { char *filein, *fileout; l_uint8 *array1, *array2, *dataout, *dataout2; l_int32 i, blocksize; size_t nbytes, nout, nout2; BBUFFER *bb, *bb2; FILE *fp; static char mainName[] = "buffertest"; if (argc != 3) exit(ERROR_INT(" Syntax: buffertest filein fileout", mainName, 1)); filein = argv[1]; fileout = argv[2]; if ((array1 = l_binaryRead(filein, &nbytes)) == NULL) exit(ERROR_INT("array not made", mainName, 1)); fprintf(stderr, " Bytes read from file: %ld\n", nbytes); /* Application of byte buffer ops: compress/decompress in memory */ #if 1 dataout = zlibCompress(array1, nbytes, &nout); l_binaryWrite(fileout, "w", dataout, nout); dataout2 = zlibUncompress(dataout, nout, &nout2); l_binaryWrite("/tmp/junktest", "w", dataout2, nout2); fprintf(stderr, "nbytes in = %ld, nbytes comp = %ld, nbytes uncomp = %ld\n", nbytes, nout, nout2); lept_free(dataout); lept_free(dataout2); #endif /* Low-level byte buffer read/write test */ #if 0 bb = bbufferCreate(array1, nbytes); bbufferRead(bb, array1, nbytes); array2 = (l_uint8 *)lept_calloc(2 * nbytes, sizeof(l_uint8)); fprintf(stderr, " Bytes initially in buffer: %d\n", bb->n); blocksize = (2 * nbytes) / NBLOCKS; for (i = 0; i <= NBLOCKS; i++) { bbufferWrite(bb, array2, blocksize, &nout); fprintf(stderr, " block %d: wrote %d bytes\n", i + 1, nout); } fprintf(stderr, " Bytes left in buffer: %d\n", bb->n); bb2 = bbufferCreate(NULL, 0); bbufferRead(bb2, array1, nbytes); fp = lept_fopen(fileout, "wb"); bbufferWriteStream(bb2, fp, nbytes, &nout); fprintf(stderr, " bytes written out to fileout: %d\n", nout); bbufferDestroy(&bb); bbufferDestroy(&bb2); lept_free(array2); #endif lept_free(array1); return 0; }