imagecore 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/.gitignore +24 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +2 -0
  4. data/ext/imagecore/analyze_image.cxx +58 -0
  5. data/ext/imagecore/analyze_image.h +6 -0
  6. data/ext/imagecore/extconf.rb +9 -0
  7. data/ext/imagecore/imagecore.cxx +34 -0
  8. data/ext/opencv/core/___.c +3 -0
  9. data/ext/opencv/core/alloc.cpp +697 -0
  10. data/ext/opencv/core/array.cpp +3206 -0
  11. data/ext/opencv/core/datastructs.cpp +4064 -0
  12. data/ext/opencv/core/extconf.rb +22 -0
  13. data/ext/opencv/core/matrix.cpp +3777 -0
  14. data/ext/opencv/core/precomp.hpp +216 -0
  15. data/ext/opencv/core/system.cpp +832 -0
  16. data/ext/opencv/core/tables.cpp +3512 -0
  17. data/ext/opencv/highgui/___.c +3 -0
  18. data/ext/opencv/highgui/bitstrm.cpp +582 -0
  19. data/ext/opencv/highgui/bitstrm.hpp +182 -0
  20. data/ext/opencv/highgui/extconf.rb +28 -0
  21. data/ext/opencv/highgui/grfmt_base.cpp +128 -0
  22. data/ext/opencv/highgui/grfmt_base.hpp +113 -0
  23. data/ext/opencv/highgui/grfmt_bmp.cpp +564 -0
  24. data/ext/opencv/highgui/grfmt_bmp.hpp +99 -0
  25. data/ext/opencv/highgui/grfmt_exr.hpp +113 -0
  26. data/ext/opencv/highgui/grfmt_imageio.hpp +56 -0
  27. data/ext/opencv/highgui/grfmt_jpeg.cpp +622 -0
  28. data/ext/opencv/highgui/grfmt_jpeg.hpp +90 -0
  29. data/ext/opencv/highgui/grfmt_jpeg2000.cpp +529 -0
  30. data/ext/opencv/highgui/grfmt_jpeg2000.hpp +95 -0
  31. data/ext/opencv/highgui/grfmt_png.cpp +406 -0
  32. data/ext/opencv/highgui/grfmt_png.hpp +101 -0
  33. data/ext/opencv/highgui/grfmt_pxm.cpp +513 -0
  34. data/ext/opencv/highgui/grfmt_pxm.hpp +92 -0
  35. data/ext/opencv/highgui/grfmt_sunras.cpp +425 -0
  36. data/ext/opencv/highgui/grfmt_sunras.hpp +105 -0
  37. data/ext/opencv/highgui/grfmt_tiff.cpp +718 -0
  38. data/ext/opencv/highgui/grfmt_tiff.hpp +136 -0
  39. data/ext/opencv/highgui/grfmts.hpp +56 -0
  40. data/ext/opencv/highgui/loadsave.cpp +535 -0
  41. data/ext/opencv/highgui/precomp.hpp +223 -0
  42. data/ext/opencv/highgui/utils.cpp +689 -0
  43. data/ext/opencv/highgui/utils.hpp +128 -0
  44. data/ext/opencv/imgproc/___.c +3 -0
  45. data/ext/opencv/imgproc/_geom.h +72 -0
  46. data/ext/opencv/imgproc/color.cpp +3179 -0
  47. data/ext/opencv/imgproc/contours.cpp +1780 -0
  48. data/ext/opencv/imgproc/extconf.rb +11 -0
  49. data/ext/opencv/imgproc/filter.cpp +3063 -0
  50. data/ext/opencv/imgproc/precomp.hpp +159 -0
  51. data/ext/opencv/imgproc/shapedescr.cpp +1306 -0
  52. data/ext/opencv/imgproc/smooth.cpp +1566 -0
  53. data/ext/opencv/imgproc/tables.cpp +214 -0
  54. data/ext/opencv/imgproc/thresh.cpp +636 -0
  55. data/ext/opencv/imgproc/utils.cpp +242 -0
  56. data/ext/opencv/include/opencv2/core/core.hpp +4344 -0
  57. data/ext/opencv/include/opencv2/core/core_c.h +1885 -0
  58. data/ext/opencv/include/opencv2/core/internal.hpp +710 -0
  59. data/ext/opencv/include/opencv2/core/mat.hpp +2557 -0
  60. data/ext/opencv/include/opencv2/core/operations.hpp +3623 -0
  61. data/ext/opencv/include/opencv2/core/types_c.h +1875 -0
  62. data/ext/opencv/include/opencv2/core/version.hpp +58 -0
  63. data/ext/opencv/include/opencv2/highgui/highgui.hpp +198 -0
  64. data/ext/opencv/include/opencv2/highgui/highgui_c.h +506 -0
  65. data/ext/opencv/include/opencv2/imgproc/imgproc.hpp +1139 -0
  66. data/ext/opencv/include/opencv2/imgproc/imgproc_c.h +783 -0
  67. data/ext/opencv/include/opencv2/imgproc/types_c.h +538 -0
  68. data/imagecore.gemspec +20 -0
  69. data/lib/imagecore.rb +16 -0
  70. data/lib/imagecore/version.rb +3 -0
  71. metadata +119 -0
