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,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.o
19
+ *.so
20
+ *.sw?
21
+ ext/imagecore/Makefile
22
+ cvconfig.h
23
+ mkmf.log
24
+ Makefile
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in imagecore.gemspec
4
+ gemspec
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,58 @@
1
+ #include "opencv2/core/types_c.h"
2
+ #include "opencv2/highgui/highgui.hpp"
3
+ #include "opencv2/imgproc/imgproc.hpp"
4
+ #include "analyze_image.h"
5
+
6
+ using namespace cv;
7
+ using namespace std;
8
+
9
+ bool image_core_analyze_image(const char *filename, int thresh,
10
+ int &tlx, int &tly, int &brx, int &bry)
11
+ {
12
+ Mat src, src_gray;
13
+
14
+ src = imread(filename, 1);
15
+
16
+ if (src.empty())
17
+ return false;
18
+
19
+ cvtColor(src, src_gray, CV_BGR2GRAY);
20
+ blur(src_gray, src_gray, Size(3, 3));
21
+
22
+ Mat threshold_output;
23
+ vector<vector<Point> > contours;
24
+ vector<Vec4i> hierarchy;
25
+
26
+ /// Detect edges using Threshold
27
+ threshold(src_gray, threshold_output, thresh, 255, THRESH_BINARY);
28
+
29
+ /// Find contours
30
+ findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE,
31
+ Point(0, 0));
32
+
33
+ vector<Rect> boundRect(contours.size());
34
+ vector<Point> allcontours;
35
+ unsigned enclosing = -1;
36
+
37
+ for (unsigned i = 0; i < contours.size(); i++) {
38
+ boundRect[i] = boundingRect(Mat(contours[i]));
39
+
40
+ // detect big enclosing rect with everything
41
+ if (boundRect[i].width >= src.cols - 5 && boundRect[i].height >= src.rows - 5)
42
+ enclosing = i;
43
+ else
44
+ allcontours.insert(allcontours.end(), contours[i].begin(), contours[i].end());
45
+ }
46
+
47
+ if (allcontours.size() == 0)
48
+ allcontours = contours[0];
49
+
50
+ Rect globalrect = boundingRect(Mat(allcontours));
51
+
52
+ tlx = globalrect.tl().x;
53
+ tly = globalrect.tl().y;
54
+ brx = globalrect.br().x;
55
+ bry = globalrect.br().y;
56
+
57
+ return true;
58
+ }
@@ -0,0 +1,6 @@
1
+ #ifndef __analyze_image_h
2
+ #define __analyze_image_h
3
+
4
+ bool image_core_analyze_image(const char *filename, int threshold, int &tlx, int &tly, int &brx, int &bry);
5
+
6
+ #endif
@@ -0,0 +1,9 @@
1
+ require 'mkmf'
2
+
3
+ # not valid for C++ code
4
+ $warnflags = ($warnflags.split - %w(-Wdeclaration-after-statement -Wimplicit-function-declaration)) * ' '
5
+
6
+ # OpenCV includes
7
+ $INCFLAGS << ' -I ../opencv/include'
8
+
9
+ create_makefile("imagecore")
@@ -0,0 +1,34 @@
1
+ #include "ruby.h"
2
+ #include <stdio.h>
3
+ #include "analyze_image.h"
4
+
5
+ static VALUE analyze(VALUE klass, VALUE filename, VALUE thresh)
6
+ {
7
+ Check_Type(filename, T_STRING);
8
+ Check_Type(thresh, T_FIXNUM);
9
+
10
+ char *fn = StringValueCStr(filename);
11
+
12
+ int threshold = NUM2INT(thresh);
13
+ int tlx, tly, brx, bry;
14
+
15
+ if (image_core_analyze_image(fn, threshold, tlx, tly, brx, bry)) {
16
+ VALUE arr = rb_ary_new();
17
+
18
+ rb_ary_push(arr, INT2FIX(tlx));
19
+ rb_ary_push(arr, INT2FIX(tly));
20
+ rb_ary_push(arr, INT2FIX(brx));
21
+ rb_ary_push(arr, INT2FIX(bry));
22
+
23
+ return arr;
24
+ } else
25
+ return Qnil;
26
+ }
27
+
28
+ extern "C" void Init_imagecore()
29
+ {
30
+ VALUE module = rb_const_get(rb_cObject, rb_intern("ImageCore"));
31
+ VALUE klass = rb_define_class_under(module, "Ext", rb_cObject);
32
+
33
+ rb_define_singleton_method(klass, "analyze", (VALUE(*)(ANYARGS))analyze, 2);
34
+ }
@@ -0,0 +1,3 @@
1
+ void Init_opencv_core()
2
+ {
3
+ }
@@ -0,0 +1,697 @@
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
+
45
+ #define CV_USE_SYSTEM_MALLOC 1
46
+
47
+ namespace cv
48
+ {
49
+
50
+ static void* OutOfMemoryError(size_t size)
51
+ {
52
+ CV_Error_(CV_StsNoMem, ("Failed to allocate %lu bytes", (unsigned long)size));
53
+ return 0;
54
+ }
55
+
56
+ #if CV_USE_SYSTEM_MALLOC
57
+
58
+ void deleteThreadAllocData() {}
59
+
60
+ void* fastMalloc( size_t size )
61
+ {
62
+ uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN);
63
+ if(!udata)
64
+ return OutOfMemoryError(size);
65
+ uchar** adata = alignPtr((uchar**)udata + 1, CV_MALLOC_ALIGN);
66
+ adata[-1] = udata;
67
+ return adata;
68
+ }
69
+
70
+ void fastFree(void* ptr)
71
+ {
72
+ if(ptr)
73
+ {
74
+ uchar* udata = ((uchar**)ptr)[-1];
75
+ CV_DbgAssert(udata < (uchar*)ptr &&
76
+ ((uchar*)ptr - udata) <= (ptrdiff_t)(sizeof(void*)+CV_MALLOC_ALIGN));
77
+ free(udata);
78
+ }
79
+ }
80
+
81
+ #else
82
+
83
+ #if 0
84
+ #define SANITY_CHECK(block) \
85
+ CV_Assert(((size_t)(block) & (MEM_BLOCK_SIZE-1)) == 0 && \
86
+ (unsigned)(block)->binIdx <= (unsigned)MAX_BIN && \
87
+ (block)->signature == MEM_BLOCK_SIGNATURE)
88
+ #else
89
+ #define SANITY_CHECK(block)
90
+ #endif
91
+
92
+ #define STAT(stmt)
93
+
94
+ #ifdef WIN32
95
+ struct CriticalSection
96
+ {
97
+ CriticalSection() { InitializeCriticalSection(&cs); }
98
+ ~CriticalSection() { DeleteCriticalSection(&cs); }
99
+ void lock() { EnterCriticalSection(&cs); }
100
+ void unlock() { LeaveCriticalSection(&cs); }
101
+ bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
102
+
103
+ CRITICAL_SECTION cs;
104
+ };
105
+
106
+ void* SystemAlloc(size_t size)
107
+ {
108
+ void* ptr = malloc(size);
109
+ return ptr ? ptr : OutOfMemoryError(size);
110
+ }
111
+
112
+ void SystemFree(void* ptr, size_t)
113
+ {
114
+ free(ptr);
115
+ }
116
+ #else
117
+ struct CriticalSection
118
+ {
119
+ CriticalSection() { pthread_mutex_init(&mutex, 0); }
120
+ ~CriticalSection() { pthread_mutex_destroy(&mutex); }
121
+ void lock() { pthread_mutex_lock(&mutex); }
122
+ void unlock() { pthread_mutex_unlock(&mutex); }
123
+ bool trylock() { return pthread_mutex_trylock(&mutex) == 0; }
124
+
125
+ pthread_mutex_t mutex;
126
+ };
127
+
128
+ void* SystemAlloc(size_t size)
129
+ {
130
+ #ifndef MAP_ANONYMOUS
131
+ #define MAP_ANONYMOUS MAP_ANON
132
+ #endif
133
+ void* ptr = 0;
134
+ ptr = mmap(ptr, size, (PROT_READ | PROT_WRITE), MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
135
+ return ptr != MAP_FAILED ? ptr : OutOfMemoryError(size);
136
+ }
137
+
138
+ void SystemFree(void* ptr, size_t size)
139
+ {
140
+ munmap(ptr, size);
141
+ }
142
+ #endif
143
+
144
+ struct AutoLock
145
+ {
146
+ AutoLock(CriticalSection& _cs) : cs(&_cs) { cs->lock(); }
147
+ ~AutoLock() { cs->unlock(); }
148
+ CriticalSection* cs;
149
+ };
150
+
151
+ const size_t MEM_BLOCK_SIGNATURE = 0x01234567;
152
+ const int MEM_BLOCK_SHIFT = 14;
153
+ const size_t MEM_BLOCK_SIZE = 1 << MEM_BLOCK_SHIFT;
154
+ const size_t HDR_SIZE = 128;
155
+ const size_t MAX_BLOCK_SIZE = MEM_BLOCK_SIZE - HDR_SIZE;
156
+ const int MAX_BIN = 28;
157
+
158
+ static const int binSizeTab[MAX_BIN+1] =
159
+ { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 128, 160, 192, 256, 320, 384, 480, 544, 672, 768,
160
+ 896, 1056, 1328, 1600, 2688, 4048, 5408, 8128, 16256 };
161
+
162
+ struct MallocTables
163
+ {
164
+ void initBinTab()
165
+ {
166
+ int i, j = 0, n;
167
+ for( i = 0; i <= MAX_BIN; i++ )
168
+ {
169
+ n = binSizeTab[i]>>3;
170
+ for( ; j <= n; j++ )
171
+ binIdx[j] = (uchar)i;
172
+ }
173
+ }
174
+ int bin(size_t size)
175
+ {
176
+ assert( size <= MAX_BLOCK_SIZE );
177
+ return binIdx[(size + 7)>>3];
178
+ }
179
+
180
+ MallocTables()
181
+ {
182
+ initBinTab();
183
+ }
184
+
185
+ uchar binIdx[MAX_BLOCK_SIZE/8+1];
186
+ };
187
+
188
+ MallocTables mallocTables;
189
+
190
+ struct Node
191
+ {
192
+ Node* next;
193
+ };
194
+
195
+ struct ThreadData;
196
+
197
+ struct Block
198
+ {
199
+ Block(Block* _next)
200
+ {
201
+ signature = MEM_BLOCK_SIGNATURE;
202
+ prev = 0;
203
+ next = _next;
204
+ privateFreeList = publicFreeList = 0;
205
+ bumpPtr = endPtr = 0;
206
+ objSize = 0;
207
+ threadData = 0;
208
+ data = (uchar*)this + HDR_SIZE;
209
+ }
210
+
211
+ ~Block() {}
212
+
213
+ void init(Block* _prev, Block* _next, int _objSize, ThreadData* _threadData)
214
+ {
215
+ prev = _prev;
216
+ if(prev)
217
+ prev->next = this;
218
+ next = _next;
219
+ if(next)
220
+ next->prev = this;
221
+ objSize = _objSize;
222
+ binIdx = mallocTables.bin(objSize);
223
+ threadData = _threadData;
224
+ privateFreeList = publicFreeList = 0;
225
+ bumpPtr = data;
226
+ int nobjects = MAX_BLOCK_SIZE/objSize;
227
+ endPtr = bumpPtr + nobjects*objSize;
228
+ almostEmptyThreshold = (nobjects + 1)/2;
229
+ allocated = 0;
230
+ }
231
+
232
+ bool isFilled() const { return allocated > almostEmptyThreshold; }
233
+
234
+ size_t signature;
235
+ Block* prev;
236
+ Block* next;
237
+ Node* privateFreeList;
238
+ Node* publicFreeList;
239
+ uchar* bumpPtr;
240
+ uchar* endPtr;
241
+ uchar* data;
242
+ ThreadData* threadData;
243
+ int objSize;
244
+ int binIdx;
245
+ int allocated;
246
+ int almostEmptyThreshold;
247
+ CriticalSection cs;
248
+ };
249
+
250
+ struct BigBlock
251
+ {
252
+ BigBlock(int bigBlockSize, BigBlock* _next)
253
+ {
254
+ first = alignPtr((Block*)(this+1), MEM_BLOCK_SIZE);
255
+ next = _next;
256
+ nblocks = (int)(((char*)this + bigBlockSize - (char*)first)/MEM_BLOCK_SIZE);
257
+ Block* p = 0;
258
+ for( int i = nblocks-1; i >= 0; i-- )
259
+ p = ::new((uchar*)first + i*MEM_BLOCK_SIZE) Block(p);
260
+ }
261
+
262
+ ~BigBlock()
263
+ {
264
+ for( int i = nblocks-1; i >= 0; i-- )
265
+ ((Block*)((uchar*)first+i*MEM_BLOCK_SIZE))->~Block();
266
+ }
267
+
268
+ BigBlock* next;
269
+ Block* first;
270
+ int nblocks;
271
+ };
272
+
273
+ struct BlockPool
274
+ {
275
+ BlockPool(int _bigBlockSize=1<<20) : pool(0), bigBlockSize(_bigBlockSize)
276
+ {
277
+ }
278
+
279
+ ~BlockPool()
280
+ {
281
+ AutoLock lock(cs);
282
+ while( pool )
283
+ {
284
+ BigBlock* nextBlock = pool->next;
285
+ pool->~BigBlock();
286
+ SystemFree(pool, bigBlockSize);
287
+ pool = nextBlock;
288
+ }
289
+ }
290
+
291
+ Block* alloc()
292
+ {
293
+ AutoLock lock(cs);
294
+ Block* block;
295
+ if( !freeBlocks )
296
+ {
297
+ BigBlock* bblock = ::new(SystemAlloc(bigBlockSize)) BigBlock(bigBlockSize, pool);
298
+ assert( bblock != 0 );
299
+ freeBlocks = bblock->first;
300
+ pool = bblock;
301
+ }
302
+ block = freeBlocks;
303
+ freeBlocks = freeBlocks->next;
304
+ if( freeBlocks )
305
+ freeBlocks->prev = 0;
306
+ STAT(stat.bruttoBytes += MEM_BLOCK_SIZE);
307
+ return block;
308
+ }
309
+
310
+ void free(Block* block)
311
+ {
312
+ AutoLock lock(cs);
313
+ block->prev = 0;
314
+ block->next = freeBlocks;
315
+ freeBlocks = block;
316
+ STAT(stat.bruttoBytes -= MEM_BLOCK_SIZE);
317
+ }
318
+
319
+ CriticalSection cs;
320
+ Block* freeBlocks;
321
+ BigBlock* pool;
322
+ int bigBlockSize;
323
+ int blocksPerBigBlock;
324
+ };
325
+
326
+ BlockPool mallocPool;
327
+
328
+ enum { START=0, FREE=1, GC=2 };
329
+
330
+ struct ThreadData
331
+ {
332
+ ThreadData() { for(int i = 0; i <= MAX_BIN; i++) bins[i][START] = bins[i][FREE] = bins[i][GC] = 0; }
333
+ ~ThreadData()
334
+ {
335
+ // mark all the thread blocks as abandoned or even release them
336
+ for( int i = 0; i <= MAX_BIN; i++ )
337
+ {
338
+ Block *bin = bins[i][START], *block = bin;
339
+ bins[i][START] = bins[i][FREE] = bins[i][GC] = 0;
340
+ if( block )
341
+ {
342
+ do
343
+ {
344
+ Block* next = block->next;
345
+ int allocated = block->allocated;
346
+ {
347
+ AutoLock lock(block->cs);
348
+ block->next = block->prev = 0;
349
+ block->threadData = 0;
350
+ Node *node = block->publicFreeList;
351
+ for( ; node != 0; node = node->next )
352
+ allocated--;
353
+ }
354
+ if( allocated == 0 )
355
+ mallocPool.free(block);
356
+ block = next;
357
+ }
358
+ while( block != bin );
359
+ }
360
+ }
361
+ }
362
+
363
+ void moveBlockToFreeList( Block* block )
364
+ {
365
+ int i = block->binIdx;
366
+ Block*& freePtr = bins[i][FREE];
367
+ CV_DbgAssert( block->next->prev == block && block->prev->next == block );
368
+ if( block != freePtr )
369
+ {
370
+ Block*& gcPtr = bins[i][GC];
371
+ if( gcPtr == block )
372
+ gcPtr = block->next;
373
+ if( block->next != block )
374
+ {
375
+ block->prev->next = block->next;
376
+ block->next->prev = block->prev;
377
+ }
378
+ block->next = freePtr->next;
379
+ block->prev = freePtr;
380
+ freePtr = block->next->prev = block->prev->next = block;
381
+ }
382
+ }
383
+
384
+ Block* bins[MAX_BIN+1][3];
385
+
386
+ #ifdef WIN32
387
+ #ifdef WINCE
388
+ # define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
389
+ #endif
390
+
391
+ static DWORD tlsKey;
392
+ static ThreadData* get()
393
+ {
394
+ ThreadData* data;
395
+ if( tlsKey == TLS_OUT_OF_INDEXES )
396
+ tlsKey = TlsAlloc();
397
+ data = (ThreadData*)TlsGetValue(tlsKey);
398
+ if( !data )
399
+ {
400
+ data = new ThreadData;
401
+ TlsSetValue(tlsKey, data);
402
+ }
403
+ return data;
404
+ }
405
+ #else
406
+ static void deleteData(void* data)
407
+ {
408
+ delete (ThreadData*)data;
409
+ }
410
+
411
+ static pthread_key_t tlsKey;
412
+ static ThreadData* get()
413
+ {
414
+ ThreadData* data;
415
+ if( !tlsKey )
416
+ pthread_key_create(&tlsKey, deleteData);
417
+ data = (ThreadData*)pthread_getspecific(tlsKey);
418
+ if( !data )
419
+ {
420
+ data = new ThreadData;
421
+ pthread_setspecific(tlsKey, data);
422
+ }
423
+ return data;
424
+ }
425
+ #endif
426
+ };
427
+
428
+ #ifdef WIN32
429
+ DWORD ThreadData::tlsKey = TLS_OUT_OF_INDEXES;
430
+
431
+ void deleteThreadAllocData()
432
+ {
433
+ if( ThreadData::tlsKey != TLS_OUT_OF_INDEXES )
434
+ delete (ThreadData*)TlsGetValue( ThreadData::tlsKey );
435
+ }
436
+
437
+ #else
438
+ pthread_key_t ThreadData::tlsKey = 0;
439
+ #endif
440
+
441
+ #if 0
442
+ static void checkList(ThreadData* tls, int idx)
443
+ {
444
+ Block* block = tls->bins[idx][START];
445
+ if( !block )
446
+ {
447
+ CV_DbgAssert( tls->bins[idx][FREE] == 0 && tls->bins[idx][GC] == 0 );
448
+ }
449
+ else
450
+ {
451
+ bool gcInside = false;
452
+ bool freeInside = false;
453
+ do
454
+ {
455
+ if( tls->bins[idx][FREE] == block )
456
+ freeInside = true;
457
+ if( tls->bins[idx][GC] == block )
458
+ gcInside = true;
459
+ block = block->next;
460
+ }
461
+ while( block != tls->bins[idx][START] );
462
+ CV_DbgAssert( gcInside && freeInside );
463
+ }
464
+ }
465
+ #else
466
+ #define checkList(tls, idx)
467
+ #endif
468
+
469
+ void* fastMalloc( size_t size )
470
+ {
471
+ if( size > MAX_BLOCK_SIZE )
472
+ {
473
+ size_t size1 = size + sizeof(uchar*)*2 + MEM_BLOCK_SIZE;
474
+ uchar* udata = (uchar*)SystemAlloc(size1);
475
+ uchar** adata = alignPtr((uchar**)udata + 2, MEM_BLOCK_SIZE);
476
+ adata[-1] = udata;
477
+ adata[-2] = (uchar*)size1;
478
+ return adata;
479
+ }
480
+
481
+ {
482
+ ThreadData* tls = ThreadData::get();
483
+ int idx = mallocTables.bin(size);
484
+ Block*& startPtr = tls->bins[idx][START];
485
+ Block*& gcPtr = tls->bins[idx][GC];
486
+ Block*& freePtr = tls->bins[idx][FREE], *block = freePtr;
487
+ checkList(tls, idx);
488
+ size = binSizeTab[idx];
489
+ STAT(
490
+ stat.nettoBytes += size;
491
+ stat.mallocCalls++;
492
+ );
493
+ uchar* data = 0;
494
+
495
+ for(;;)
496
+ {
497
+ if( block )
498
+ {
499
+ // try to find non-full block
500
+ for(;;)
501
+ {
502
+ CV_DbgAssert( block->next->prev == block && block->prev->next == block );
503
+ if( block->bumpPtr )
504
+ {
505
+ data = block->bumpPtr;
506
+ if( (block->bumpPtr += size) >= block->endPtr )
507
+ block->bumpPtr = 0;
508
+ break;
509
+ }
510
+
511
+ if( block->privateFreeList )
512
+ {
513
+ data = (uchar*)block->privateFreeList;
514
+ block->privateFreeList = block->privateFreeList->next;
515
+ break;
516
+ }
517
+
518
+ if( block == startPtr )
519
+ break;
520
+ block = block->next;
521
+ }
522
+ #if 0
523
+ avg_k += _k;
524
+ avg_nk++;
525
+ if( avg_nk == 1000 )
526
+ {
527
+ printf("avg search iters per 1e3 allocs = %g\n", (double)avg_k/avg_nk );
528
+ avg_k = avg_nk = 0;
529
+ }
530
+ #endif
531
+
532
+ freePtr = block;
533
+ if( !data )
534
+ {
535
+ block = gcPtr;
536
+ for( int k = 0; k < 2; k++ )
537
+ {
538
+ SANITY_CHECK(block);
539
+ CV_DbgAssert( block->next->prev == block && block->prev->next == block );
540
+ if( block->publicFreeList )
541
+ {
542
+ {
543
+ AutoLock lock(block->cs);
544
+ block->privateFreeList = block->publicFreeList;
545
+ block->publicFreeList = 0;
546
+ }
547
+ Node* node = block->privateFreeList;
548
+ for(;node != 0; node = node->next)
549
+ --block->allocated;
550
+ data = (uchar*)block->privateFreeList;
551
+ block->privateFreeList = block->privateFreeList->next;
552
+ gcPtr = block->next;
553
+ if( block->allocated+1 <= block->almostEmptyThreshold )
554
+ tls->moveBlockToFreeList(block);
555
+ break;
556
+ }
557
+ block = block->next;
558
+ }
559
+ if( !data )
560
+ gcPtr = block;
561
+ }
562
+ }
563
+
564
+ if( data )
565
+ break;
566
+ block = mallocPool.alloc();
567
+ block->init(startPtr ? startPtr->prev : block, startPtr ? startPtr : block, (int)size, tls);
568
+ if( !startPtr )
569
+ startPtr = gcPtr = freePtr = block;
570
+ checkList(tls, block->binIdx);
571
+ SANITY_CHECK(block);
572
+ }
573
+
574
+ ++block->allocated;
575
+ return data;
576
+ }
577
+ }
578
+
579
+ void fastFree( void* ptr )
580
+ {
581
+ if( ((size_t)ptr & (MEM_BLOCK_SIZE-1)) == 0 )
582
+ {
583
+ if( ptr != 0 )
584
+ {
585
+ void* origPtr = ((void**)ptr)[-1];
586
+ size_t sz = (size_t)((void**)ptr)[-2];
587
+ SystemFree( origPtr, sz );
588
+ }
589
+ return;
590
+ }
591
+
592
+ {
593
+ ThreadData* tls = ThreadData::get();
594
+ Node* node = (Node*)ptr;
595
+ Block* block = (Block*)((size_t)ptr & -(int)MEM_BLOCK_SIZE);
596
+ assert( block->signature == MEM_BLOCK_SIGNATURE );
597
+
598
+ if( block->threadData == tls )
599
+ {
600
+ STAT(
601
+ stat.nettoBytes -= block->objSize;
602
+ stat.freeCalls++;
603
+ float ratio = (float)stat.nettoBytes/stat.bruttoBytes;
604
+ if( stat.minUsageRatio > ratio )
605
+ stat.minUsageRatio = ratio;
606
+ );
607
+
608
+ SANITY_CHECK(block);
609
+
610
+ bool prevFilled = block->isFilled();
611
+ --block->allocated;
612
+ if( !block->isFilled() && (block->allocated == 0 || prevFilled) )
613
+ {
614
+ if( block->allocated == 0 )
615
+ {
616
+ int idx = block->binIdx;
617
+ Block*& startPtr = tls->bins[idx][START];
618
+ Block*& freePtr = tls->bins[idx][FREE];
619
+ Block*& gcPtr = tls->bins[idx][GC];
620
+
621
+ if( block == block->next )
622
+ {
623
+ CV_DbgAssert( startPtr == block && freePtr == block && gcPtr == block );
624
+ startPtr = freePtr = gcPtr = 0;
625
+ }
626
+ else
627
+ {
628
+ if( freePtr == block )
629
+ freePtr = block->next;
630
+ if( gcPtr == block )
631
+ gcPtr = block->next;
632
+ if( startPtr == block )
633
+ startPtr = block->next;
634
+ block->prev->next = block->next;
635
+ block->next->prev = block->prev;
636
+ }
637
+ mallocPool.free(block);
638
+ checkList(tls, idx);
639
+ return;
640
+ }
641
+
642
+ tls->moveBlockToFreeList(block);
643
+ }
644
+ node->next = block->privateFreeList;
645
+ block->privateFreeList = node;
646
+ }
647
+ else
648
+ {
649
+ AutoLock lock(block->cs);
650
+ SANITY_CHECK(block);
651
+
652
+ node->next = block->publicFreeList;
653
+ block->publicFreeList = node;
654
+ if( block->threadData == 0 )
655
+ {
656
+ // take ownership of the abandoned block.
657
+ // note that it can happen at the same time as
658
+ // ThreadData::deleteData() marks the blocks as abandoned,
659
+ // so this part of the algorithm needs to be checked for data races
660
+ int idx = block->binIdx;
661
+ block->threadData = tls;
662
+ Block*& startPtr = tls->bins[idx][START];
663
+
664
+ if( startPtr )
665
+ {
666
+ block->next = startPtr;
667
+ block->prev = startPtr->prev;
668
+ block->next->prev = block->prev->next = block;
669
+ }
670
+ else
671
+ startPtr = tls->bins[idx][FREE] = tls->bins[idx][GC] = block;
672
+ }
673
+ }
674
+ }
675
+ }
676
+
677
+ #endif
678
+
679
+ }
680
+
681
+ CV_IMPL void cvSetMemoryManager( CvAllocFunc, CvFreeFunc, void * )
682
+ {
683
+ CV_Error( -1, "Custom memory allocator is not supported" );
684
+ }
685
+
686
+ CV_IMPL void* cvAlloc( size_t size )
687
+ {
688
+ return cv::fastMalloc( size );
689
+ }
690
+
691
+ CV_IMPL void cvFree_( void* ptr )
692
+ {
693
+ cv::fastFree( ptr );
694
+ }
695
+
696
+
697
+ /* End of file. */