Skip to content

Commit cb2957b

Browse files
committed
Replace callback by direct function calls in TessBaseAPI::GetComponentImages
The new code avoids dynamic memory allocation, uses faster function calls and allows removing more code from tesscallback.h. Signed-off-by: Stefan Weil <[email protected]>
1 parent 3159f42 commit cb2957b

File tree

2 files changed

+20
-215
lines changed

2 files changed

+20
-215
lines changed

src/api/baseapi.cpp

+20-14
Original file line numberDiff line numberDiff line change
@@ -707,24 +707,23 @@ Boxa* TessBaseAPI::GetComponentImages(PageIteratorLevel level,
707707
int component_count = 0;
708708
int left, top, right, bottom;
709709

710-
TessResultCallback<bool>* get_bbox = nullptr;
711710
if (raw_image) {
712711
// Get bounding box in original raw image with padding.
713-
get_bbox = NewPermanentTessCallback(page_it, &PageIterator::BoundingBox,
714-
level, raw_padding,
715-
&left, &top, &right, &bottom);
712+
do {
713+
if (page_it->BoundingBox(level, raw_padding,
714+
&left, &top, &right, &bottom) &&
715+
(!text_only || PTIsTextType(page_it->BlockType())))
716+
++component_count;
717+
} while (page_it->Next(level));
716718
} else {
717719
// Get bounding box from binarized imaged. Note that this could be
718720
// differently scaled from the original image.
719-
get_bbox = NewPermanentTessCallback(page_it,
720-
&PageIterator::BoundingBoxInternal,
721-
level, &left, &top, &right, &bottom);
721+
do {
722+
if (page_it->BoundingBoxInternal(level, &left, &top, &right, &bottom) &&
723+
(!text_only || PTIsTextType(page_it->BlockType())))
724+
++component_count;
725+
} while (page_it->Next(level));
722726
}
723-
do {
724-
if (get_bbox->Run() &&
725-
(!text_only || PTIsTextType(page_it->BlockType())))
726-
++component_count;
727-
} while (page_it->Next(level));
728727

729728
Boxa* boxa = boxaCreate(component_count);
730729
if (pixa != nullptr)
@@ -739,7 +738,15 @@ Boxa* TessBaseAPI::GetComponentImages(PageIteratorLevel level,
739738
int component_index = 0;
740739
page_it->Begin();
741740
do {
742-
if (get_bbox->Run() &&
741+
bool got_bounding_box;
742+
if (raw_image) {
743+
got_bounding_box =
744+
page_it->BoundingBox(level, raw_padding, &left, &top, &right, &bottom);
745+
} else {
746+
got_bounding_box =
747+
page_it->BoundingBoxInternal(level, &left, &top, &right, &bottom);
748+
}
749+
if (got_bounding_box &&
743750
(!text_only || PTIsTextType(page_it->BlockType()))) {
744751
Box* lbox = boxCreate(left, top, right - left, bottom - top);
745752
boxaAddBox(boxa, lbox, L_INSERT);
@@ -770,7 +777,6 @@ Boxa* TessBaseAPI::GetComponentImages(PageIteratorLevel level,
770777
}
771778
} while (page_it->Next(level));
772779
delete page_it;
773-
delete get_bbox;
774780
return boxa;
775781
}
776782

src/ccutil/tesscallback.h

-201
Original file line numberDiff line numberDiff line change
@@ -169,207 +169,6 @@ struct Identity {
169169
using type = T;
170170
};
171171

172-
template <bool del, class R, class T, class P1, class P2, class P3, class P4,
173-
class P5>
174-
class _ConstTessMemberResultCallback_5_0 : public TessResultCallback<R> {
175-
public:
176-
using base = TessResultCallback<R>;
177-
using MemberSignature = R (T::*)(P1, P2, P3, P4, P5) const;
178-
179-
private:
180-
const T* object_;
181-
MemberSignature member_;
182-
typename remove_reference<P1>::type p1_;
183-
typename remove_reference<P2>::type p2_;
184-
typename remove_reference<P3>::type p3_;
185-
typename remove_reference<P4>::type p4_;
186-
typename remove_reference<P5>::type p5_;
187-
188-
public:
189-
inline _ConstTessMemberResultCallback_5_0(const T* object,
190-
MemberSignature member, P1 p1,
191-
P2 p2, P3 p3, P4 p4, P5 p5)
192-
: object_(object),
193-
member_(member),
194-
p1_(p1),
195-
p2_(p2),
196-
p3_(p3),
197-
p4_(p4),
198-
p5_(p5) {}
199-
200-
R Run() override {
201-
if (!del) {
202-
R result = (object_->*member_)(p1_, p2_, p3_, p4_, p5_);
203-
return result;
204-
}
205-
R result = (object_->*member_)(p1_, p2_, p3_, p4_, p5_);
206-
// zero out the pointer to ensure segfault if used again
207-
member_ = nullptr;
208-
delete this;
209-
return result;
210-
}
211-
};
212-
213-
template <bool del, class T, class P1, class P2, class P3, class P4, class P5>
214-
class _ConstTessMemberResultCallback_5_0<del, void, T, P1, P2, P3, P4, P5>
215-
: public TessClosure {
216-
public:
217-
using base = TessClosure;
218-
using MemberSignature = void (T::*)(P1, P2, P3, P4, P5) const;
219-
220-
private:
221-
const T* object_;
222-
MemberSignature member_;
223-
typename remove_reference<P1>::type p1_;
224-
typename remove_reference<P2>::type p2_;
225-
typename remove_reference<P3>::type p3_;
226-
typename remove_reference<P4>::type p4_;
227-
typename remove_reference<P5>::type p5_;
228-
229-
public:
230-
inline _ConstTessMemberResultCallback_5_0(const T* object,
231-
MemberSignature member, P1 p1,
232-
P2 p2, P3 p3, P4 p4, P5 p5)
233-
: object_(object),
234-
member_(member),
235-
p1_(p1),
236-
p2_(p2),
237-
p3_(p3),
238-
p4_(p4),
239-
p5_(p5) {}
240-
241-
void Run() override {
242-
if (!del) {
243-
(object_->*member_)(p1_, p2_, p3_, p4_, p5_);
244-
} else {
245-
(object_->*member_)(p1_, p2_, p3_, p4_, p5_);
246-
// zero out the pointer to ensure segfault if used again
247-
member_ = nullptr;
248-
delete this;
249-
}
250-
}
251-
};
252-
253-
#ifndef SWIG
254-
template <class T1, class T2, class R, class P1, class P2, class P3, class P4,
255-
class P5>
256-
inline typename _ConstTessMemberResultCallback_5_0<false, R, T1, P1, P2, P3, P4,
257-
P5>::base*
258-
NewPermanentTessCallback(const T1* obj,
259-
R (T2::*member)(P1, P2, P3, P4, P5) const,
260-
typename Identity<P1>::type p1,
261-
typename Identity<P2>::type p2,
262-
typename Identity<P3>::type p3,
263-
typename Identity<P4>::type p4,
264-
typename Identity<P5>::type p5) {
265-
return new _ConstTessMemberResultCallback_5_0<false, R, T1, P1, P2, P3, P4,
266-
P5>(obj, member, p1, p2, p3, p4,
267-
p5);
268-
}
269-
#endif
270-
271-
template <bool del, class R, class T, class P1, class P2, class P3, class P4,
272-
class P5, class P6>
273-
class _ConstTessMemberResultCallback_6_0 : public TessResultCallback<R> {
274-
public:
275-
using base = TessResultCallback<R>;
276-
using MemberSignature = R (T::*)(P1, P2, P3, P4, P5, P6) const;
277-
278-
private:
279-
const T* object_;
280-
MemberSignature member_;
281-
typename remove_reference<P1>::type p1_;
282-
typename remove_reference<P2>::type p2_;
283-
typename remove_reference<P3>::type p3_;
284-
typename remove_reference<P4>::type p4_;
285-
typename remove_reference<P5>::type p5_;
286-
typename remove_reference<P6>::type p6_;
287-
288-
public:
289-
inline _ConstTessMemberResultCallback_6_0(const T* object,
290-
MemberSignature member, P1 p1,
291-
P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
292-
: object_(object),
293-
member_(member),
294-
p1_(p1),
295-
p2_(p2),
296-
p3_(p3),
297-
p4_(p4),
298-
p5_(p5),
299-
p6_(p6) {}
300-
301-
R Run() override {
302-
if (!del) {
303-
R result = (object_->*member_)(p1_, p2_, p3_, p4_, p5_, p6_);
304-
return result;
305-
}
306-
R result = (object_->*member_)(p1_, p2_, p3_, p4_, p5_, p6_);
307-
// zero out the pointer to ensure segfault if used again
308-
member_ = nullptr;
309-
delete this;
310-
return result;
311-
}
312-
};
313-
314-
template <bool del, class T, class P1, class P2, class P3, class P4, class P5,
315-
class P6>
316-
class _ConstTessMemberResultCallback_6_0<del, void, T, P1, P2, P3, P4, P5, P6>
317-
: public TessClosure {
318-
public:
319-
using base = TessClosure;
320-
using MemberSignature = void (T::*)(P1, P2, P3, P4, P5, P6) const;
321-
322-
private:
323-
const T* object_;
324-
MemberSignature member_;
325-
typename remove_reference<P1>::type p1_;
326-
typename remove_reference<P2>::type p2_;
327-
typename remove_reference<P3>::type p3_;
328-
typename remove_reference<P4>::type p4_;
329-
typename remove_reference<P5>::type p5_;
330-
typename remove_reference<P6>::type p6_;
331-
332-
public:
333-
inline _ConstTessMemberResultCallback_6_0(const T* object,
334-
MemberSignature member, P1 p1,
335-
P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
336-
: object_(object),
337-
member_(member),
338-
p1_(p1),
339-
p2_(p2),
340-
p3_(p3),
341-
p4_(p4),
342-
p5_(p5),
343-
p6_(p6) {}
344-
345-
void Run() override {
346-
if (!del) {
347-
(object_->*member_)(p1_, p2_, p3_, p4_, p5_, p6_);
348-
} else {
349-
(object_->*member_)(p1_, p2_, p3_, p4_, p5_, p6_);
350-
// zero out the pointer to ensure segfault if used again
351-
member_ = nullptr;
352-
delete this;
353-
}
354-
}
355-
};
356-
357-
#ifndef SWIG
358-
template <class T1, class T2, class R, class P1, class P2, class P3, class P4,
359-
class P5, class P6>
360-
inline typename _ConstTessMemberResultCallback_6_0<false, R, T1, P1, P2, P3, P4,
361-
P5, P6>::base*
362-
NewPermanentTessCallback(
363-
const T1* obj, R (T2::*member)(P1, P2, P3, P4, P5, P6) const,
364-
typename Identity<P1>::type p1, typename Identity<P2>::type p2,
365-
typename Identity<P3>::type p3, typename Identity<P4>::type p4,
366-
typename Identity<P5>::type p5, typename Identity<P6>::type p6) {
367-
return new _ConstTessMemberResultCallback_6_0<false, R, T1, P1, P2, P3, P4,
368-
P5, P6>(obj, member, p1, p2, p3,
369-
p4, p5, p6);
370-
}
371-
#endif
372-
373172
template <class A1>
374173
class TessCallback1 {
375174
public:

0 commit comments

Comments
 (0)