imagecore 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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. */