Coverage Report

Created: 2019-07-03 22:50

/home/liu/buildslave/linux-x64-runtests/build/lib/io/_ccv_io_libjpeg.inc
Line
Count
Source (jump to first uncovered line)
1
#include <setjmp.h>
2
3
typedef struct ccv_jpeg_error_mgr_t
4
{
5
  struct jpeg_error_mgr pub;
6
  jmp_buf setjmp_buffer;
7
} ccv_jpeg_error_mgr_t;
8
9
METHODDEF(void) error_exit(j_common_ptr cinfo)
10
0
{
11
0
  ccv_jpeg_error_mgr_t* err_mgr = (ccv_jpeg_error_mgr_t*)(cinfo->err);
12
0
13
0
  /* Return control to the setjmp point */
14
0
  longjmp(err_mgr->setjmp_buffer, 1);
15
0
}
16
17
/***************************************************************************
18
 * following code is for supporting MJPEG image files
19
 * based on a message of Laurent Pinchart on the video4linux mailing list
20
 ***************************************************************************/
21
22
/* JPEG DHT Segment for YCrCb omitted from MJPEG data */
23
static
24
unsigned char _ccv_jpeg_odml_dht[0x1a4] = {
25
  0xff, 0xc4, 0x01, 0xa2,
26
27
  0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
28
  0x00, 0x00, 0x00, 0x00, 0x00,
29
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
30
31
  0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
32
  0x00, 0x00, 0x00, 0x00, 0x00,
33
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
34
35
  0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
36
  0x04, 0x00, 0x00, 0x01, 0x7d,
37
  0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
38
  0x13, 0x51, 0x61, 0x07,
39
  0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1,
40
  0x15, 0x52, 0xd1, 0xf0,
41
  0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a,
42
  0x25, 0x26, 0x27, 0x28,
43
  0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
44
  0x46, 0x47, 0x48, 0x49,
45
  0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65,
46
  0x66, 0x67, 0x68, 0x69,
47
  0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85,
48
  0x86, 0x87, 0x88, 0x89,
49
  0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3,
50
  0xa4, 0xa5, 0xa6, 0xa7,
51
  0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
52
  0xc2, 0xc3, 0xc4, 0xc5,
53
  0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
54
  0xd9, 0xda, 0xe1, 0xe2,
55
  0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4,
56
  0xf5, 0xf6, 0xf7, 0xf8,
57
  0xf9, 0xfa,
58
59
  0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
60
  0x04, 0x00, 0x01, 0x02, 0x77,
61
  0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
62
  0x51, 0x07, 0x61, 0x71,
63
  0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09,
64
  0x23, 0x33, 0x52, 0xf0,
65
  0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17,
66
  0x18, 0x19, 0x1a, 0x26,
67
  0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
68
  0x45, 0x46, 0x47, 0x48,
69
  0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
70
  0x65, 0x66, 0x67, 0x68,
71
  0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
72
  0x84, 0x85, 0x86, 0x87,
73
  0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a,
74
  0xa2, 0xa3, 0xa4, 0xa5,
75
  0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
76
  0xb9, 0xba, 0xc2, 0xc3,
77
  0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
78
  0xd7, 0xd8, 0xd9, 0xda,
79
  0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
80
  0xf5, 0xf6, 0xf7, 0xf8,
81
  0xf9, 0xfa
82
};
83
84
/*
85
 * Parse the DHT table.
86
 * This code comes from jpeg6b (jdmarker.c).
87
 */
