Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/sdcte.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* DCT encoding filter stream */
18
#include "memory_.h"
19
#include "stdio_.h"
20
#include "jpeglib_.h"
21
#include "jerror_.h"
22
#include "gdebug.h"
23
#include "gsmemory.h"
24
#include "strimpl.h"
25
#include "sdct.h"
26
#include "sjpeg.h"
27
28
0
#define ICC_OVERHEAD  16
29
0
#define MAX_MARKER_DATA_SIZE  (65535 - ICC_OVERHEAD)
30
31
public_st_jpeg_compress_data();
32
33
/* ------ DCTEncode ------ */
34
35
/* JPEG destination manager procedures */
36
static void
37
dcte_init_destination(j_compress_ptr cinfo)
38
877
{
39
877
}
40
static boolean
41
dcte_empty_output_buffer(j_compress_ptr cinfo)
42
2.66k
{
43
2.66k
    return FALSE;
44
2.66k
}
45
static void
46
dcte_term_destination(j_compress_ptr cinfo)
47
867
{
48
867
}
49
50
/* Set the defaults for the DCTEncode filter. */
51
static void
52
s_DCTE_set_defaults(stream_state * st)
53
378k
{
54
378k
    stream_DCT_state *const ss = (stream_DCT_state *) st;
55
56
378k
    s_DCT_set_defaults(st);
57
378k
    ss->QFactor = 1.0;
58
378k
    ss->ColorTransform = -1;
59
378k
    ss->Markers.data = 0;
60
378k
    ss->Markers.size = 0;
61
378k
    ss->NoMarker = true;
62
378k
}
63
64
/* Initialize DCTEncode filter */
65
static int
66
s_DCTE_init(stream_state * st)
67
877
{
68
877
    stream_DCT_state *const ss = (stream_DCT_state *) st;
69
877
    struct jpeg_destination_mgr *dest = &ss->data.compress->destination;
70
71
877
    dest->init_destination = dcte_init_destination;
72
877
    dest->empty_output_buffer = dcte_empty_output_buffer;
73
877
    dest->term_destination = dcte_term_destination;
74
877
    ss->data.common->memory = ss->jpeg_memory;
75
877
    ss->data.compress->cinfo.dest = dest;
76
877
    ss->phase = 0;
77
877
    ss->icc_marker = 0;
78
877
    ss->icc_position = -1;
79
877
    return 0;
80
877
}
81
82
/* Process a buffer */
83
static int
84
s_DCTE_process(stream_state * st, stream_cursor_read * pr,
85
               stream_cursor_write * pw, bool last)