@@ -0,0 +1,564 @@
1
+ /*M///////////////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
+ //
5
+ // By downloading, copying, installing or using the software you agree to this license.
6
+ // If you do not agree to this license, do not download, install,
7
+ // copy or use the software.
8
+ //
9
+ //
10
+ // License Agreement
11
+ // For Open Source Computer Vision Library
12
+ //
13
+ // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14
+ // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15
+ // Third party copyrights are property of their respective owners.
16
+ //
17
+ // Redistribution and use in source and binary forms, with or without modification,
18
+ // are permitted provided that the following conditions are met:
19
+ //
20
+ // * Redistribution's of source code must retain the above copyright notice,
21
+ // this list of conditions and the following disclaimer.
22
+ //
23
+ // * Redistribution's in binary form must reproduce the above copyright notice,
24
+ // this list of conditions and the following disclaimer in the documentation
25
+ // and/or other materials provided with the distribution.
26
+ //
27
+ // * The name of the copyright holders may not be used to endorse or promote products
28
+ // derived from this software without specific prior written permission.
29
+ //
30
+ // This software is provided by the copyright holders and contributors "as is" and
31
+ // any express or implied warranties, including, but not limited to, the implied
32
+ // warranties of merchantability and fitness for a particular purpose are disclaimed.
33
+ // In no event shall the Intel Corporation or contributors be liable for any direct,
34
+ // indirect, incidental, special, exemplary, or consequential damages
35
+ // (including, but not limited to, procurement of substitute goods or services;
36
+ // loss of use, data, or profits; or business interruption) however caused
37
+ // and on any theory of liability, whether in contract, strict liability,
38
+ // or tort (including negligence or otherwise) arising in any way out of
39
+ // the use of this software, even if advised of the possibility of such damage.
40
+ //
41
+ //M*/
42
+
43
+ #include "precomp.hpp"
44
+ #include "grfmt_bmp.hpp"
45
+
46
+ namespace cv
47
+ {
48
+
49
+ static const char* fmtSignBmp = "BM";
50
+
51
+ /************************ BMP decoder *****************************/
52
+
53
+ BmpDecoder::BmpDecoder()
54
+ {
55
+ m_signature = fmtSignBmp;
56
+ m_offset = -1;
57
+ m_buf_supported = true;
58
+ }
59
+
60
+
61
+ BmpDecoder::~BmpDecoder()
62
+ {
63
+ }
64
+
65
+
66
+ void BmpDecoder::close()
67
+ {
68
+ m_strm.close();
69
+ }
70
+
71
+ ImageDecoder BmpDecoder::newDecoder() const
72
+ {
73
+ return new BmpDecoder;
74
+ }
75
+
76
+ bool BmpDecoder::readHeader()
77
+ {
78
+ bool result = false;
79
+ bool iscolor = false;
80
+
81
+ if( !m_buf.empty() )
82
+ {
83
+ if( !m_strm.open( m_buf ) )
84
+ return false;
85
+ }
86
+ else if( !m_strm.open( m_filename ))
87
+ return false;
88
+
89
+ try
90
+ {
91
+ m_strm.skip( 10 );
92
+ m_offset = m_strm.getDWord();
93
+
94
+ int size = m_strm.getDWord();
95
+
96
+ if( size >= 36 )
97
+ {
98
+ m_width = m_strm.getDWord();
99
+ m_height = m_strm.getDWord();
100
+ m_bpp = m_strm.getDWord() >> 16;
101
+ m_rle_code = (BmpCompression)m_strm.getDWord();
102
+ m_strm.skip(12);
103
+ int clrused = m_strm.getDWord();
104
+ m_strm.skip( size - 36 );
105
+
106
+ if( m_width > 0 && m_height != 0 &&
107
+ (((m_bpp == 1 || m_bpp == 4 || m_bpp == 8 ||
108
+ m_bpp == 24 || m_bpp == 32 ) && m_rle_code == BMP_RGB) ||
109
+ (m_bpp == 16 && (m_rle_code == BMP_RGB || m_rle_code == BMP_BITFIELDS)) ||
110
+ (m_bpp == 4 && m_rle_code == BMP_RLE4) ||
111
+ (m_bpp == 8 && m_rle_code == BMP_RLE8)))
112
+ {
113
+ iscolor = true;
114
+ result = true;
115
+
116
+ if( m_bpp <= 8 )
117
+ {
118
+ memset( m_palette, 0, sizeof(m_palette));
119
+ m_strm.getBytes( m_palette, (clrused == 0? 1<<m_bpp : clrused)*4 );
120
+ iscolor = IsColorPalette( m_palette, m_bpp );
121
+ }
122
+ else if( m_bpp == 16 && m_rle_code == BMP_BITFIELDS )
123
+ {
124
+ int redmask = m_strm.getDWord();
125
+ int greenmask = m_strm.getDWord();
126
+ int bluemask = m_strm.getDWord();
127
+
128
+ if( bluemask == 0x1f && greenmask == 0x3e0 && redmask == 0x7c00 )
129
+ m_bpp = 15;
130
+ else if( bluemask == 0x1f && greenmask == 0x7e0 && redmask == 0xf800 )
131
+ ;
132
+ else
133
+ result = false;
134
+ }
135
+ else if( m_bpp == 16 && m_rle_code == BMP_RGB )
136
+ m_bpp = 15;
137
+ }
138
+ }
139
+ else if( size == 12 )
140
+ {
141
+ m_width = m_strm.getWord();
142
+ m_height = m_strm.getWord();
143
+ m_bpp = m_strm.getDWord() >> 16;
144
+ m_rle_code = BMP_RGB;
145
+
146
+ if( m_width > 0 && m_height != 0 &&
147
+ (m_bpp == 1 || m_bpp == 4 || m_bpp == 8 ||
148
+ m_bpp == 24 || m_bpp == 32 ))
149
+ {
150
+ if( m_bpp <= 8 )
151
+ {
152
+ uchar buffer[256*3];
153
+ int j, clrused = 1 << m_bpp;
154
+ m_strm.getBytes( buffer, clrused*3 );
155
+ for( j = 0; j < clrused; j++ )
156
+ {
157
+ m_palette[j].b = buffer[3*j+0];
158
+ m_palette[j].g = buffer[3*j+1];
159
+ m_palette[j].r = buffer[3*j+2];
160
+ }
161
+ }
162
+ result = true;
163
+ }
164
+ }
165
+ }
166
+ catch(...)
167
+ {
168
+ }
169
+
170
+ m_type = iscolor ? CV_8UC3 : CV_8UC1;
171
+ m_origin = m_height > 0 ? IPL_ORIGIN_BL : IPL_ORIGIN_TL;
172
+ m_height = std::abs(m_height);
173
+
174
+ if( !result )
175
+ {
176
+ m_offset = -1;
177
+ m_width = m_height = -1;
178
+ m_strm.close();
179
+ }
180
+ return result;
181
+ }
182
+
183
+
184
+ bool BmpDecoder::readData( Mat& img )
185
+ {
186
+ uchar* data = img.data;
187
+ int step = (int)img.step;
188
+ bool color = img.channels() > 1;
189
+ uchar gray_palette[256];
190
+ bool result = false;
191
+ int src_pitch = ((m_width*(m_bpp != 15 ? m_bpp : 16) + 7)/8 + 3) & -4;
192
+ int nch = color ? 3 : 1;
193
+ int y, width3 = m_width*nch;
194
+
195
+ if( m_offset < 0 || !m_strm.isOpened())
196
+ return false;
197
+
198
+ if( m_origin == IPL_ORIGIN_BL )
199
+ {
200
+ data += (m_height - 1)*step;
201
+ step = -step;
202
+ }
203
+
204
+ AutoBuffer<uchar> _src, _bgr;
205
+ _src.allocate(src_pitch + 32);
206
+
207
+ if( !color )
208
+ {
209
+ if( m_bpp <= 8 )
210
+ {
211
+ CvtPaletteToGray( m_palette, gray_palette, 1 << m_bpp );
212
+ }
213
+ _bgr.allocate(m_width*3 + 32);
214
+ }
215
+ uchar *src = _src, *bgr = _bgr;
216
+
217
+ try
218
+ {
219
+ m_strm.setPos( m_offset );
220
+
221
+ switch( m_bpp )
222
+ {
223
+ /************************* 1 BPP ************************/
224
+ case 1:
225
+ for( y = 0; y < m_height; y++, data += step )
226
+ {
227
+ m_strm.getBytes( src, src_pitch );
228
+ FillColorRow1( color ? data : bgr, src, m_width, m_palette );
229
+ if( !color )
230
+ icvCvt_BGR2Gray_8u_C3C1R( bgr, 0, data, 0, cvSize(m_width,1) );
231
+ }
232
+ result = true;
233
+ break;
234
+
235
+ /************************* 4 BPP ************************/
236
+ case 4:
237
+ if( m_rle_code == BMP_RGB )
238
+ {
239
+ for( y = 0; y < m_height; y++, data += step )
240
+ {
241
+ m_strm.getBytes( src, src_pitch );
242
+ if( color )
243
+ FillColorRow4( data, src, m_width, m_palette );
244
+ else
245
+ FillGrayRow4( data, src, m_width, gray_palette );
246
+ }
247
+ result = true;
248
+ }
249
+ else if( m_rle_code == BMP_RLE4 ) // rle4 compression
250
+ {
251
+ uchar* line_end = data + width3;
252
+ y = 0;
253
+
254
+ for(;;)
255
+ {
256
+ int code = m_strm.getWord();
257
+ int len = code & 255;
258
+ code >>= 8;
259
+ if( len != 0 ) // encoded mode
260
+ {
261
+ PaletteEntry clr[2];
262
+ uchar gray_clr[2];
263
+ int t = 0;
264
+
265
+ clr[0] = m_palette[code >> 4];
266
+ clr[1] = m_palette[code & 15];
267
+ gray_clr[0] = gray_palette[code >> 4];
268
+ gray_clr[1] = gray_palette[code & 15];
269
+
270
+ uchar* end = data + len*nch;
271
+ if( end > line_end ) goto decode_rle4_bad;
272
+ do
273
+ {
274
+ if( color )
275
+ WRITE_PIX( data, clr[t] );
276
+ else
277
+ *data = gray_clr[t];
278
+ t ^= 1;
279
+ }
280
+ while( (data += nch) < end );
281
+ }
282
+ else if( code > 2 ) // absolute mode
283
+ {
284
+ if( data + code*nch > line_end ) goto decode_rle4_bad;
285
+ m_strm.getBytes( src, (((code + 1)>>1) + 1) & -2 );
286
+ if( color )
287
+ data = FillColorRow4( data, src, code, m_palette );
288
+ else
289
+ data = FillGrayRow4( data, src, code, gray_palette );
290
+ }
291
+ else
292
+ {
293
+ int x_shift3 = (int)(line_end - data);
294
+ int y_shift = m_height - y;
295
+
296
+ if( code == 2 )
297
+ {
298
+ x_shift3 = m_strm.getByte()*nch;
299
+ y_shift = m_strm.getByte();
300
+ }
301
+
302
+ len = x_shift3 + ((y_shift * width3) & ((code == 0) - 1));
303
+
304
+ if( color )
305
+ data = FillUniColor( data, line_end, step, width3,
306
+ y, m_height, x_shift3,
307
+ m_palette[0] );
308
+ else
309
+ data = FillUniGray( data, line_end, step, width3,
310
+ y, m_height, x_shift3,
311
+ gray_palette[0] );
312
+
313
+ if( y >= m_height )
314
+ break;
315
+ }
316
+ }
317
+
318
+ result = true;
319
+ decode_rle4_bad: ;
320
+ }
321
+ break;
322
+
323
+ /************************* 8 BPP ************************/
324
+ case 8:
325
+ if( m_rle_code == BMP_RGB )
326
+ {
327
+ for( y = 0; y < m_height; y++, data += step )
328
+ {
329
+ m_strm.getBytes( src, src_pitch );
330
+ if( color )
331
+ FillColorRow8( data, src, m_width, m_palette );
332
+ else
333
+ FillGrayRow8( data, src, m_width, gray_palette );
334
+ }
335
+ result = true;
336
+ }
337
+ else if( m_rle_code == BMP_RLE8 ) // rle8 compression
338
+ {
339
+ uchar* line_end = data + width3;
340
+ int line_end_flag = 0;
341
+ y = 0;
342
+
343
+ for(;;)
344
+ {
345
+ int code = m_strm.getWord();
346
+ int len = code & 255;
347
+ code >>= 8;
348
+ if( len != 0 ) // encoded mode
349
+ {
350
+ int prev_y = y;
351
+ len *= nch;
352
+
353
+ if( data + len > line_end )
354
+ goto decode_rle8_bad;
355
+
356
+ if( color )
357
+ data = FillUniColor( data, line_end, step, width3,
358
+ y, m_height, len,
359
+ m_palette[code] );
360
+ else
361
+ data = FillUniGray( data, line_end, step, width3,
362
+ y, m_height, len,
363
+ gray_palette[code] );
364
+
365
+ line_end_flag = y - prev_y;
366
+ }
367
+ else if( code > 2 ) // absolute mode
368
+ {
369
+ int prev_y = y;
370
+ int code3 = code*nch;
371
+
372
+ if( data + code3 > line_end )
373
+ goto decode_rle8_bad;
374
+ m_strm.getBytes( src, (code + 1) & -2 );
375
+ if( color )
376
+ data = FillColorRow8( data, src, code, m_palette );
377
+ else
378
+ data = FillGrayRow8( data, src, code, gray_palette );
379
+
380
+ line_end_flag = y - prev_y;
381
+ }
382
+ else
383
+ {
384
+ int x_shift3 = (int)(line_end - data);
385
+ int y_shift = m_height - y;
386
+
387
+ if( code || !line_end_flag || x_shift3 < width3 )
388
+ {
389
+ if( code == 2 )
390
+ {
391
+ x_shift3 = m_strm.getByte()*nch;
392
+ y_shift = m_strm.getByte();
393
+ }
394
+
395
+ x_shift3 += (y_shift * width3) & ((code == 0) - 1);
396
+
397
+ if( y >= m_height )
398
+ break;
399
+
400
+ if( color )
401
+ data = FillUniColor( data, line_end, step, width3,
402
+ y, m_height, x_shift3,
403
+ m_palette[0] );
404
+ else
405
+ data = FillUniGray( data, line_end, step, width3,
406
+ y, m_height, x_shift3,
407
+ gray_palette[0] );
408
+
409
+ if( y >= m_height )
410
+ break;
411
+ }
412
+
413
+ line_end_flag = 0;
414
+ }
415
+ }
416
+
417
+ result = true;
418
+ decode_rle8_bad: ;
419
+ }
420
+ break;
421
+ /************************* 15 BPP ************************/
422
+ case 15:
423
+ for( y = 0; y < m_height; y++, data += step )
424
+ {
425
+ m_strm.getBytes( src, src_pitch );
426
+ if( !color )
427
+ icvCvt_BGR5552Gray_8u_C2C1R( src, 0, data, 0, cvSize(m_width,1) );
428
+ else
429
+ icvCvt_BGR5552BGR_8u_C2C3R( src, 0, data, 0, cvSize(m_width,1) );
430
+ }
431
+ result = true;
432
+ break;
433
+ /************************* 16 BPP ************************/
434
+ case 16:
435
+ for( y = 0; y < m_height; y++, data += step )
436
+ {
437
+ m_strm.getBytes( src, src_pitch );
438
+ if( !color )
439
+ icvCvt_BGR5652Gray_8u_C2C1R( src, 0, data, 0, cvSize(m_width,1) );
440
+ else
441
+ icvCvt_BGR5652BGR_8u_C2C3R( src, 0, data, 0, cvSize(m_width,1) );
442
+ }
443
+ result = true;
444
+ break;
445
+ /************************* 24 BPP ************************/
446
+ case 24:
447
+ for( y = 0; y < m_height; y++, data += step )
448
+ {
449
+ m_strm.getBytes( src, src_pitch );
450
+ if(!color)
451
+ icvCvt_BGR2Gray_8u_C3C1R( src, 0, data, 0, cvSize(m_width,1) );
452
+ else
453
+ memcpy( data, src, m_width*3 );
454
+ }
455
+ result = true;
456
+ break;
457
+ /************************* 32 BPP ************************/
458
+ case 32:
459
+ for( y = 0; y < m_height; y++, data += step )
460
+ {
461
+ m_strm.getBytes( src, src_pitch );
462
+
463
+ if( !color )
464
+ icvCvt_BGRA2Gray_8u_C4C1R( src, 0, data, 0, cvSize(m_width,1) );
465
+ else
466
+ icvCvt_BGRA2BGR_8u_C4C3R( src, 0, data, 0, cvSize(m_width,1) );
467
+ }
468
+ result = true;
469
+ break;
470
+ default:
471
+ assert(0);
472
+ }
473
+ }
474
+ catch(...)
475
+ {
476
+ }
477
+
478
+ return result;
479
+ }
480
+
481
+
482
+ //////////////////////////////////////////////////////////////////////////////////////////
483
+
484
+ BmpEncoder::BmpEncoder()
485
+ {
486
+ m_description = "Windows bitmap (*.bmp;*.dib)";
487
+ m_buf_supported = true;
488
+ }
489
+
490
+
491
+ BmpEncoder::~BmpEncoder()
492
+ {
493
+ }
494
+
495
+ ImageEncoder BmpEncoder::newEncoder() const
496
+ {
497
+ return new BmpEncoder;
498
+ }
499
+
500
+ bool BmpEncoder::write( const Mat& img, const vector<int>& )
501
+ {
502
+ int width = img.cols, height = img.rows, channels = img.channels();
503
+ int fileStep = (width*channels + 3) & -4;
504
+ uchar zeropad[] = "\0\0\0\0";
505
+ WLByteStream strm;
506
+
507
+ if( m_buf )
508
+ {
509
+ if( !strm.open( *m_buf ) )
510
+ return false;
511
+ }
512
+ else if( !strm.open( m_filename ))
513
+ return false;
514
+
515
+ int bitmapHeaderSize = 40;
516
+ int paletteSize = channels > 1 ? 0 : 1024;
517
+ int headerSize = 14 /* fileheader */ + bitmapHeaderSize + paletteSize;
518
+ int fileSize = fileStep*height + headerSize;
519
+ PaletteEntry palette[256];
520
+
521
+ if( m_buf )
522
+ m_buf->reserve( alignSize(fileSize + 16, 256) );
523
+
524
+ // write signature 'BM'
525
+ strm.putBytes( fmtSignBmp, (int)strlen(fmtSignBmp) );
526
+
527
+ // write file header
528
+ strm.putDWord( fileSize ); // file size
529
+ strm.putDWord( 0 );
530
+ strm.putDWord( headerSize );
531
+
532
+ // write bitmap header
533
+ strm.putDWord( bitmapHeaderSize );
534
+ strm.putDWord( width );
535
+ strm.putDWord( height );
536
+ strm.putWord( 1 );
537
+ strm.putWord( channels << 3 );
538
+ strm.putDWord( BMP_RGB );
539
+ strm.putDWord( 0 );
540
+ strm.putDWord( 0 );
541
+ strm.putDWord( 0 );
542
+ strm.putDWord( 0 );
543
+ strm.putDWord( 0 );
544
+
545
+ if( channels == 1 )
546
+ {
547
+ FillGrayPalette( palette, 8 );
548
+ strm.putBytes( palette, sizeof(palette));
549
+ }
550
+
551
+ width *= channels;
552
+ for( int y = height - 1; y >= 0; y-- )
553
+ {
554
+ strm.putBytes( img.data + img.step*y, width );
555
+ if( fileStep > width )
556
+ strm.putBytes( zeropad, fileStep - width );
557
+ }
558
+
559
+ strm.close();
560
+ return true;
561
+ }
562
+
563
+ }
564
+