88
static int _ccv_jpeg_load_dht(struct jpeg_decompress_struct *info, unsigned char *dht, JHUFF_TBL *ac_tables[], JHUFF_TBL *dc_tables[])
89
0
{
90
0
  unsigned int length = (dht[2] << 8) + dht[3] - 2;
91
0
  unsigned int pos = 4;
92
0
  unsigned int count, i;
93
0
  int index;
94
0
95
0
  JHUFF_TBL **hufftbl;
96
0
  unsigned char bits[17];
97
0
  unsigned char huffval[256];
98
0
99
0
  while (length > 16)
100
0
  {
101
0
    bits[0] = 0;
102
0
    index = dht[pos++];
103
0
    count = 0;
104
0
    for (i = 1; i <= 16; ++i)
105
0
    {
106
0
      bits[i] = dht[pos++];
107
0
      count += bits[i];
108
0
    }
109
0
    length -= 17;
110
0
111
0
    if (count > 256 || count > length)
112
0
      return -1;
113
0
114
0
    for (i = 0; i < count; ++i)
115
0
      huffval[i] = dht[pos++];
116
0
    length -= count;
117
0
118
0
    if (index & 0x10)
119
0
    {
120
0
      index -= 0x10;
121
0
      hufftbl = &ac_tables[index];
122
0
    }
123
0
    else
124
0
      hufftbl = &dc_tables[index];
125
0
126
0
    if (index < 0 || index >= NUM_HUFF_TBLS)
127
0
      return -1;
128
0
129
0
    if (*hufftbl == 0)
130
0
      *hufftbl = jpeg_alloc_huff_table ((j_common_ptr)info);
131
0
    if (*hufftbl == 0)
132
0
      return -1;
133
0
134
0
    memcpy((*hufftbl)->bits, bits, sizeof (*hufftbl)->bits);
135
0
    memcpy((*hufftbl)->huffval, huffval, sizeof (*hufftbl)->huffval);
136
0
  }
137
0
138
0
  if (length != 0)
139
0
    return -1;
140
0
141
0
  return 0;
142
0
}
143
144
/***************************************************************************
145
 * end of code for supportting MJPEG image files
146
 * based on a message of Laurent Pinchart on the video4linux mailing list
147
 ***************************************************************************/
