Coverage Report

Created: 2017-11-12 13:27

/home/liu/buildslave/linux-x64-runtests/build/lib/ccv_io.c
Line
Count
Source (jump to first uncovered line)
1
#include "ccv.h"
2
#include "ccv_internal.h"
3
#ifdef HAVE_LIBPNG
4
#ifdef __APPLE__
5
#include "TargetConditionals.h"
6
#if TARGET_OS_IPHONE
7
// iOS
8
#elif TARGET_IPHONE_SIMULATOR
9
// iOS Simulator
10
#elif TARGET_OS_MAC
11
#include <zlib.h>
12
#include <png.h>
13
#else
14
// Unsupported platform
15
#endif
16
#else
17
#include <zlib.h>
18
#include <png.h>
19
#endif
20
#include "io/_ccv_io_libpng.inc"
21
#endif
22
#ifdef HAVE_LIBJPEG
23
#include <jpeglib.h>
24
#include "io/_ccv_io_libjpeg.inc"
25
#endif
26
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
27
#include <sys/param.h>
28
#endif
29
#include "io/_ccv_io_bmp.inc"
30
#include "io/_ccv_io_binary.inc"
31
#include "io/_ccv_io_raw.inc"
32
33
static int _ccv_read_and_close_fd(FILE* fd, ccv_dense_matrix_t** x, int type)
34
48
{
35
40
  int ctype = (type & 0xF00) ? 
CCV_8U | ((type & 0xF00) >> 8)8
:
040
;
36
48
  if ((type & 0XFF) == CCV_IO_ANY_FILE)
37
48
  {
38
48
    unsigned char sig[8];
39
48
    (void) fread(sig, 1, 8, fd);
40
48
    if (memcmp(sig, "\x89\x50\x4e\x47\xd\xa\x1a\xa", 8) == 0)
41
21
      type = CCV_IO_PNG_FILE;
42
27
    else 
if (27
memcmp(sig, "\xff\xd8\xff", 3) == 027
)
43
2
      type = CCV_IO_JPEG_FILE;
44
25
    else 
if (25
memcmp(sig, "BM", 2) == 025
)
45
0
      type = CCV_IO_BMP_FILE;
46
25
    else 
if (25
memcmp(sig, "CCVBINDM", 8) == 025
)
47
25
      type = CCV_IO_BINARY_FILE;
48
48
    fseek(fd, 0, SEEK_SET);
49
48
  }
50
48
  switch (type & 0XFF)
51
48
  {
52
48
#ifdef HAVE_LIBJPEG
53
2
    case CCV_IO_JPEG_FILE:
54
2
      _ccv_read_jpeg_fd(fd, x, ctype);
55
2
      break;
56
2
#endif
57
2
#ifdef HAVE_LIBPNG
58
21
    case CCV_IO_PNG_FILE:
59
21
      _ccv_read_png_fd(fd, x, ctype);
60
21
      break;
61
2
#endif
62
0
    case CCV_IO_BMP_FILE:
63
0
      _ccv_read_bmp_fd(fd, x, ctype);
64
0
      break;
65
25
    case CCV_IO_BINARY_FILE:
66
25
      _ccv_read_binary_fd(fd, x, ctype);
67
48
  }
68
48
  
if (48
*x != 048
)
69
48
    ccv_make_matrix_immutable(*x);
70
48
  if (type & CCV_IO_ANY_FILE)
71
48
    fclose(fd);
72
48
  return CCV_IO_FINAL;
73
48
}
74
75
static int _ccv_read_raw(ccv_dense_matrix_t** x, void* data, int type, int rows, int cols, int scanline)
76
20
{
77
20
  assert(rows > 0 && cols > 0 && scanline > 0);
78
20
  if (type & CCV_IO_NO_COPY)
79
1
  {
80
1
    // there is no conversion that we can apply if it is NO_COPY mode
81
1
    // NO_COPY mode generate an "unreusable" matrix, which requires you to
82
1
    // manually release its data block (which is, in fact the same data
83
1
    // block you passed in)
84
1
    int ctype = CCV_8U | CCV_C1;
85
1
    switch (type & 0xFF)
86
1
    {
87
0
      case CCV_IO_RGB_RAW:
88
0
      case CCV_IO_BGR_RAW:
89
0
        ctype = CCV_8U | CCV_C3;
90
0
        break;
91
0
      case CCV_IO_RGBA_RAW:
92
0
      case CCV_IO_ARGB_RAW:
93
0
      case CCV_IO_BGRA_RAW:
94
0
      case CCV_IO_ABGR_RAW:
95
0
        ctype = CCV_8U | CCV_C4;
96
0
        break;
97
0
      case CCV_IO_GRAY_RAW:
98
1
      default:
99
1
        /* default one */
100
1
        break;
101
1
    }
102
1
    *x = ccv_dense_matrix_new(rows, cols, ctype | CCV_NO_DATA_ALLOC, data, 0);
103
1
    (*x)->step = scanline;
104
19
  } else {
105
19
    switch (type & 0xFF)
106
19
    {
107
2
      case CCV_IO_RGB_RAW:
108
2
        _ccv_read_rgb_raw(x, data, type, rows, cols, scanline);
109
2
        break;
110
3
      case CCV_IO_RGBA_RAW:
111
3
        _ccv_read_rgba_raw(x, data, type, rows, cols, scanline);
112
3
        break;
113
3
      case CCV_IO_ARGB_RAW:
114
3
        _ccv_read_argb_raw(x, data, type, rows, cols, scanline);
115
3
        break;
116
3
      case CCV_IO_BGR_RAW:
117
3
        _ccv_read_bgr_raw(x, data, type, rows, cols, scanline);
118
3
        break;
119
3
      case CCV_IO_BGRA_RAW:
120
3
        _ccv_read_bgra_raw(x, data, type, rows, cols, scanline);
121
3
        break;
122
3
      case CCV_IO_ABGR_RAW:
123
3
        _ccv_read_abgr_raw(x, data, type, rows, cols, scanline);
124
3
        break;
125
2
      case CCV_IO_GRAY_RAW:
126
2
        _ccv_read_gray_raw(x, data, type, rows, cols, scanline);
127
2
        break;
128
19
    }
129
19
  }
130
20
  
if (20
*x != 020
)
131
20
    ccv_make_matrix_immutable(*x);
132
20
  return CCV_IO_FINAL;
133
20
}
134
135
#if defined(__APPLE__) || defined(BSD)
136
typedef struct {
137
  char* buffer;
138
  fpos_t pos;
139
  size_t size;
140
} ccv_io_mem_t;
141
142
static int readfn(void* context, char* buf, int size)
143
{
144
  ccv_io_mem_t* mem = (ccv_io_mem_t*)context;
145
  if (size + mem->pos > mem->size)
146
    size = mem->size - mem->pos;
147
  memcpy(buf, mem->buffer + mem->pos, size);
148
  mem->pos += size;
149
  return size;
150
}
151
152
static fpos_t seekfn(void* context, fpos_t off, int whence)
153
{
154
  ccv_io_mem_t* mem = (ccv_io_mem_t*)context;
155
  fpos_t pos;
156
  switch (whence)
157
  {
158
    case SEEK_SET:
159
      pos = off;
160
      break;
161
    case SEEK_CUR:
162
      pos = mem->pos + off;
163
      break;
164
    case SEEK_END:
165
      pos = mem->size + off;
166
      break;
167
  }
168
  if (pos >= mem->size)
169
    return -1;
170
  mem->pos = pos;
171
  return pos;
172
}
173
#endif
174
175
int ccv_read_impl(const void* in, ccv_dense_matrix_t** x, int type, int rows, int cols, int scanline)
176
68
{
177
68
  FILE* fd = 0;
178
68
  if (type & CCV_IO_ANY_FILE)
179
46
  {
180
46
    assert(rows == 0 && cols == 0 && scanline == 0);
181
46
    fd = fopen((const char*)in, "rb");
182
46
    if (!fd)
183
0
      return CCV_IO_ERROR;
184
46
    return _ccv_read_and_close_fd(fd, x, type);
185
22
  } else 
if (22
type & CCV_IO_ANY_STREAM22
)
{2
186
2
    assert(rows > 8 && cols == 0 && scanline == 0);
187
2
    assert((type & 0xFF) != CCV_IO_DEFLATE_STREAM); // deflate stream (compressed stream) is not supported yet
188
2
#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L || defined(__APPLE__) || defined(BSD)
189
2
    // this is only supported by glibc
190
2
#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
191
2
    fd = fmemopen((void*)in, (size_t)rows, "rb");
192
2
#else
193
    ccv_io_mem_t mem = {
194
      .size = rows,
195
      .pos = 0,
196
      .buffer = (char*)in,
197
    };
198
    fd = funopen(&mem, readfn, 0, seekfn, 0);
199
#endif
200
2
    if (!fd)
201
0
      return CCV_IO_ERROR;
202
2
    // mimicking itself as a "file"
203
2
    type = (type & ~0x10) | 0x20;
204
2
    return _ccv_read_and_close_fd(fd, x, type);
205
2
#endif
206
20
  } else 
if (20
type & CCV_IO_ANY_RAW20
)
{20
207
20
    return _ccv_read_raw(x, (void*)in /* it can be modifiable if it is NO_COPY mode */, type, rows, cols, scanline);
208
20
  }
209
0
  return CCV_IO_UNKNOWN;
210
68
}
211
212
int ccv_write(ccv_dense_matrix_t* mat, char* out, int* len, int type, void* conf)
213
0
{
214
0
  FILE* fd = 0;
215
0
  if (type & CCV_IO_ANY_FILE)
216
0
  {
217
0
    fd = fopen(out, "wb");
218
0
    if (!fd)
219
0
      return CCV_IO_ERROR;
220
0
  }
221
0
  switch (type)
222
0
  {
223
0
    case CCV_IO_JPEG_FILE:
224
0
#ifdef HAVE_LIBJPEG
225
0
      _ccv_write_jpeg_fd(mat, fd, conf);
226
0
      if (len != 0)
227
0
        *len = 0;
228
0
#else
229
      assert(0 && "ccv_write requires libjpeg support for JPEG format");
230
#endif
231
0
      break;
232
0
    case CCV_IO_PNG_FILE:
233
0
#ifdef HAVE_LIBPNG
234
0
      _ccv_write_png_fd(mat, fd, conf);
235
0
      if (len != 0)
236
0
        *len = 0;
237
0
#else
238
      assert(0 && "ccv_write requires libpng support for PNG format");
239
#endif
240
0
      break;
241
0
    case CCV_IO_BINARY_FILE:
242
0
      _ccv_write_binary_fd(mat, fd, conf);
243
0
      if (len != 0)
244
0
        *len = 0;
245
0
      break;
246
0
  }
247
0
  
if (0
type & CCV_IO_ANY_FILE0
)
248
0
    fclose(fd);
249
0
  return CCV_IO_FINAL;
250
0
}