86
68.3k
{
87
68.3k
    stream_DCT_state *const ss = (stream_DCT_state *) st;
88
68.3k
    jpeg_compress_data *jcdp = ss->data.compress;
89
68.3k
    struct jpeg_destination_mgr *dest = jcdp->cinfo.dest;
90
91
68.3k
    if_debug2m('w', st->memory, "[wde]process avail=%u, last=%d\n",
92
68.3k
               (uint) (pr->limit - pr->ptr), last);
93
68.3k
    dest->next_output_byte = pw->ptr + 1;
94
68.3k
    dest->free_in_buffer = pw->limit - pw->ptr;
95
68.3k
    switch (ss->phase) {
96
877
        case 0:   /* not initialized yet */
97
877
            if (gs_jpeg_start_compress(ss, TRUE) < 0)
98
0
                return ERRC;
99
877
            if_debug4m('w', st->memory, "[wde]width=%u, height=%u, components=%d, scan_line_size=%u\n",
100
877
                       jcdp->cinfo.image_width,
101
877
                       jcdp->cinfo.image_height,
102
877
                       jcdp->cinfo.input_components,
103
877
                       ss->scan_line_size);
104
877
            pw->ptr = dest->next_output_byte - 1;
105
877
            ss->phase = 1;
106
            /* falls through */
107
877
        case 1:   /* initialized, Markers not written */
108
877
            if (pw->limit - pw->ptr < ss->Markers.size)
109
0
                return 1;
110
877
            memcpy(pw->ptr + 1, ss->Markers.data, ss->Markers.size);
111
877
            pw->ptr += ss->Markers.size;
112
877
            ss->phase = 2;
113
            /* falls through */
114
877
        case 2:   /* still need to write Adobe marker */
115
877
            if (!ss->NoMarker) {
116
877
                static const byte Adobe[] =
117
877
                {
118
877
                    0xFF, JPEG_APP0 + 14, 0, 14, /* parameter length */
119
877
                    'A', 'd', 'o', 'b', 'e',
120
877
                    0, 100, /* Version */
121
877
                    0, 0, /* Flags0 */
122
877
                    0, 0, /* Flags1 */
123
877
                    0   /* ColorTransform */
124
877
                };
125
126
2.63k
#define ADOBE_MARKER_LEN sizeof(Adobe)
127
877
                if (pw->limit - pw->ptr < ADOBE_MARKER_LEN)
128
0
                    return 1;
129
877
                memcpy(pw->ptr + 1, Adobe, ADOBE_MARKER_LEN);
130
877
                pw->ptr += ADOBE_MARKER_LEN;
131
877
                *pw->ptr = ss->ColorTransform;
132
877
#undef ADOBE_MARKER_LEN
133
877
            }
134
877
            dest->next_output_byte = pw->ptr + 1;
135
877
            dest->free_in_buffer = pw->limit - pw->ptr;
136
877
            ss->phase = 3;
137
            /* falls through */
138
877
        case  3:
139
            /* If we have it, then write out the ICC profile */
140
            /* Due to size limitations allowed in APP0 markers, the profile
141
               may have to be written in mutiple markers */
142
877
          if (ss->icc_profile != NULL) {
143
0
            static const char marker[2] = {0xFF, 0xE2};  /* JPEG_APP0 + 2 */
144
0
                byte num_mark;
145
146
                /* Number of markers */
147
0
                num_mark = ss->icc_profile->buffer_size / MAX_MARKER_DATA_SIZE;
148
0
                if (num_mark * MAX_MARKER_DATA_SIZE < ss->icc_profile->buffer_size) {
149
0
                    num_mark++;
150
0
                }
151
0
            while (ss->icc_marker < num_mark) {
152
0
                ulong offset = ss->icc_marker * MAX_MARKER_DATA_SIZE;
153
0
                ulong size;
154
155
0
                    size = ss->icc_profile->buffer_size - offset;
156
0
                    if (size > MAX_MARKER_DATA_SIZE)
157
0
                      size = MAX_MARKER_DATA_SIZE;
158
159
                    /* In this case we are just getting started with the
160
                       header of the marker.  Write that portion out */
161
0
                if (ss->icc_position == -1) {
162
0
                  byte length_byte[2];
163
0
                  byte curr_mark = ss->icc_marker + 1;
164
0
                  ulong total_length;
165
166
0
                  if ((uint) (pw->limit - pw->ptr) < (sizeof(marker) + ICC_OVERHEAD))
167
0
                        return 1;
168
0
                  total_length = size + ICC_OVERHEAD;
169
0
                  memcpy(pw->ptr + 1, marker, sizeof(marker));
170
0
                  length_byte[0] = total_length >> 8;
171
0
                  length_byte[1] = total_length & 0xFF;
172
0
                  memcpy(pw->ptr + 3, length_byte, sizeof(length_byte));
173
0
                  memcpy(pw->ptr + 5, "ICC_PROFILE", 12); /* Null included */
174
0
                  memcpy(pw->ptr + 17, &curr_mark, 1);
175
0
                  memcpy(pw->ptr + 18, &num_mark, 1);
176
0
                  pw->ptr += sizeof(marker) + ICC_OVERHEAD;
177
0
                  ss->icc_position = 0;
178
0
                }
179
                    /* Now write out the actual profile data */
180
0
                while (ss->icc_position < size) {
181
0
                  ulong avail_bytes, num_bytes;
182
183
0
                  avail_bytes = (ulong) (pw->limit - pw->ptr);
184
0
                  if (avail_bytes == 0)
185
0
                      return 1;
186
0
                  num_bytes = (size - ss->icc_position);
187
0
                  if (num_bytes > avail_bytes)
188
0
                      num_bytes = avail_bytes;
189
0
                  memcpy(pw->ptr + 1,  ss->icc_profile->buffer + offset + ss->icc_position, num_bytes);
190
0
                  ss->icc_position += num_bytes;
191
0
                  pw->ptr += num_bytes;
192
0
                }
193
                    /* Move on to the next marker */
194
0
                ++ss->icc_marker;
195
0
                ss->icc_position = -1;
196
0
            }
197
0
              dest->next_output_byte = pw->ptr + 1;
198
0
              dest->free_in_buffer = pw->limit - pw->ptr;
199
0
          }
200
877
          ss->phase = 4;
201
          /* falls through */
202
68.3k
        case 4:   /* markers written, processing data */
203
208k
            while (jcdp->cinfo.image_height > jcdp->cinfo.next_scanline) {
204
207k
                int written;
205
206
                /*
207
                 * The data argument for jpeg_write_scanlines is
208
                 * declared as a JSAMPARRAY.  There is no corresponding
209
                 * const type, so we must remove const from the
210
                 * argument that we are passing here.  (Tom Lane of IJG
211
                 * judges that providing const analogues of the
212
                 * interface types wouldn't be worth the trouble.)
213
                 */
214
207k
                /*const */ byte *samples = (byte *) (pr->ptr + 1);
215
216
207k
                if_debug1m('w', st->memory, "[wde]next_scanline=%u\n",
217
207k
                           jcdp->cinfo.next_scanline);
218
207k
                if ((uint) (pr->limit - pr->ptr) < ss->scan_line_size) {
219
64.8k
                    if (last)
220
10
                        return ERRC;  /* premature EOD */
221
64.8k
                    return 0; /* need more data */
222
64.8k
                }
223
142k
                written = gs_jpeg_write_scanlines(ss, &samples, 1);
224
142k
                if (written < 0)
225
0
                    return ERRC;
226
142k
                if_debug3m('w', st->memory, "[wde]write returns %d, used=%u, written=%u\n",
227
142k
                           written,
228
142k
                           (uint) (samples - 1 - pr->ptr),
229
142k
                           (uint) (dest->next_output_byte - 1 - pw->ptr));
230
142k
                pw->ptr = dest->next_output_byte - 1;
231
142k
                if (!written)
232
2.66k
                    return 1;  /* output full */
233
139k
                pr->ptr += ss->scan_line_size;
234
139k
            }
235
867
            ss->phase = 5;
236
            /* falls through */
237
867
        case 5:   /* all data processed, finishing */
238
            /* jpeg_finish_compress can't suspend, so write its output
239
             * to a fixed-size internal buffer.
240
             */
241
867
            dest->next_output_byte = jcdp->finish_compress_buf;
242
867
            dest->free_in_buffer = sizeof(jcdp->finish_compress_buf);
243
867
            if (gs_jpeg_finish_compress(ss) < 0)
244
0
                return ERRC;
245
867
            jcdp->fcb_size =
246
867
                dest->next_output_byte - jcdp->finish_compress_buf;
247
867
            jcdp->fcb_pos = 0;
248
867
            ss->phase = 6;
249
            /* falls through */
250
867
        case 6:   /* copy the final data to the output */
251
867
            if (jcdp->fcb_pos < jcdp->fcb_size) {
252
867
                int count = min(jcdp->fcb_size - jcdp->fcb_pos,
253
867
                                pw->limit - pw->ptr);
254
255
867
                if_debug1m('w', st->memory, "[wde]copying final %d\n", count);
256
867
                memcpy(pw->ptr + 1, jcdp->finish_compress_buf + jcdp->fcb_pos,
257
867
                       count);
258
867
                jcdp->fcb_pos += count;
259
867
                pw->ptr += count;
260
867
                if (jcdp->fcb_pos < jcdp->fcb_size)
261
0
                    return 1;
262
867
            }
263
867
            return EOFC;
264
68.3k
    }
265
    /* Default case can't happen.... */
266
0
    return ERRC;
267
68.3k
}
268
269
/* Stream template */
270
const stream_template s_DCTE_template =
271
{&st_DCT_state, s_DCTE_init, s_DCTE_process, 1000, 4000, NULL,
272
 s_DCTE_set_defaults
273
};