1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* The test functions in this file are derived from an example included in *
* the JPEG package by The Independent JPEG Group *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include "tproto.h"
/* Hack to prevent libjpeg from re-defining `boolean` in a way that clashes
* with windows.h. This MUST come before including jpeglib.h.
*/
#ifdef H4_HAVE_WIN32_API
#define HAVE_BOOLEAN
#endif
#include <jpeglib.h>
#define ABS(x) ((int)(x) < 0 ? (-x) : x)
/************************************************************************
Name: comp_using_jpeglib() - compresses a buffer using JPEG functions
Description:
This routine uses functions from the JPEG library directly to
compress the provided image buffer and writes the compressed image
to the specified file.
Return value:
The number of errors occurred in this routine.
*************************************************************************/
int
comp_using_jpeglib(const char *filename, /* file to write compressed data in */
long *file_offset, /* end offset of previous data and indicating where
to start writing data in this round */
int im_height, /* image's height */
int im_width, /* image's width */
int im_ncomps, /* image's number of components */
int quality, /* JPEG quality value */
uint8 *written_buffer) /* data to be compressed */
{
FILE *outfile; /* target file */
int row_stride; /* physical row width in image buffer */
/* JPEG object for JPEG compression parameters and pointers to working space
(which is allocated as needed by the JPEG library). */
struct jpeg_compress_struct cinfo;
/* This struct represents a JPEG error handler. It is declared separately
* because applications often want to supply a specialized error handler
* (see the second half of this file for an example). But here we just
* take the easy way out and use the standard error handler, which will
* print a message on stderr and call exit() if compression fails.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
struct jpeg_error_mgr jerr;
/* Initialize JPEG compression object */
/* We have to set up the error handler first, in case the initialization
* step fails. (Unlikely, but it could happen if you are out of memory.)
* This routine fills in the contents of struct jerr, and returns jerr's
* address which we place into the link field in cinfo.
*/
cinfo.err = jpeg_std_error(&jerr);
/* Initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);
/* Open the output file to write binary data */
if ((outfile = fopen(filename, "ab")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
exit(1);
}
/* Forward to the position to write data */
if (fseek(outfile, (off_t)*file_offset, SEEK_SET) == -1) {
fprintf(stderr, "can't seek offset %d\n", (int)*file_offset);
exit(1);
}
/* Specify output file */
jpeg_stdio_dest(&cinfo, outfile);
/* Set parameters for compression */
/* Supply a description of the input image.
* Four fields of the cinfo struct must be filled in:
*/
cinfo.image_width = im_width; /* image width and height, in pixels */
cinfo.image_height = im_height;
cinfo.input_components = im_ncomps; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
/* Set default compression parameters. At least cinfo.in_color_space must
be set before calling jpeg_set_defaults, since the defaults depend on the
source color space */
jpeg_set_defaults(&cinfo);
/* Set quality (quantization table) scaling */
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
/* Start compressor */
/* TRUE ensures that we will write a complete interchange-JPEG file.
* From JPEG: Pass TRUE unless you are very sure of what you're doing. */
jpeg_start_compress(&cinfo, TRUE);
row_stride = im_width * im_ncomps; /* JSAMPLEs per row in written_buffer */
/* While there are more scan line in the buffer */
while (cinfo.next_scanline < cinfo.image_height) {
/* jpeg_write_scanlines expects an array of pointers to scanlines.
* Here the array is only one element long, but you could pass
* more than one scanline at a time if that's more convenient.
*/
JSAMPROW row_pointer = &written_buffer[cinfo.next_scanline * row_stride];
(void)jpeg_write_scanlines(&cinfo, &row_pointer, 1);
}
/* Finish compression */
jpeg_finish_compress(&cinfo);
/* Get the current file offset to return */
*file_offset = ftell(outfile);
/* Close the file */
fclose(outfile);
/* Release JPEG compression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_compress(&cinfo);
return 0;
} /* comp_using_jpeglib */
/***************************************************************************
Name: decomp_using_jpeglib() - decompresses a buffer using JPEG functions
Description:
This routine uses functions from the JPEG library directly to
decompress the data read from the specified file and store the
uncompressed data in the provided buffer.
Return value:
The number of errors occurred in this routine.
****************************************************************************/
int
decomp_using_jpeglib(const char *filename, /* file to read compressed data from */
long file_offset, /* offset in the file to start reading */
int im_height, /* image's height */
int im_width, /* image's width */
int im_ncomps, /* image's number of components */
uint8 *read_buffer) /* buffer to store decompressed data */
{
/* This struct contains the JPEG decompression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
*/
struct jpeg_decompress_struct cinfo; /* JPEG compression info */
struct jpeg_error_mgr jerr_pub; /* JPEG error handler */
FILE *infile; /* source file */
JSAMPARRAY buffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
uint8 *local_buf = NULL, *ptr = NULL;
/* Open the output file to write binary data */
if ((infile = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
exit(1);
}
/* Forward to the specified position to write data */
if (fseek(infile, (off_t)file_offset, SEEK_SET) == -1) {
fprintf(stderr, "can't seek offset %d\n", (int)file_offset);
exit(1);
}
/* Allocate local buffer to hold read values until all reading is done
before copying into caller's buffer */
local_buf = malloc(im_height * im_width * im_ncomps * sizeof(uint8));
CHECK_ALLOC(local_buf, "local_buf", "decomp_using_jpeglib");
/* Set up the JPEG error routines */
cinfo.err = jpeg_std_error(&jerr_pub);
/* Initialize the JPEG decompression object. */
jpeg_create_decompress(&cinfo);
/* Specify input file */
jpeg_stdio_src(&cinfo, infile);
/* Read file parameters */
(void)jpeg_read_header(&cinfo, TRUE);
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
* See libjpeg.doc for more info.
*/
/* Start decompressor */
(void)jpeg_start_decompress(&cinfo);
/* the return value is ignored here since suspension is not possible
* with the stdio data source (from JPEG example) */
/* Number of values per row */
row_stride = cinfo.output_width * cinfo.output_components;
/* Make a one-row-high array to read a row of values, JSAMPLEs per row */
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
ptr = local_buf; /* index into the buffer */
/* Read each scanline until all are read */
while (cinfo.output_scanline < cinfo.output_height) {
/* jpeg_read_scanlines expects an array of pointers to scanlines. */
(void)jpeg_read_scanlines(&cinfo, buffer, 1);
/* Saved read line to the local buffer */
memcpy(ptr, buffer[0], row_stride);
ptr = ptr + row_stride;
}
/* Copying values from local buffer to caller's buffer after success */
memcpy(read_buffer, local_buf, im_height * im_width * im_ncomps);
free(local_buf);
/* Finish decompression */
(void)jpeg_finish_decompress(&cinfo);
/* Release JPEG decompression object */
jpeg_destroy_decompress(&cinfo);
/* Close the file */
fclose(infile);
return 0;
} /* decomp_using_jpeglib */
|