File: tusejpegfuncs.c

package info (click to toggle)
libhdf4 4.3.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 30,288 kB
  • sloc: ansic: 128,699; sh: 15,015; fortran: 12,444; java: 5,863; xml: 1,205; makefile: 790; yacc: 678; pascal: 418; perl: 360; javascript: 203; lex: 163; csh: 41
file content (235 lines) | stat: -rw-r--r-- 9,572 bytes parent folder | download | duplicates (4)
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 */