148
149
static void _ccv_read_jpeg_fd(FILE* in, ccv_dense_matrix_t** x, int type)
150
2
{
151
2
  struct jpeg_decompress_struct cinfo;
152
2
  struct ccv_jpeg_error_mgr_t jerr;
153
2
  JSAMPARRAY buffer;
154
2
  int row_stride;
155
2
  cinfo.err = jpeg_std_error(&jerr.pub);
156
2
  jerr.pub.error_exit = error_exit;
157
2
  if (setjmp(jerr.setjmp_buffer))
158
2
  {
159
0
    jpeg_destroy_decompress(&cinfo);
160
0
    return;
161
0
  }
162
2
  jpeg_create_decompress(&cinfo);
163
2
164
2
  jpeg_stdio_src(&cinfo, in);
165
2
166
2
  jpeg_read_header(&cinfo, TRUE);
167
2
  
168
2
  ccv_dense_matrix_t* im = *x;
169
2
  if (im == 0)
170
2
    *x = im = ccv_dense_matrix_new(cinfo.image_height, cinfo.image_width, (type) ? 
type0
: CCV_8U | ((cinfo.num_components > 1) ? CCV_C3 :
CCV_C10
), 0, 0);
171
2
172
2
  /* yes, this is a mjpeg image format, so load the correct huffman table */
173
2
  if (cinfo.ac_huff_tbl_ptrs[0] == 0 && 
cinfo.ac_huff_tbl_ptrs[1] == 00
&&
cinfo.dc_huff_tbl_ptrs[0] == 00
&&
cinfo.dc_huff_tbl_ptrs[1] == 00
)
174
0
    _ccv_jpeg_load_dht(&cinfo, _ccv_jpeg_odml_dht, cinfo.ac_huff_tbl_ptrs, cinfo.dc_huff_tbl_ptrs);
175
2
176
2
  if(cinfo.num_components != 4)
177
0
  {
178
0
    if (cinfo.num_components > 1)
179
0
    {
180
0
      cinfo.out_color_space = JCS_RGB;
181
0
      cinfo.out_color_components = 3;
182
0
    } else {
183
0
      cinfo.out_color_space = JCS_GRAYSCALE;
184
0
      cinfo.out_color_components = 1;
185
0
    }
186
2
  } else {
187
2
    cinfo.out_color_space = JCS_CMYK;
188
2
    cinfo.out_color_components = 4;
189
2
  }
190
2
191
2
  jpeg_start_decompress(&cinfo);
192
2
  row_stride = cinfo.output_width * 4;
193
2
  buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
194
2
195
2
  unsigned char* ptr = im->data.u8;
196
2
  int i;
197
2
  int ch = CCV_GET_CHANNEL(im->type);
198
2
  if(cinfo.num_components != 4)
199
0
  {
200
0
    if ((cinfo.num_components > 1 && ch == CCV_C3) || (cinfo.num_components == 1 && ch == CCV_C1))
201
0
    {
202
0
      /* no format coversion, direct copy */
203
0
      if (im->cols * ch < im->step)
204
0
      {
205
0
        size_t extra = im->step - im->cols * ch;
206
0
        // empty the padding
207
0
        while (cinfo.output_scanline < cinfo.output_height)
208
0
        {
209
0
          jpeg_read_scanlines(&cinfo, buffer, 1);
210
0
          memcpy(ptr, buffer[0], im->step);
211
0
          memset(ptr + im->cols * ch, 0, extra);
212
0
          ptr += im->step;
213
0
        }
214
0
      } else {
215
0
        while (cinfo.output_scanline < cinfo.output_height)
216
0
        {
217
0
          jpeg_read_scanlines(&cinfo, buffer, 1);
218
0
          memcpy(ptr, buffer[0], im->step);
219
0
          ptr += im->step;
220
0
        }
221
0
      }
222
0
    } else {
223
0
      if (cinfo.num_components > 1 && CCV_GET_CHANNEL(im->type) == CCV_C1)
224
0
      {
225
0
        /* RGB to gray */
226
0
        while (cinfo.output_scanline < cinfo.output_height)
227
0
        {
228
0
          jpeg_read_scanlines(&cinfo, buffer, 1);
229
0
          unsigned char* g = ptr;
230
0
          unsigned char* rgb = (unsigned char*)buffer[0];
231
0
          for(i = 0; i < im->cols; i++, rgb += 3, g++)
232
0
            *g = (unsigned char)((rgb[0] * 6969 + rgb[1] * 23434 + rgb[2] * 2365) >> 15);
233
0
          ptr += im->step;
234
0
        }
235
0
      } else if (cinfo.num_components == 1 && CCV_GET_CHANNEL(im->type) == CCV_C3) {
236
0
        /* gray to RGB */
237
0
        while (cinfo.output_scanline < cinfo.output_height)
238
0
        {
239
0
          jpeg_read_scanlines(&cinfo, buffer, 1);
240
0
          unsigned char* g = (unsigned char*)buffer[0];
241
0
          unsigned char* rgb = ptr;
242
0
          for(i = 0; i < im->cols; i++, rgb += 3, g++)
243
0
            rgb[0] = rgb[1] = rgb[2] = *g;
244
0
          ptr += im->step;
245
0
        }
246
0
      }
247
0
      // empty out the padding
248
0
      if (im->cols * ch < im->step)
249
0
      {
250
0
        size_t extra = im->step - im->cols * ch;
251
0
        unsigned char* ptr = im->data.u8 + im->cols * ch;
252
0
        for (i = 0; i < im->rows; i++, ptr += im->step)
253
0
          memset(ptr, 0, extra);
254
0
      }
255
0
    }
256
2
  } else {
257
2
    if (CCV_GET_CHANNEL(im->type) == CCV_C1)
258
0
    {
259
0
      /* CMYK to gray */
260
0
      while (cinfo.output_scanline < cinfo.output_height)
261
0
      {
262
0
        jpeg_read_scanlines(&cinfo, buffer, 1);
263
0
        unsigned char* cmyk = (unsigned char*)buffer[0];
264
0
        unsigned char* g = ptr;
265
0
        for(i = 0; i < im->cols; i++, g++, cmyk += 4)
266
0
        {
267
0
          int c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
268
0
          c = k - ((255 - c) * k >> 8);
269
0
          m = k - ((255 - m) * k >> 8);
270
0
          y = k - ((255 - y) * k >> 8);
271
0
          *g = (unsigned char)((c * 6969 + m * 23434 + y * 2365) >> 15);
272
0
        }
273
0
        ptr += im->step;
274
0
      }
275
2
    } else if (CCV_GET_CHANNEL(im->type) == CCV_C3) {
276
2
      /* CMYK to RGB */
277
3.49k
      while (cinfo.output_scanline < cinfo.output_height)
278
3.49k
      {
279
3.49k
        jpeg_read_scanlines(&cinfo, buffer, 1);
280
3.49k
        unsigned char* cmyk = (unsigned char*)buffer[0];
281
3.49k
        unsigned char* rgb = ptr;
282
8.37M
        for(i = 0; i < im->cols; 
i++, rgb += 3, cmyk += 48.37M
)
283
8.37M
        {
284
8.37M
          int c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
285
8.37M
          c = k - ((255 - c) * k >> 8);
286
8.37M
          m = k - ((255 - m) * k >> 8);
287
8.37M
          y = k - ((255 - y) * k >> 8);
288
8.37M
          rgb[0] = (unsigned char)c;
289
8.37M
          rgb[1] = (unsigned char)m;
290
8.37M
          rgb[2] = (unsigned char)y;
291
8.37M
        }
292
3.49k
        ptr += im->step;
293
3.49k
      }
294
2
    }
295
2
    // empty out the padding
296
2
    if (im->cols * ch < im->step)
297
0
    {
298
0
      size_t extra = im->step - im->cols * ch;
299
0
      unsigned char* ptr = im->data.u8 + im->cols * ch;
300
0
      for (i = 0; i < im->rows; i++, ptr += im->step)
301
0
        memset(ptr, 0, extra);
302
0
    }
303
2
  }
304
2
305
2
  jpeg_finish_decompress(&cinfo);
306
2
  jpeg_destroy_decompress(&cinfo);
307
2
}
308
309
static void _ccv_write_jpeg_fd(ccv_dense_matrix_t* mat, FILE* fd, void* conf)
310
0
{
311
0
  struct jpeg_compress_struct cinfo;
312
0
  struct ccv_jpeg_error_mgr_t jerr;
313
0
  jpeg_create_compress(&cinfo);
314
0
    cinfo.err = jpeg_std_error(&jerr.pub);
315
0
  jerr.pub.error_exit = error_exit;
316
0
  jpeg_stdio_dest(&cinfo, fd);
317
0
  if (setjmp(jerr.setjmp_buffer))
318
0
  {
319
0
    jpeg_destroy_compress(&cinfo);
320
0
    return;
321
0
  }
322
0
  cinfo.image_width = mat->cols;
323
0
  cinfo.image_height = mat->rows;
324
0
  cinfo.input_components = (CCV_GET_CHANNEL(mat->type) == CCV_C1) ? 1 : 3;
325
0
  cinfo.in_color_space = (CCV_GET_CHANNEL(mat->type) == CCV_C1) ? JCS_GRAYSCALE : JCS_RGB;
326
0
  jpeg_set_defaults(&cinfo);
327
0
  if (conf == 0)
328
0
    jpeg_set_quality(&cinfo, 95, TRUE);
329
0
  else
330
0
    jpeg_set_quality(&cinfo, *(int*)conf, TRUE);
331
0
  jpeg_start_compress(&cinfo, TRUE);
332
0
  int i;
333
0
  unsigned char* ptr = mat->data.u8;
334
0
  for (i = 0; i < mat->rows; i++)
335
0
  {
336
0
    jpeg_write_scanlines(&cinfo, &ptr, 1);
337
0
    ptr += mat->step;
338
0
  }
339
0
  jpeg_finish_compress(&cinfo);
340
0
  jpeg_destroy_compress(&cinfo);
341
0
}