1 /*====================================================================*
2  -  Copyright (C) 2001 Leptonica.  All rights reserved.
3  -
4  -  Redistribution and use in source and binary forms, with or without
5  -  modification, are permitted provided that the following conditions
6  -  are met:
7  -  1. Redistributions of source code must retain the above copyright
8  -     notice, this list of conditions and the following disclaimer.
9  -  2. Redistributions in binary form must reproduce the above
10  -     copyright notice, this list of conditions and the following
11  -     disclaimer in the documentation and/or other materials
12  -     provided with the distribution.
13  -
14  -  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  -  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  -  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  -  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ANY
18  -  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  -  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  -  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  -  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  -  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  -  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
27 /*
28  * ptra1_reg.c
29  *
30  *    Testing basic ptra operations
31  */
32 
33 #include "allheaders.h"
34 
35 static void MakePtrasFromPixa(PIXA *pixa, L_PTRA **ppapix, L_PTRA **ppabox,
36                               l_int32 copyflag);
37 static PIXA *ReconstructPixa(L_PTRA *papix, L_PTRA *pabox, l_int32 choose);
38 static PIXA *ReconstructPixa1(L_PTRA *papix, L_PTRA *pabox);
39 static PIXA *ReconstructPixa2(L_PTRA *papix, L_PTRA *pabox);
40 static void DisplayResult(PIXA *pixac, PIXA **ppixa, l_int32 w, l_int32 h,
41                           l_int32 newline);
42 
43 #define  CHOOSE_RECON    2    /* 1 or 2 */
44 
45 
main(int argc,char ** argv)46 int main(int    argc,
47          char **argv)
48 {
49 l_int32      i, n, w, h, nactual, imax;
50 BOX         *box;
51 BOXA        *boxa;
52 PIX         *pixs, *pixd, *pix;
53 PIXA        *pixas, *pixat, *pixac;
54 L_PTRA      *papix, *pabox, *papix2, *pabox2;
55 static char  mainName[] = "ptra1_reg";
56 
57     if (argc != 1)
58         return ERROR_INT(" Syntax: ptra1_reg", mainName, 1);
59 
60     setLeptDebugOK(1);
61     pixac = pixaCreate(0);
62 
63     if ((pixs = pixRead("lucasta.1.300.tif")) == NULL)
64         return ERROR_INT("pixs not made", mainName, 1);
65     pixGetDimensions(pixs, &w, &h, NULL);
66     boxa = pixConnComp(pixs, &pixas, 8);
67     pixDestroy(&pixs);
68     boxaDestroy(&boxa);
69     n = pixaGetCount(pixas);
70 
71         /* Fill ptras with clones and reconstruct */
72     fprintf(stderr, "Fill with clones and reconstruct\n");
73     MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE);
74     pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
75     ptraDestroy(&papix, 0, 1);
76     ptraDestroy(&pabox, 0, 1);
77     DisplayResult(pixac, &pixat, w, h, 1);
78 
79         /* Remove every other one for the first half;
80          * with compaction at each removal */
81     fprintf(stderr, "Remove every other in 1st half, with compaction\n");
82     MakePtrasFromPixa(pixas, &papix, &pabox, L_COPY);
83     for (i = 0; i < n / 2; i++) {
84         if (i % 2 == 0) {
85             pix = (PIX *)ptraRemove(papix, i, L_COMPACTION);
86             box = (BOX *)ptraRemove(pabox, i, L_COMPACTION);
87             pixDestroy(&pix);
88             boxDestroy(&box);
89         }
90     }
91     pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
92     ptraDestroy(&papix, 0, 1);
93     ptraDestroy(&pabox, 0, 1);
94     DisplayResult(pixac, &pixat, w, h, 0);
95 
96         /* Remove every other one for the entire set,
97          * but without compaction at each removal */
98     fprintf(stderr,
99             "Remove every other in 1st half, without & then with compaction\n");
100     MakePtrasFromPixa(pixas, &papix, &pabox, L_COPY);
101     for (i = 0; i < n; i++) {
102         if (i % 2 == 0) {
103             pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION);
104             box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION);
105             pixDestroy(&pix);
106             boxDestroy(&box);
107         }
108     }
109     ptraCompactArray(papix);  /* now do the compaction */
110     ptraCompactArray(pabox);
111     pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
112     ptraDestroy(&papix, 0, 1);
113     ptraDestroy(&pabox, 0, 1);
114     DisplayResult(pixac, &pixat, w, h, 0);
115 
116         /* Fill ptras using insert at head, and reconstruct */
117     fprintf(stderr, "Insert at head and reconstruct\n");
118     papix = ptraCreate(n);
119     pabox = ptraCreate(n);
120     for (i = 0; i < n; i++) {
121         pix = pixaGetPix(pixas, i, L_CLONE);
122         box = pixaGetBox(pixas, i, L_CLONE);
123         ptraInsert(papix, 0, pix, L_MIN_DOWNSHIFT);
124         ptraInsert(pabox, 0, box, L_FULL_DOWNSHIFT);
125     }
126     pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
127     ptraDestroy(&papix, 0, 1);
128     ptraDestroy(&pabox, 0, 1);
129     DisplayResult(pixac, &pixat, w, h, 1);
130 
131         /* Reverse the arrays by swapping */
132     fprintf(stderr, "Reverse by swapping\n");
133     MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE);
134     for (i = 0; i < n / 2; i++) {
135         ptraSwap(papix, i, n - i - 1);
136         ptraSwap(pabox, i, n - i - 1);
137     }
138     ptraCompactArray(papix);  /* already compact; shouldn't do anything */
139     ptraCompactArray(pabox);
140     pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
141     ptraDestroy(&papix, 0, 1);
142     ptraDestroy(&pabox, 0, 1);
143     DisplayResult(pixac, &pixat, w, h, 0);
144 
145         /* Remove at the top of the array and push the hole to the end
146          * by neighbor swapping (!).  This is O(n^2), so it's not a
147          * recommended way to copy a ptra. [joke]  */
148     fprintf(stderr,
149             "Remove at top, pushing hole to end by swapping -- O(n^2)\n");
150     MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE);
151     papix2 = ptraCreate(0);
152     pabox2 = ptraCreate(0);
153     while (1) {
154         ptraGetActualCount(papix, &nactual);
155         if (nactual == 0) break;
156         ptraGetMaxIndex(papix, &imax);
157         pix = (PIX *)ptraRemove(papix, 0, L_NO_COMPACTION);
158         box = (BOX *)ptraRemove(pabox, 0, L_NO_COMPACTION);
159         ptraAdd(papix2, pix);
160         ptraAdd(pabox2, box);
161         for (i = 1; i <= imax; i++) {
162            ptraSwap(papix, i - 1, i);
163            ptraSwap(pabox, i - 1, i);
164         }
165     }
166     ptraCompactArray(papix);  /* should be empty */
167     ptraCompactArray(pabox);  /* ditto */
168     pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
169     ptraDestroy(&papix, 0, 1);
170     ptraDestroy(&pabox, 0, 1);
171     DisplayResult(pixac, &pixat, w, h, 1);  /* nothing there */
172     pixat = ReconstructPixa(papix2, pabox2, CHOOSE_RECON);
173     ptraDestroy(&papix2, 0, 1);
174     ptraDestroy(&pabox2, 0, 1);
175     DisplayResult(pixac, &pixat, w, h, 0);
176 
177         /* Remove and insert one position above, allowing minimum downshift.
178          * If you specify L_AUTO_DOWNSHIFT, because there is only 1 hole,
179          * it will do a full downshift at each insert.  This is a
180          * situation where the heuristic (expected number of holes)
181          * fails to do the optimal thing. */
182     fprintf(stderr, "Remove and insert one position above (min downshift)\n");
183     MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE);
184     for (i = 1; i < n; i++) {
185         pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION);
186         box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION);
187         ptraInsert(papix, i - 1, pix, L_MIN_DOWNSHIFT);
188         ptraInsert(pabox, i - 1, box, L_MIN_DOWNSHIFT);
189     }
190     pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
191     ptraDestroy(&papix, 0, 1);
192     ptraDestroy(&pabox, 0, 1);
193     DisplayResult(pixac, &pixat, w, h, 1);
194 
195         /* Remove and insert one position above, but this time
196          * forcing a full downshift at each step.  */
197     fprintf(stderr, "Remove and insert one position above (full downshift)\n");
198     MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE);
199     for (i = 1; i < n; i++) {
200         pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION);
201         box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION);
202         ptraInsert(papix, i - 1, pix, L_AUTO_DOWNSHIFT);
203         ptraInsert(pabox, i - 1, box, L_AUTO_DOWNSHIFT);
204     }
205 /*    ptraCompactArray(papix);
206     ptraCompactArray(pabox); */
207     pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
208     ptraDestroy(&papix, 0, 1);
209     ptraDestroy(&pabox, 0, 1);
210     DisplayResult(pixac, &pixat, w, h, 0);
211 
212     pixd = pixaDisplay(pixac, 0, 0);
213     pixDisplay(pixd, 100, 100);
214     pixWrite("/tmp/junkptra1.png", pixd, IFF_PNG);
215     pixDestroy(&pixd);
216     pixaDestroy(&pixac);
217     pixaDestroy(&pixas);
218     return 0;
219 }
220 
221 
222 static void
MakePtrasFromPixa(PIXA * pixa,L_PTRA ** ppapix,L_PTRA ** ppabox,l_int32 copyflag)223 MakePtrasFromPixa(PIXA     *pixa,
224                   L_PTRA  **ppapix,
225                   L_PTRA  **ppabox,
226                   l_int32   copyflag)
227 {
228 l_int32  i, n;
229 BOX     *box;
230 PIX     *pix;
231 L_PTRA  *papix, *pabox;
232 
233     n = pixaGetCount(pixa);
234     papix = ptraCreate(n);
235     pabox = ptraCreate(n);
236     for (i = 0; i < n; i++) {
237         pix = pixaGetPix(pixa, i, copyflag);
238         box = pixaGetBox(pixa, i, copyflag);
239         ptraAdd(papix, pix);
240         ptraAdd(pabox, box);
241     }
242 
243     *ppapix = papix;
244     *ppabox = pabox;
245     return;
246 }
247 
248 
249 static PIXA *
ReconstructPixa(L_PTRA * papix,L_PTRA * pabox,l_int32 choose)250 ReconstructPixa(L_PTRA  *papix,
251                 L_PTRA  *pabox,
252                 l_int32  choose)
253 {
254 PIXA  *pixa;
255 
256     if (choose == 1)
257         pixa = ReconstructPixa1(papix, pabox);
258     else
259         pixa = ReconstructPixa2(papix, pabox);
260     return pixa;
261 }
262 
263 
264     /* Reconstruction without compaction */
265 static PIXA *
ReconstructPixa1(L_PTRA * papix,L_PTRA * pabox)266 ReconstructPixa1(L_PTRA  *papix,
267                  L_PTRA  *pabox)
268 {
269 l_int32  i, imax, nactual;
270 BOX     *box;
271 PIX     *pix;
272 PIXA    *pixat;
273 
274     ptraGetMaxIndex(papix, &imax);
275     ptraGetActualCount(papix, &nactual);
276     fprintf(stderr, "Before removal:  imax = %4d, actual = %4d\n",
277             imax, nactual);
278 
279     pixat = pixaCreate(imax + 1);
280     for (i = 0; i <= imax; i++) {
281         pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION);
282         box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION);
283         if (pix) pixaAddPix(pixat, pix, L_INSERT);
284         if (box) pixaAddBox(pixat, box, L_INSERT);
285     }
286 
287     ptraGetMaxIndex(papix, &imax);
288     ptraGetActualCount(papix, &nactual);
289     fprintf(stderr, "After removal:   imax = %4d, actual = %4d\n\n",
290             imax, nactual);
291 
292     return pixat;
293 }
294 
295 
296     /* Reconstruction with compaction */
297 static PIXA *
ReconstructPixa2(L_PTRA * papix,L_PTRA * pabox)298 ReconstructPixa2(L_PTRA  *papix,
299                  L_PTRA  *pabox)
300 {
301 l_int32  i, imax, nactual;
302 BOX     *box;
303 PIX     *pix;
304 PIXA    *pixat;
305 
306     ptraGetMaxIndex(papix, &imax);
307     ptraGetActualCount(papix, &nactual);
308     fprintf(stderr, "Before removal:    imax = %4d, actual = %4d\n",
309             imax, nactual);
310 
311         /* Remove half */
312     pixat = pixaCreate(imax + 1);
313     for (i = 0; i <= imax; i++) {
314         if (i % 2 == 0) {
315             pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION);
316             box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION);
317             if (pix) pixaAddPix(pixat, pix, L_INSERT);
318             if (box) pixaAddBox(pixat, box, L_INSERT);
319         }
320     }
321 
322         /* Compact */
323     ptraGetMaxIndex(papix, &imax);
324     ptraGetActualCount(papix, &nactual);
325     fprintf(stderr, "Before compaction: imax = %4d, actual = %4d\n",
326             imax, nactual);
327     ptraCompactArray(papix);
328     ptraCompactArray(pabox);
329     ptraGetMaxIndex(papix, &imax);
330     ptraGetActualCount(papix, &nactual);
331     fprintf(stderr, "After compaction:  imax = %4d, actual = %4d\n",
332             imax, nactual);
333 
334         /* Remove the rest (and test compaction with removal) */
335     while (1) {
336         ptraGetActualCount(papix, &nactual);
337         if (nactual == 0) break;
338 
339         pix = (PIX *)ptraRemove(papix, 0, L_COMPACTION);
340         box = (BOX *)ptraRemove(pabox, 0, L_COMPACTION);
341         pixaAddPix(pixat, pix, L_INSERT);
342         pixaAddBox(pixat, box, L_INSERT);
343     }
344 
345     ptraGetMaxIndex(papix, &imax);
346     ptraGetActualCount(papix, &nactual);
347     fprintf(stderr, "After removal:     imax = %4d, actual = %4d\n\n",
348             imax, nactual);
349 
350     return pixat;
351 }
352 
353 
354 static void
DisplayResult(PIXA * pixac,PIXA ** ppixa,l_int32 w,l_int32 h,l_int32 newline)355 DisplayResult(PIXA   *pixac,
356               PIXA  **ppixa,
357               l_int32  w,
358               l_int32  h,
359               l_int32  newline)
360 {
361 PIX   *pixd;
362 
363     pixd = pixaDisplay(*ppixa, w, h);
364     pixSaveTiled(pixd, pixac, 1, newline, 30, 8);
365     pixDestroy(&pixd);
366     pixaDestroy(ppixa);
367     return;
368 }
369