Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/imgcodecs/src/bitstrm.cpp
16337 views
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 "bitstrm.hpp"
45
#include "utils.hpp"
46
47
namespace cv
48
{
49
50
const int BS_DEF_BLOCK_SIZE = 1<<15;
51
52
bool bsIsBigEndian( void )
53
{
54
return (((const int*)"\0\x1\x2\x3\x4\x5\x6\x7")[0] & 255) != 0;
55
}
56
57
///////////////////////// RBaseStream ////////////////////////////
58
59
bool RBaseStream::isOpened()
60
{
61
return m_is_opened;
62
}
63
64
void RBaseStream::allocate()
65
{
66
if( !m_allocated )
67
{
68
m_start = new uchar[m_block_size];
69
m_end = m_start + m_block_size;
70
m_current = m_end;
71
m_allocated = true;
72
}
73
}
74
75
76
RBaseStream::RBaseStream()
77
{
78
m_start = m_end = m_current = 0;
79
m_file = 0;
80
m_block_pos = 0;
81
m_block_size = BS_DEF_BLOCK_SIZE;
82
m_is_opened = false;
83
m_allocated = false;
84
}
85
86
87
RBaseStream::~RBaseStream()
88
{
89
close(); // Close files
90
release(); // free buffers
91
}
92
93
94
void RBaseStream::readBlock()
95
{
96
setPos( getPos() ); // normalize position
97
98
if( m_file == 0 )
99
{
100
if( m_block_pos == 0 && m_current < m_end )
101
return;
102
CV_THROW (RBS_THROW_EOS);
103
}
104
105
fseek( m_file, m_block_pos, SEEK_SET );
106
size_t readed = fread( m_start, 1, m_block_size, m_file );
107
m_end = m_start + readed;
108
109
if( readed == 0 || m_current >= m_end )
110
CV_THROW (RBS_THROW_EOS);
111
}
112
113
114
bool RBaseStream::open( const String& filename )
115
{
116
close();
117
allocate();
118
119
m_file = fopen( filename.c_str(), "rb" );
120
if( m_file )
121
{
122
m_is_opened = true;
123
setPos(0);
124
readBlock();
125
}
126
return m_file != 0;
127
}
128
129
bool RBaseStream::open( const Mat& buf )
130
{
131
close();
132
if( buf.empty() )
133
return false;
134
CV_Assert(buf.isContinuous());
135
m_start = buf.data;
136
m_end = m_start + buf.cols*buf.rows*buf.elemSize();
137
m_allocated = false;
138
m_is_opened = true;
139
setPos(0);
140
141
return true;
142
}
143
144
void RBaseStream::close()
145
{
146
if( m_file )
147
{
148
fclose( m_file );
149
m_file = 0;
150
}
151
m_is_opened = false;
152
if( !m_allocated )
153
m_start = m_end = m_current = 0;
154
}
155
156
157
void RBaseStream::release()
158
{
159
if( m_allocated )
160
delete[] m_start;
161
m_start = m_end = m_current = 0;
162
m_allocated = false;
163
}
164
165
166
void RBaseStream::setPos( int pos )
167
{
168
CV_Assert(isOpened() && pos >= 0);
169
170
if( !m_file )
171
{
172
m_current = m_start + pos;
173
m_block_pos = 0;
174
return;
175
}
176
177
int offset = pos % m_block_size;
178
m_block_pos = pos - offset;
179
m_current = m_start + offset;
180
}
181
182
183
int RBaseStream::getPos()
184
{
185
CV_Assert(isOpened());
186
int pos = validateToInt((m_current - m_start) + m_block_pos);
187
CV_Assert(pos >= m_block_pos); // overflow check
188
CV_Assert(pos >= 0); // overflow check
189
return pos;
190
}
191
192
void RBaseStream::skip( int bytes )
193
{
194
CV_Assert(bytes >= 0);
195
uchar* old = m_current;
196
m_current += bytes;
197
CV_Assert(m_current >= old); // overflow check
198
}
199
200
///////////////////////// RLByteStream ////////////////////////////
201
202
RLByteStream::~RLByteStream()
203
{
204
}
205
206
int RLByteStream::getByte()
207
{
208
uchar *current = m_current;
209
int val;
210
211
if( current >= m_end )
212
{
213
readBlock();
214
current = m_current;
215
}
216
217
CV_Assert(current < m_end);
218
219
val = *((uchar*)current);
220
m_current = current + 1;
221
return val;
222
}
223
224
225
int RLByteStream::getBytes( void* buffer, int count )
226
{
227
uchar* data = (uchar*)buffer;
228
int readed = 0;
229
CV_Assert(count >= 0);
230
231
while( count > 0 )
232
{
233
int l;
234
235
for(;;)
236
{
237
l = (int)(m_end - m_current);
238
if( l > count ) l = count;
239
if( l > 0 ) break;
240
readBlock();
241
}
242
memcpy( data, m_current, l );
243
m_current += l;
244
data += l;
245
count -= l;
246
readed += l;
247
}
248
return readed;
249
}
250
251
252
//////////// RLByteStream & RMByteStream <Get[d]word>s ////////////////
253
254
RMByteStream::~RMByteStream()
255
{
256
}
257
258
259
int RLByteStream::getWord()
260
{
261
uchar *current = m_current;
262
int val;
263
264
if( current+1 < m_end )
265
{
266
val = current[0] + (current[1] << 8);
267
m_current = current + 2;
268
}
269
else
270
{
271
val = getByte();
272
val|= getByte() << 8;
273
}
274
return val;
275
}
276
277
278
int RLByteStream::getDWord()
279
{
280
uchar *current = m_current;
281
int val;
282
283
if( current+3 < m_end )
284
{
285
val = current[0] + (current[1] << 8) +
286
(current[2] << 16) + (current[3] << 24);
287
m_current = current + 4;
288
}
289
else
290
{
291
val = getByte();
292
val |= getByte() << 8;
293
val |= getByte() << 16;
294
val |= getByte() << 24;
295
}
296
return val;
297
}
298
299
300
int RMByteStream::getWord()
301
{
302
uchar *current = m_current;
303
int val;
304
305
if( current+1 < m_end )
306
{
307
val = (current[0] << 8) + current[1];
308
m_current = current + 2;
309
}
310
else
311
{
312
val = getByte() << 8;
313
val|= getByte();
314
}
315
return val;
316
}
317
318
319
int RMByteStream::getDWord()
320
{
321
uchar *current = m_current;
322
int val;
323
324
if( current+3 < m_end )
325
{
326
val = (current[0] << 24) + (current[1] << 16) +
327
(current[2] << 8) + current[3];
328
m_current = current + 4;
329
}
330
else
331
{
332
val = getByte() << 24;
333
val |= getByte() << 16;
334
val |= getByte() << 8;
335
val |= getByte();
336
}
337
return val;
338
}
339
340
/////////////////////////// WBaseStream /////////////////////////////////
341
342
// WBaseStream - base class for output streams
343
WBaseStream::WBaseStream()
344
{
345
m_start = m_end = m_current = 0;
346
m_file = 0;
347
m_block_pos = 0;
348
m_block_size = BS_DEF_BLOCK_SIZE;
349
m_is_opened = false;
350
m_buf = 0;
351
}
352
353
354
WBaseStream::~WBaseStream()
355
{
356
close();
357
release();
358
}
359
360
361
bool WBaseStream::isOpened()
362
{
363
return m_is_opened;
364
}
365
366
367
void WBaseStream::allocate()
368
{
369
if( !m_start )
370
m_start = new uchar[m_block_size];
371
372
m_end = m_start + m_block_size;
373
m_current = m_start;
374
}
375
376
377
void WBaseStream::writeBlock()
378
{
379
int size = (int)(m_current - m_start);
380
381
CV_Assert(isOpened());
382
if( size == 0 )
383
return;
384
385
if( m_buf )
386
{
387
size_t sz = m_buf->size();
388
m_buf->resize( sz + size );
389
memcpy( &(*m_buf)[sz], m_start, size );
390
}
391
else
392
{
393
fwrite( m_start, 1, size, m_file );
394
}
395
m_current = m_start;
396
m_block_pos += size;
397
}
398
399
400
bool WBaseStream::open( const String& filename )
401
{
402
close();
403
allocate();
404
405
m_file = fopen( filename.c_str(), "wb" );
406
if( m_file )
407
{
408
m_is_opened = true;
409
m_block_pos = 0;
410
m_current = m_start;
411
}
412
return m_file != 0;
413
}
414
415
bool WBaseStream::open( std::vector<uchar>& buf )
416
{
417
close();
418
allocate();
419
420
m_buf = &buf;
421
m_is_opened = true;
422
m_block_pos = 0;
423
m_current = m_start;
424
425
return true;
426
}
427
428
void WBaseStream::close()
429
{
430
if( m_is_opened )
431
writeBlock();
432
if( m_file )
433
{
434
fclose( m_file );
435
m_file = 0;
436
}
437
m_buf = 0;
438
m_is_opened = false;
439
}
440
441
442
void WBaseStream::release()
443
{
444
if( m_start )
445
delete[] m_start;
446
m_start = m_end = m_current = 0;
447
}
448
449
450
int WBaseStream::getPos()
451
{
452
CV_Assert(isOpened());
453
return m_block_pos + (int)(m_current - m_start);
454
}
455
456
457
///////////////////////////// WLByteStream ///////////////////////////////////
458
459
WLByteStream::~WLByteStream()
460
{
461
}
462
463
void WLByteStream::putByte( int val )
464
{
465
*m_current++ = (uchar)val;
466
if( m_current >= m_end )
467
writeBlock();
468
}
469
470
471
void WLByteStream::putBytes( const void* buffer, int count )
472
{
473
uchar* data = (uchar*)buffer;
474
475
CV_Assert(data && m_current && count >= 0);
476
477
while( count )
478
{
479
int l = (int)(m_end - m_current);
480
481
if( l > count )
482
l = count;
483
484
if( l > 0 )
485
{
486
memcpy( m_current, data, l );
487
m_current += l;
488
data += l;
489
count -= l;
490
}
491
if( m_current == m_end )
492
writeBlock();
493
}
494
}
495
496
497
void WLByteStream::putWord( int val )
498
{
499
uchar *current = m_current;
500
501
if( current+1 < m_end )
502
{
503
current[0] = (uchar)val;
504
current[1] = (uchar)(val >> 8);
505
m_current = current + 2;
506
if( m_current == m_end )
507
writeBlock();
508
}
509
else
510
{
511
putByte(val);
512
putByte(val >> 8);
513
}
514
}
515
516
517
void WLByteStream::putDWord( int val )
518
{
519
uchar *current = m_current;
520
521
if( current+3 < m_end )
522
{
523
current[0] = (uchar)val;
524
current[1] = (uchar)(val >> 8);
525
current[2] = (uchar)(val >> 16);
526
current[3] = (uchar)(val >> 24);
527
m_current = current + 4;
528
if( m_current == m_end )
529
writeBlock();
530
}
531
else
532
{
533
putByte(val);
534
putByte(val >> 8);
535
putByte(val >> 16);
536
putByte(val >> 24);
537
}
538
}
539
540
541
///////////////////////////// WMByteStream ///////////////////////////////////
542
543
WMByteStream::~WMByteStream()
544
{
545
}
546
547
548
void WMByteStream::putWord( int val )
549
{
550
uchar *current = m_current;
551
552
if( current+1 < m_end )
553
{
554
current[0] = (uchar)(val >> 8);
555
current[1] = (uchar)val;
556
m_current = current + 2;
557
if( m_current == m_end )
558
writeBlock();
559
}
560
else
561
{
562
putByte(val >> 8);
563
putByte(val);
564
}
565
}
566
567
568
void WMByteStream::putDWord( int val )
569
{
570
uchar *current = m_current;
571
572
if( current+3 < m_end )
573
{
574
current[0] = (uchar)(val >> 24);
575
current[1] = (uchar)(val >> 16);
576
current[2] = (uchar)(val >> 8);
577
current[3] = (uchar)val;
578
m_current = current + 4;
579
if( m_current == m_end )
580
writeBlock();
581
}
582
else
583
{
584
putByte(val >> 24);
585
putByte(val >> 16);
586
putByte(val >> 8);
587
putByte(val);
588
}
589
}
590
591
}
592
593