|
1 #include "Page.h" // Inclou pam.h |
|
2 #include "Bitmap.h" |
|
3 #include <stdio.h> |
|
4 #include <string.h> |
|
5 #include <math.h> |
|
6 #include "Errors.h" |
|
7 |
|
8 Page::Page(const char *filename) |
|
9 { |
|
10 map = NULL; |
|
11 hist = NULL; |
|
12 text = NULL; |
|
13 readMap(filename); |
|
14 } |
|
15 |
|
16 Page::~Page() |
|
17 { |
|
18 delete map; |
|
19 } |
|
20 |
|
21 void Page::readMap(const char *filename) |
|
22 { |
|
23 FILE *fp; |
|
24 int i,j; |
|
25 char *image; // FIXME: Good type |
|
26 tuple *tuplerow; |
|
27 |
|
28 if (!strcmp(filename, "-")) |
|
29 fp = stdin; |
|
30 else |
|
31 // FIXME: exception |
|
32 |
|
33 if(!(fp = fopen(filename,"r"))) |
|
34 Errors::Fatal("Cannot open filename."); |
|
35 |
|
36 // Si existia un mapa, el borrem. |
|
37 if(map != NULL) |
|
38 delete map; |
|
39 |
|
40 pnm_readpaminit(fp, &pamImage, sizeof(pamImage)); |
|
41 // FIXME: Read ok |
|
42 |
|
43 width = pamImage.width; |
|
44 height = pamImage.height; |
|
45 |
|
46 map = new Bitmap(width,height); |
|
47 tuplerow = pnm_allocpamrow(&pamImage); |
|
48 |
|
49 |
|
50 for (i=0; i<height; i++) |
|
51 { |
|
52 pnm_readpamrow(&pamImage, tuplerow); |
|
53 for (j=0; j<width; j++) |
|
54 { |
|
55 // We only read the first sample (changing 0 and 1) |
|
56 map->pixels[i][j] = tuplerow[j][0]?0:1; |
|
57 } |
|
58 } |
|
59 pnm_freepamrow(tuplerow); |
|
60 |
|
61 fclose(fp); |
|
62 } |
|
63 |
|
64 void Page::writeMap(const char *filename) const |
|
65 { |
|
66 pam outpam; |
|
67 FILE *fp; |
|
68 tuple *tuplerow; |
|
69 int i,j; |
|
70 |
|
71 outpam = pamImage; |
|
72 outpam.width = width; |
|
73 outpam.height = height; |
|
74 |
|
75 fprintf(stderr,"Writting %s: w:%i,h:%i\n", filename, width, height); |
|
76 |
|
77 if (!strcmp(filename, "-")) |
|
78 fp = stdout; |
|
79 else |
|
80 // FIXME: exception |
|
81 |
|
82 if(!(fp = fopen(filename,"w"))) |
|
83 Errors::Fatal("Cannot open filename."); |
|
84 |
|
85 outpam.file = fp; |
|
86 |
|
87 pnm_writepaminit(&outpam); |
|
88 |
|
89 tuplerow = pnm_allocpamrow(&outpam); |
|
90 |
|
91 for (i=0; i<height; i++) |
|
92 { |
|
93 for (j=0; j<width; j++) |
|
94 { |
|
95 // We only write the first sample (changing 0 and 1) |
|
96 tuplerow[j][0] = map->pixels[i][j]?0:1; |
|
97 } |
|
98 pnm_writepamrow(&outpam, tuplerow); |
|
99 } |
|
100 pnm_freepamrow(tuplerow); |
|
101 |
|
102 fclose(fp); |
|
103 } |
|
104 |
|
105 /* |
|
106 static void Page::Initialize() |
|
107 { |
|
108 pnm_init(NULL,NULL); |
|
109 } |
|
110 */ |
|
111 |
|
112 float Page::ratioBlackWhite() const |
|
113 { |
|
114 int i,j; |
|
115 float white=0, black=0; |
|
116 |
|
117 for(i=0; i<height; i++) |
|
118 for (j=0; j<width; j++) |
|
119 if (map->pixels[i][j] == 0) |
|
120 white++; |
|
121 else |
|
122 black++; |
|
123 return black/white; |
|
124 } |
|
125 |
|
126 void Page::calcHistogram() |
|
127 { |
|
128 if (hist!=NULL) |
|
129 delete hist; |
|
130 |
|
131 map->calcHistogram(hist); |
|
132 } |
|
133 |
|
134 void Page::rotateMap(float angle) |
|
135 { |
|
136 Bitmap *newmap; |
|
137 rotateMap(angle, newmap); |
|
138 |
|
139 // Interchange maps: New -> Page's |
|
140 delete map; |
|
141 map = newmap; |
|
142 |
|
143 height = map->get_height(); |
|
144 width = map->get_width(); |
|
145 } |
|
146 |
|
147 void Page::rotateMap(float angle, Bitmap* &mapNew) |
|
148 { |
|
149 // Code taken from OCRchie |
|
150 int nx,ny,newheight,newwidth,oldheight,oldwidth,i,j,halfnewheight,halfnewwidth; |
|
151 int halfoldheight,halfoldwidth; |
|
152 double radians; |
|
153 double cosval,sinval; |
|
154 |
|
155 radians = -(angle) / ((180 / 3.142)); |
|
156 cosval = cos(radians); |
|
157 sinval = sin(radians); |
|
158 |
|
159 oldheight = height; |
|
160 oldwidth = width; |
|
161 |
|
162 newwidth = (int)abs((int)(oldwidth*cosval)) + (int)abs((int)(oldheight*sinval)); |
|
163 newheight = (int)abs((int)(-oldwidth*sinval)) + (int)abs((int)(oldheight*cosval)); |
|
164 |
|
165 halfnewheight = newheight / 2; |
|
166 halfnewwidth = newwidth / 2; |
|
167 halfoldwidth = oldwidth /2; |
|
168 halfoldheight = oldheight /2 ; |
|
169 |
|
170 int num_chars = (newwidth / 8) + 1; |
|
171 |
|
172 mapNew = new Bitmap(newwidth,newheight); |
|
173 mapNew->setToZero(); |
|
174 |
|
175 for(i=0;i < newheight;i++) |
|
176 { |
|
177 for(j=0;j < newwidth;j++) |
|
178 { |
|
179 nx =(int)( (j - halfnewwidth)*cosval + (i-halfnewheight)*sinval); |
|
180 ny =(int)( -((j - halfnewwidth)*sinval) + (i - halfnewheight)*cosval); |
|
181 nx = nx + halfoldwidth; |
|
182 ny = ny + halfoldheight; |
|
183 if ((nx < oldwidth) && (ny < oldheight) && (nx > 0) && (ny > 0)) |
|
184 { |
|
185 mapNew->pixels[i][j] = map->pixels[ny][nx]; |
|
186 } |
|
187 else |
|
188 { |
|
189 mapNew->pixels[i][j] = 0; |
|
190 } |
|
191 } |
|
192 } |
|
193 |
|
194 |
|
195 } |
|
196 |
|
197 void Page::tryAngles(float min, float max, float step) |
|
198 { |
|
199 float i; |
|
200 float std_dev; |
|
201 |
|
202 |
|
203 for(i=min; i<=max; i+=step) |
|
204 { |
|
205 std_dev = std_dev_lines_angle(i); |
|
206 fprintf(stderr, "Angle: %f, Dev: %f\n", i, |
|
207 std_dev); |
|
208 } |
|
209 } |
|
210 |
|
211 float Page::std_dev_lines_angle(float angle) |
|
212 { |
|
213 float retval; |
|
214 |
|
215 Bitmap *tmpmap; |
|
216 Histogram *tmphist; |
|
217 |
|
218 |
|
219 if (angle == 0) |
|
220 { |
|
221 map->calcHistogram(tmphist); |
|
222 } |
|
223 else |
|
224 { |
|
225 rotateMap(angle,tmpmap); |
|
226 tmpmap->calcHistogram(tmphist); |
|
227 delete tmpmap; |
|
228 } |
|
229 |
|
230 retval = tmphist->get_std_dev(); |
|
231 |
|
232 delete tmphist; |
|
233 |
|
234 return retval; |
|
235 } |
|
236 |
|
237 float Page::getSkew(int depth, float margin) |
|
238 { |
|
239 float x1,x2,x3; |
|
240 float y1,y2,y3; |
|
241 float newx, newy; |
|
242 int i; |
|
243 |
|
244 x1 = -margin; |
|
245 x2 = 0; |
|
246 x3 = margin; |
|
247 |
|
248 /* Bret's Method */ |
|
249 /* |
|
250 for (i=0; i<depth; i++) |
|
251 { |
|
252 y1 = std_dev_lines_angle(x1); |
|
253 y2 = std_dev_lines_angle(x2); |
|
254 y3 = std_dev_lines_angle(x3); |
|
255 fprintf(stderr, "New stddevs: %f, %f, %f\n", y1, y2, y3); |
|
256 |
|
257 newx = x2 - 0.5 * ((x2-x1)*(x2-x1) * (y2-y3) - |
|
258 (x2-x3)*(x2-x3) * (y2-y1)) / |
|
259 ((x2-x1) * (y2-y3) - (x2-x3) * (y2-y1)); |
|
260 |
|
261 // Comprovacions |
|
262 |
|
263 // Resultat |
|
264 if (newx > x1 && newx < x2) |
|
265 { |
|
266 x3 = x2; |
|
267 x2 = newx; |
|
268 } |
|
269 else if (newx > x2 && newx < x3) |
|
270 { |
|
271 x1 = x2; |
|
272 x2 = newx; |
|
273 } |
|
274 else |
|
275 Errors::Fatal("No convergence!"); |
|
276 fprintf(stderr, "Nous punts: %f, %f, %f\n", x1,x2,x3); |
|
277 } |
|
278 */ |
|
279 |
|
280 /* Golden Slice */ |
|
281 y1 = std_dev_lines_angle(x1); |
|
282 y2 = std_dev_lines_angle(x2); |
|
283 y3 = std_dev_lines_angle(x3); |
|
284 |
|
285 for (i=0; i<depth; i++) |
|
286 { |
|
287 |
|
288 // Flanc esquerra |
|
289 newx = (x2+x1)/2; |
|
290 newy = std_dev_lines_angle(newx); |
|
291 |
|
292 // Resultat |
|
293 if (newy < y2 ) |
|
294 { |
|
295 x1 = newx; |
|
296 y1 = newy; |
|
297 } |
|
298 else // newy < y2 |
|
299 { |
|
300 x3 = x2; |
|
301 y3 = y2; |
|
302 x2 = newx; |
|
303 y2 = newy; |
|
304 } |
|
305 |
|
306 // Flanc dret |
|
307 newx = (x3+x2)/2; |
|
308 newy = std_dev_lines_angle(newx); |
|
309 |
|
310 // Resultat |
|
311 if (newy < y2 ) |
|
312 { |
|
313 x3 = newx; |
|
314 y3 = newy; |
|
315 } |
|
316 else // newy < y2 |
|
317 { |
|
318 x1 = x2; |
|
319 y1 = y2; |
|
320 x2 = newx; |
|
321 y2 = newy; |
|
322 } |
|
323 fprintf(stderr, "Nous punts: %f, %f, %f\n", x1,x2,x3); |
|
324 } |
|
325 return x2; |
|
326 } |
|
327 |
|
328 void Page::getText() |
|
329 { |
|
330 if (text == NULL) |
|
331 text = new Text(); |
|
332 |
|
333 text->getLines(map); |
|
334 } |