1 /***************************************************************************
2 
3         Very simple OCR engine
4 
5         We do it in 3 passes
6 
7                 Ask the vobsub decoder for a bitmap
8                 Try to split the bitmap in lines
9                 For each lines try to split in glyph (i.e. horizontal line)
10                 Detour the glyph
11                 If the detoured glyph has a width much less inferiror to its width
12                 it probably means we have a italic or kerning.
13                 In that case use the detouring to isolate the glyphs
14 
15 
16          A bit of warning.
17                         The UI code is ugly.
18                         Bottom is the last actual line so to get height you have to to last-first +1 !
19 
20     begin                : Jan 2005
21     copyright            : (C) 2002 by mean
22     email                : fixounet@free.fr
23  ***************************************************************************/
24 
25 /***************************************************************************
26  *                                                                         *
27  *   This program is free software; you can redistribute it and/or modify  *
28  *   it under the terms of the GNU General Public License as published by  *
29  *   the Free Software Foundation; either version 2 of the License, or     *
30  *   (at your option) any later version.                                   *
31  *                                                                         *
32  ***************************************************************************/
33 #include "ADM_toolkitGtk.h"
34 
35 #include "DIA_coreToolkit.h"
36 #include "ADM_editor/ADM_edit.hxx"
37 #include "DIA_fileSel.h"
38 
39 #if 0
40 //#include "ADM_videoFilter/ADM_vobsubinfo.h"
41 //#include "ADM_videoFilter/ADM_vidVobSub.h"
42 #include "ADM_ocr/ADM_leftturn.h"
43 #include "DIA_enter.h"
44 
45 #include "ADM_ocr/ADM_ocr.h"
46 #include "ADM_ocr/ADM_ocrInternal.h"
47 /******************************/
48 
49 #define TESTSUB "/home/fx/usbstick/subs/vts_01_0.idx"
50 #define CONNECT(x,y,z) 	gtk_signal_connect(GTK_OBJECT(WID(x)), #y,GTK_SIGNAL_FUNC(z),   NULL);
51 
52 
53 /* Minimal size of the current glyph display window */
54 #define MAX_W 65
55 #define MAX_H 65
56 
57 
58 extern  uint8_t DIA_vobsub(vobSubParam *param);
59 //********************************************
60 extern  GtkWidget *DIA_ocr(void);
61 
62 
63 //********************************************
64 
65 
66 
67 
68 typedef enum
69 {
70     actionLoadVob=10,
71     actionSaveSub,
72     actionGo,
73     actionLoadGlyph,
74     actionSaveGlyph,
75     actionSkip,
76     actionSkipAll,
77     actionAccept,
78     actionIgnore,
79     actionCalibrate
80 }ocrAction;
81 
82 
83 /************************ UI Dependant part ********************/
84 /**
85         Search throught the existing glyphs , if not present create it
86         and append the text to decodedString
87 */
88 
89 static GtkWidget *dialog=NULL;
90 static GtkWidget *mainDisplay=NULL;
91 static GtkWidget *smallDisplay=NULL;
92 
93 static uint32_t clipW=0,clipH=0;
94 
95 static gboolean   gui_draw( void );
96 static gboolean   gui_draw_small( void );
97 static void       displaySmall( admGlyph *glyph );
98 static int        cb_accept(GtkObject * object, gpointer user_data);
99 
100 
101 ReplyType glyphToText(admGlyph *glyph,admGlyph *head,char *decodedString)
102 {
103  admGlyph *cand;
104             //printf("2t: %d x %d\n",glyph->width,glyph->height);
105             if(glyph->width<2 && glyph->height<2)
106             {
107                 delete glyph;
108                 return ReplyOk;
109             }
110             cand=searchGlyph(head,glyph);
111             if(!cand) // New glyph
112             {
113                 char *string;
114                 // Draw it
115                 displaySmall(glyph);
116                 gtk_label_set_text(GTK_LABEL(WID(labelText)),decodedString);
117                 gtk_editable_delete_text(GTK_EDITABLE(WID(entry)), 0,-1);
118 
119                 //gtk_widget_set_sensitive(WID(buttonAccept),1);
120                 //gtk_widget_set_sensitive(WID(buttonSkip),1);
121                 //gtk_widget_set_sensitive(WID(entryEntry),1);
122 
123                 gtk_widget_grab_focus (WID(entry));
124                 gtk_widget_grab_default (WID(buttonOk));
125 
126                 //printf("i\n");
127                 switch(gtk_dialog_run(GTK_DIALOG(dialog)))
128                 {
129                 case actionIgnore:
130                         glyph->code=NULL;
131                         insertInGlyphTree(head,glyph);
132                         //*nbGl++;
133                         break;
134                 case actionCalibrate: return ReplyCalibrate;
135                 case actionAccept:
136                     string =gtk_editable_get_chars(GTK_EDITABLE (WID(entry)), 0, -1);
137                     if(string&& strlen(string))
138                     {
139                         glyph->code=ADM_strdup(string);
140                         insertInGlyphTree(head,glyph);
141                         //printf("New glyph:%s\n",glyph->code);
142                         strcat(decodedString,glyph->code);
143                         //*nbGl++;
144 
145                     }
146                     else delete glyph;
147                     break;
148                 case actionSkip: //SKIP
149                     return ReplySkip;
150                     break;
151                 case actionSkipAll:
152                     return ReplySkipAll;
153                     break;
154                 case GTK_RESPONSE_CLOSE:
155                   if(GUI_Question(QT_TR_NOOP("Sure ?"))) return ReplyClose;
156                     break; // Abort
157 
158                 }
159                 gtk_editable_delete_text(GTK_EDITABLE(WID(entry)), 0,-1);
160                 //gtk_widget_set_sensitive(WID(buttonAccept),0);
161                 //gtk_widget_set_sensitive(WID(buttonSkip),0);
162                 //gtk_widget_set_sensitive(WID(entryEntry),0);
163             }
164             else
165             {
166                 //printf("Glyph known :%s \n",cand->code);
167                 if(cand->code)
168                     strcat(decodedString,cand->code);
169                 delete glyph;
170             }
171            return ReplyOk;
172 
173 }
174 static int sx=0,sy=0,sw=0,sh=0;
175 static int redraw_x=0,redraw_y=0;
176 static uint8_t *drawing=NULL;
177 static uint8_t *sdata=NULL;
178 uint8_t ADM_ocrSetRedrawSize(void *ui,uint32_t w,uint32_t h)
179 {
180 		redraw_x=w;
181 		redraw_y=h;
182 		return 1;
183 }
184 
185 //*****************************************************************************************
186 gboolean gui_draw( void )
187 {
188 static int lastx=0,lasty=0;
189 	if(!drawing) return true;
190     if(lastx!=redraw_x || lasty!=redraw_y)
191         gtk_widget_set_usize(mainDisplay, redraw_x, redraw_y);
192     lastx=redraw_x;
193     lasty=redraw_y;
194 
195     gdk_draw_gray_image(mainDisplay->window, mainDisplay->style->fg_gc[GTK_STATE_NORMAL],
196                         0,                          // X
197                         0,                          // y
198                         redraw_x,                          //width
199                         redraw_y,                          //h*2, // heigth
200                         GDK_RGB_DITHER_NONE,
201                         drawing, // buffer
202                         redraw_x );
203     return true;
204 }
205 //*****************************************************************************************
206 
207 void displaySmall( admGlyph *glyph)
208 {
209     if(sw!=glyph->width || sh!=glyph->height)
210     {
211 
212         if(sdata) delete [] sdata;
213         sdata=NULL;
214         sw=glyph->width;
215         sh=glyph->height;
216         sdata=new uint8_t[(sw*2+2)*(sh*2+2)];
217         clipW= sw*2+2;
218         clipH=  sh*2+2;
219 #ifndef MAX
220         #define MAX(a,b) a>b?a:b
221 #endif
222         clipW=MAX(MAX_W,clipW);
223         clipH=MAX(MAX_H,clipH);
224         gtk_widget_set_usize(smallDisplay, clipW,clipH);
225     }
226     uint32_t stride=sw*2+2;
227     uint8_t *in=glyph->data;
228     uint8_t *out=sdata;
229 
230     memset(out,0,stride);
231     out+=stride;
232     for(uint32_t y=0;y<sh;y++)
233     {
234       *(out++)=0;
235       for(uint32_t x=0;x<sw;x++)
236       {
237         out[1]=out[0]=out[stride]=out[stride+1]=*in;
238         out+=2;
239         in++;
240 
241       }
242       *(out++)=0;
243       out+=stride;
244     }
245     memset(out,0,stride);
246     //memcpy(sdata,glyph->data,sw*sh);
247     gui_draw_small();
248 }
249 
250 gboolean gui_draw_small(void)
251 {
252 	if(clipW && clipH)
253 	{
254 		 gdk_draw_rectangle(smallDisplay->window,
255 				 				smallDisplay->style->fg_gc[GTK_STATE_NORMAL],
256 				 				1, // Filled
257 		                        0,                          // X
258 		                        0,                          // y
259 		                        clipW,
260 		                        clipH);
261 
262 
263 	}
264  if(sw && sh && sdata)
265  {
266     gdk_draw_gray_image(smallDisplay->window, smallDisplay->style->fg_gc[GTK_STATE_NORMAL],
267                         1,                          // X
268                         1,                          // y
269                         sw*2+1,                          //width
270                         sh*2+1,                          //h*2, // heigth
271                         GDK_RGB_DITHER_NONE,
272                         sdata, // buffer
273                         sw*2+2 );
274  }
275     return true;
276 }
277 
278 
279 /**
280     \fn cb_accept
281     \brief Bridge between dialog/Accept and gtk signals
282 */
283 int cb_accept(GtkObject * object, gpointer user_data)
284 {
285         //printf("Hopla\n");
286         gtk_signal_emit_by_name(GTK_OBJECT(WID(buttonOk)),"clicked",(gpointer)1);
287         return 0;
288 }
289 uint8_t ADM_ocrUpdateNbLines(void *ui,uint32_t cur,uint32_t total)
290 {
291 char text[50];
292          snprintf(text,50,"%03d/%03d",cur,total);
293          gtk_label_set_text(GTK_LABEL(WID(labelNbLines)),text);
294          return 1;
295 }
296 uint8_t ADM_ocrUpdateNbGlyphs(void *ui,uint32_t nbGlyphs)
297 {
298 char text[50];
299          snprintf(text,50,"%03d",nbGlyphs);
300          gtk_label_set_text(GTK_LABEL(WID(labelNbGlyphs)),text);
301          return 1;
302 }
303 uint8_t ADM_ocrUpdateTextAndTime(void *ui,char *decodedString,char *timeCode)
304 {
305              gtk_label_set_text(GTK_LABEL(WID(labelText)),decodedString);
306              gtk_label_set_text(GTK_LABEL(WID(labelTime)),timeCode);
307              return 1;
308 }
309 uint8_t ADM_ocrDrawFull(void *d,uint8_t *data)
310 {
311 		    drawing=data;;
312 			UI_purge();
313              gui_draw();
314              UI_purge();
315              return 1;
316 }
317 
318 uint8_t ADM_ocrUiEnd(void *d)
319 {
320 	GtkWidget *dialog=(GtkWidget *)d;
321 	ADM_assert(dialog);
322 		// Final round
323 	    gtk_widget_set_sensitive(WID(frameBitmap),0);
324 	   // gtk_widget_set_sensitive(WID(Current_Glyph),0);
325 
326 
327 	    gtk_unregister_dialog(dialog);
328 	    gtk_widget_destroy(dialog);
329 
330 }
331 void *ADM_ocrUiSetup(void)
332 {
333 	// Create UI && prepare callback
334 	 	dialog=NULL;
335 	    mainDisplay=NULL;
336 	    smallDisplay=NULL;
337 	    drawing=NULL;
338 	    sdata=NULL;
339 	    clipW=0;
340 	    clipH=0;
341 	    dialog=DIA_ocr();
342 	    gtk_register_dialog(dialog);
343 	#define ASSOCIATE(x,y)   gtk_dialog_add_action_widget (GTK_DIALOG (dialog), WID(x),y)
344 
345 	    ASSOCIATE(buttonOk,   actionAccept);
346 	    ASSOCIATE(buttonSkip,     actionSkip);
347 	    ASSOCIATE(buttonSkipAll,     actionSkipAll);
348 	    ASSOCIATE(buttonIgnore,   actionIgnore);
349 	    ASSOCIATE(buttonCalibrate,   actionCalibrate);
350 
351 
352 	    gtk_widget_show(dialog);
353 	    //
354 
355 	//  disable
356 
357 	    mainDisplay=WID(drawingareaBitmap);
358 	    smallDisplay=WID(drawingareaSmall);
359 
360 
361 
362 	    CONNECT(drawingareaBitmap,expose_event,gui_draw);
363 	    CONNECT(drawingareaSmall,expose_event,gui_draw_small);
364 
365 	    CONNECT(entry,activate,cb_accept);
366 	    return (void *)dialog;
367 
368 }
369 #endif
370 //;
371