(C) Relatively high density file backups on paper. Cross-platform CLI port of Ollydbg's Paperback from Windows and Borland C.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Decoder.cpp 36KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. ////////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // PaperBack -- high density backups on the plain paper //
  4. // //
  5. // Copyright (c) 2007 Oleh Yuschuk //
  6. // ollydbg at t-online de (set Subject to 'paperback' or be filtered out!) //
  7. // //
  8. // //
  9. // This file is part of PaperBack. //
  10. // //
  11. // Paperback is free software; you can redistribute it and/or modify it under //
  12. // the terms of the GNU General Public License as published by the Free //
  13. // Software Foundation; either version 3 of the License, or (at your option) //
  14. // any later version. //
  15. // //
  16. // PaperBack is distributed in the hope that it will be useful, but WITHOUT //
  17. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //
  18. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for //
  19. // more details. //
  20. // //
  21. // You should have received a copy of the GNU General Public License along //
  22. // with this program. If not, see <http://www.gnu.org/licenses/>. //
  23. // //
  24. // //
  25. // Note that bzip2 compression/decompression library, which is the part of //
  26. // this project, is covered by different license, which, in my opinion, is //
  27. // compatible with GPL. //
  28. // //
  29. ////////////////////////////////////////////////////////////////////////////////
  30. #ifdef _WIN32
  31. #include <windows.h>
  32. #endif
  33. #include <stdlib.h>
  34. #include <algorithm>
  35. #include <math.h>
  36. #include "bzlib.h"
  37. #include "aes.h"
  38. #include "paperbak.h"
  39. #include "Resource.h"
  40. #define NHYST 1024 // Number of points in histogramm
  41. #define NPEAK 32 // Maximal number of peaks
  42. #define SUBDX 8 // X size of subblock, pixels
  43. #define SUBDY 8 // Y size of subblock, pixels
  44. // Given hystogramm h of length n points, locates black peaks and determines
  45. // phase and step of the grid.
  46. static float Findpeaks(int *h,int n,float *bestpeak,float *beststep) {
  47. int i,j,k,ampl,amin,amax,d,l[NHYST],limit,sum;
  48. int npeak,dist,bestdist,bestcount,height[NPEAK];
  49. float area,moment,peak[NPEAK],weight[NPEAK];
  50. float x0,step,sn,sx,sy,sxx,syy,sxy;
  51. // I expect at least 16 and at most NHYST points in the histogramm.
  52. if (n<16) return 0.0;
  53. if (n>NHYST) n=NHYST;
  54. // Get absolute minimum and maximum.
  55. amin=amax=h[0];
  56. for (i=1; i<n; i++) {
  57. if (h[i]<amin) amin=h[i];
  58. if (h[i]>amax) amax=h[i]; };
  59. // Remove gradients by shadowing over 32 pixels. May create small artefacts
  60. // in the vicinity of the main peak.
  61. d=(amax-amin+16)/32;
  62. ampl=h[0];
  63. for (i=0; i<n; i++) {
  64. l[i]=ampl=std::max(ampl-d,h[i]); };
  65. amax=0;
  66. for (i=n-1; i>=0; i--) {
  67. ampl=std::max(ampl-d,l[i]);
  68. l[i]=ampl-h[i];
  69. amax=std::max(amax,l[i]); };
  70. // TRY TO COMPARE WITH SECOND LARGE PEAK?
  71. // I set peak limit to 3/4 of the amplitude of the highest peak. This
  72. // solution at least works in 90% of all cases.
  73. limit=amax*3/4;
  74. if (limit==0) limit=1;
  75. // Start search and skip incomplete first peak.
  76. i=0; npeak=0;
  77. while (i<n && l[i]>limit) i++;
  78. // Find peaks.
  79. while (i<n && npeak<NPEAK) {
  80. // Find next peak.
  81. while (i<n && l[i]<=limit) i++;
  82. // Calculate peak parameters.
  83. area=0.0; moment=0.0; amax=0;
  84. while (i<n && l[i]>limit) {
  85. ampl=l[i]-limit;
  86. area+=ampl;
  87. moment+=ampl*i;
  88. amax=std::max(amax,l[i]);
  89. i++; };
  90. // Don't process incomplete peaks.
  91. if (i>=n) break;
  92. // Add peak to the list, removing weak artefacts.
  93. if (npeak>0) {
  94. if (amax*8<height[npeak-1]) continue;
  95. if (amax>height[npeak-1]*8) npeak--; };
  96. peak[npeak]=moment/area;
  97. weight[npeak]=area;
  98. height[npeak]=amax;
  99. npeak++;
  100. };
  101. // At least two peaks are necessary to detect the step.
  102. if (npeak<2) return 0.0;
  103. // Calculate all possible distances between the found peaks.
  104. for (i=0; i<n; i++) l[i]=0;
  105. for (i=0; i<npeak-1; i++) {
  106. for (j=i+1; j<npeak; j++) {
  107. l[(int)(peak[j]-peak[i])]++;
  108. };
  109. };
  110. // Find group with the maximal number of peaks. I allow for approximately 3%
  111. // dispersion. Distances under 16 pixels are too short to be real. Caveat:
  112. // this method can't distinguish direct sequence from interleaved.
  113. bestdist=0; bestcount=0;
  114. for (i=16; i<n; i++) {
  115. if (l[i]==0) continue;
  116. sum=0;
  117. for (j=i; j<=i+i/33+1 && j<n; j++) sum+=l[j];
  118. if (sum>bestcount) { // Shorter is better
  119. bestdist=i;
  120. bestcount=sum;
  121. };
  122. };
  123. if (bestdist==0) return 0.0;
  124. // Now determine the parameters of the sequence. The method I use is not very
  125. // good but usually sufficient.
  126. sn=sx=sy=sxx=syy=sxy=0.0;
  127. moment=0.0;
  128. for (i=0; i<npeak-1; i++) {
  129. for (j=i+1; j<npeak; j++) {
  130. dist=peak[j]-peak[i];
  131. if (dist<bestdist || dist>=bestdist+bestdist/33+1) continue;
  132. if (sn==0.0) // First link
  133. k=0;
  134. else {
  135. x0=(sx*sxy-sxx*sy)/(sx*sx-sn*sxx);
  136. step=(sx*sy-sn*sxy)/(sx*sx-sn*sxx);
  137. k=(peak[i]-x0+step/2.0)/step; };
  138. sn+=2.0;
  139. sx+=k*2+1;
  140. sy+=peak[i]+peak[j];
  141. sxx+=k*k+(k+1)*(k+1);
  142. syy+=peak[i]*peak[i]+peak[j]*peak[j];
  143. sxy+=peak[i]*k+peak[j]*(k+1);
  144. moment+=height[i]+height[j];
  145. };
  146. };
  147. *bestpeak=(sx*sxy-sxx*sy)/(sx*sx-sn*sxx);
  148. *beststep=(sx*sy-sn*sxy)/(sx*sx-sn*sxx);
  149. return moment/sn;
  150. };
  151. // Given grid of recognized dots, extracts saved information. Returns number of
  152. // corrected erorrs (0..16) on success and 17 if information is not readable.
  153. static int Recognizebits(t_data *result,uchar grid[NDOT][NDOT],
  154. t_procdata *pdata) {
  155. int i,j,k,q,r,factor,lcorr,c,cmin,cmax,limit;
  156. int grid1[NDOT][NDOT],answer,bestanswer;
  157. static int lastgood;
  158. ushort crc;
  159. t_data uncorrected,bestresult;
  160. cmin=pdata->cmin;
  161. cmax=pdata->cmax;
  162. bestanswer=17;
  163. // If orientation is not yet known, try all possible orientations + mirroring.
  164. for (r=0; r<8; r++) {
  165. if (pdata->orientation>=0 && r!=pdata->orientation) continue;
  166. // Try 3 different point overlapping factors, combined with 3 different
  167. // thresholds. Usually all cells are alike, so I remember the last known
  168. // good combination and start with it.
  169. for (k=0; k<9; k++) {
  170. q=(k+lastgood)%9;
  171. switch (q) {
  172. case 0: factor=1000; lcorr=0; break;
  173. case 1: factor=32; lcorr=0; break;
  174. case 2: factor=16; lcorr=0; break;
  175. case 3: factor=1000; lcorr=(cmin-cmax)/16; break;
  176. case 4: factor=32; lcorr=(cmin-cmax)/16; break;
  177. case 5: factor=16; lcorr=(cmin-cmax)/16; break;
  178. case 6: factor=1000; lcorr=(cmax-cmin)/16; break;
  179. case 7: factor=32; lcorr=(cmax-cmin)/16; break;
  180. case 8: factor=16; lcorr=(cmax-cmin)/16; break;
  181. default: factor=1000; lcorr=0; lastgood=0; break; };
  182. // Correct grid for overlapping dots and calculate limit between black
  183. // and white. I take into account only adjacent dots; the influence of
  184. // diagonals is significantly lower.
  185. limit=0;
  186. for (j=0; j<NDOT; j++) {
  187. for (i=0; i<NDOT; i++) {
  188. c=grid[i][j]*factor;
  189. if (i>0) c-=grid[j][i-1]; else c-=cmax;
  190. if (i<31) c-=grid[j][i+1]; else c-=cmax;
  191. if (j>0) c-=grid[j-1][i]; else c-=cmax;
  192. if (j<31) c-=grid[j+1][i]; else c-=cmax;
  193. grid1[j][i]=c;
  194. limit+=c;
  195. };
  196. };
  197. limit=limit/1024+lcorr*factor;
  198. // Extract data according to the selected orientation.
  199. memset(result,0,sizeof(t_data));
  200. for (j=0; j<NDOT; j++) {
  201. for (i=0; i<NDOT; i++) {
  202. switch (r) {
  203. case 0: c=grid1[j][i]; break;
  204. case 1: c=grid1[i][NDOT-1-j]; break;
  205. case 2: c=grid1[NDOT-1-j][NDOT-1-i]; break;
  206. case 3: c=grid1[NDOT-1-i][j]; break;
  207. case 4: c=grid1[i][j]; break;
  208. case 5: c=grid1[j][NDOT-1-i]; break;
  209. case 6: c=grid1[NDOT-1-i][NDOT-1-j]; break;
  210. case 7: c=grid1[NDOT-1-j][i]; break;
  211. };
  212. if (c<limit) {
  213. ((uint32_t *)result)[j]|=1<<i;
  214. };
  215. };
  216. };
  217. // XOR with grid that corrects mean brightness.
  218. for (j=0; j<NDOT; j++) {
  219. ((uint32_t *)result)[j]^=(j & 1?0xAAAAAAAA:0x55555555); };
  220. // Apply ECC to restore invalid data.
  221. if (pdata->mode & M_BEST)
  222. memcpy(&uncorrected,result,sizeof(t_data));
  223. else
  224. memcpy(&pdata->uncorrected,result,sizeof(t_data));
  225. answer=Decode8((uchar *)result,NULL,0,127);
  226. if (answer<0) answer=17;
  227. // Verify data for correctness by calculating CRC.
  228. if (answer<=16) {
  229. crc=(ushort)(Crc16((uchar *)result,NDATA+4)^0x55AA);
  230. if (crc==result->crc) {
  231. // Data recognized correctly, save orientation of actually processed
  232. // page and factoring.
  233. pdata->orientation=r;
  234. // Report success.
  235. if ((pdata->mode & M_BEST)==0) {
  236. lastgood=q;
  237. return answer; }
  238. else if (answer<bestanswer) {
  239. bestanswer=answer;
  240. bestresult=*result;
  241. memcpy(&pdata->uncorrected,&uncorrected,sizeof(t_data));
  242. };
  243. };
  244. };
  245. };
  246. };
  247. if (pdata->mode & M_BEST)
  248. *result=bestresult;
  249. return bestanswer;
  250. };
  251. // Determines rough grid position.
  252. static void Getgridposition(t_procdata *pdata) {
  253. int i,j,nx,ny,stepx,stepy,sizex,sizey;
  254. int c,cmin,cmax,distrx[256],distry[256],limit;
  255. uchar *data,*pd;
  256. // Get frequently used variables.
  257. sizex=pdata->sizex;
  258. sizey=pdata->sizey;
  259. data=pdata->data;
  260. // Check overall bitmap size.
  261. if (sizex<=3*NDOT || sizey<=3*NDOT) {
  262. Reporterror("Bitmap is too small to process");
  263. pdata->step=0; return; };
  264. // Select horizontal and vertical lines (at most 256 in each direction) to
  265. // check for grid location.
  266. stepx=sizex/256+1; nx=(sizex-2)/stepx; if (nx>256) nx=256;
  267. stepy=sizey/256+1; ny=(sizey-2)/stepy; if (ny>256) ny=256;
  268. // The main problem in determining the grid location are the black and/or
  269. // white borders around the grid. To distinguish between borders with more or
  270. // less constant intensity and quickly changing raster, I take into account
  271. // only the fast intensity changes over the short distance (2 pixels).
  272. // Caveat: this approach may fail for artificially created bitmaps.
  273. memset(distrx,0,nx*sizeof(int));
  274. memset(distry,0,ny*sizeof(int));
  275. for (j=0; j<ny; j++) {
  276. pd=data+j*stepy*sizex;
  277. for (i=0; i<nx; i++,pd+=stepx) {
  278. c=pd[0]; cmin=c; cmax=c;
  279. c=pd[2]; cmin=std::min(cmin,c); cmax=std::max(cmax,c);
  280. c=pd[sizex+1]; cmin=std::min(cmin,c); cmax=std::max(cmax,c);
  281. c=pd[2*sizex]; cmin=std::min(cmin,c); cmax=std::max(cmax,c);
  282. c=pd[2*sizex+2]; cmin=std::min(cmin,c); cmax=std::max(cmax,c);
  283. distrx[i]+=cmax-cmin;
  284. distry[j]+=cmax-cmin;
  285. };
  286. };
  287. // Get rough bitmap limits in horizontal direction (at the level 50% of
  288. // maximum).
  289. limit=0;
  290. for (i=0; i<nx; i++) {
  291. if (distrx[i]>limit) limit=distrx[i]; };
  292. limit/=2;
  293. for (i=0; i<nx-1; i++) {
  294. if (distrx[i]>=limit) break; };
  295. pdata->gridxmin=i*stepx;
  296. for (i=nx-1; i>0; i--) {
  297. if (distrx[i]>=limit) break; };
  298. pdata->gridxmax=i*stepx;
  299. // Get rough bitmap limits in vertical direction.
  300. limit=0;
  301. for (j=0; j<ny; j++) {
  302. if (distry[j]>limit) limit=distry[j]; };
  303. limit/=2;
  304. for (j=0; j<ny-1; j++) {
  305. if (distry[j]>=limit) break; };
  306. pdata->gridymin=j*stepy;
  307. for (j=ny-1; j>0; j--) {
  308. if (distry[j]>=limit) break; };
  309. pdata->gridymax=j*stepy;
  310. // Step finished.
  311. pdata->step++;
  312. };
  313. // Selects search range, determines grid intensity and estimates sharpness.
  314. static void Getgridintensity(t_procdata *pdata) {
  315. int i,j,sizex,sizey,centerx,centery,dx,dy,n;
  316. int searchx0,searchy0,searchx1,searchy1;
  317. int distrc[256],distrd[256],cmean,cmin,cmax,limit,sum,contrast;
  318. uchar *data,*pd;
  319. // Get frequently used variables.
  320. sizex=pdata->sizex;
  321. sizey=pdata->sizey;
  322. data=pdata->data;
  323. // Select X and Y ranges to search for the grid. As I use affine transforms
  324. // instead of more CPU-intensive rotations, these ranges are determined for
  325. // Y=0 (searchx0,searchx1) and for X=0 (searchy0,searchy1).
  326. centerx=(pdata->gridxmin+pdata->gridxmax)/2;
  327. centery=(pdata->gridymin+pdata->gridymax)/2;
  328. searchx0=centerx-NHYST/2; if (searchx0<0) searchx0=0;
  329. searchx1=searchx0+NHYST; if (searchx1>sizex) searchx1=sizex;
  330. searchy0=centery-NHYST/2; if (searchy0<0) searchy0=0;
  331. searchy1=searchy0+NHYST; if (searchy1>sizey) searchy1=sizey;
  332. dx=searchx1-searchx0;
  333. dy=searchy1-searchy0;
  334. // Determine mean, minimal and maximal intensity of the central area, and
  335. // sharpness of the image. As a minimum I take the level not reached by 3%
  336. // of all pixels, as a maximum - level exceeded by 3% of pixels.
  337. memset(distrc,0,sizeof(distrc));
  338. memset(distrd,0,sizeof(distrd));
  339. cmean=0; n=0;
  340. for (j=0; j<dy-1; j++) {
  341. pd=data+(searchy0+j)*sizex+searchx0;
  342. for (i=0; i<dx-1; i++,pd++) {
  343. distrc[*pd]++; cmean+=*pd; n++;
  344. distrd[abs(pd[1]-pd[0])]++;
  345. distrd[abs(pd[sizex]-pd[0])]++;
  346. };
  347. };
  348. // Calculate mean, minimal and maximal image intensity.
  349. cmean/=n;
  350. limit=n/33; // 3% of the total number of pixels
  351. for (cmin=0,sum=0; cmin<255; cmin++) {
  352. sum+=distrc[cmin];
  353. if (sum>=limit) break; };
  354. for (cmax=255,sum=0; cmax>0; cmax--) {
  355. sum+=distrc[cmax];
  356. if (sum>=limit) break; };
  357. if (cmax-cmin<1) {
  358. Reporterror("No image");
  359. pdata->step=0;
  360. return; };
  361. // Estimate image sharpness. The factor is rather empirical. Later, when
  362. // dot size is known, this value will be corrected.
  363. limit=n/10; // 5% (each point is counted twice)
  364. for (contrast=255,sum=0; contrast>1; contrast--) {
  365. sum+=distrd[contrast];
  366. if (sum>=limit) break; };
  367. pdata->sharpfactor=(cmax-cmin)/(2.0*contrast)-1.0;
  368. // Save results.
  369. pdata->searchx0=searchx0;
  370. pdata->searchx1=searchx1;
  371. pdata->searchy0=searchy0;
  372. pdata->searchy1=searchy1;
  373. pdata->cmean=cmean;
  374. pdata->cmin=cmin;
  375. pdata->cmax=cmax;
  376. // Step finished.
  377. pdata->step++;
  378. };
  379. // Find angle and step of vertical grid lines.
  380. static void Getxangle(t_procdata *pdata) {
  381. int i,j,a,x,y,x0,y0,dx,dy,sizex;
  382. int h[NHYST],nh[NHYST],ystep;
  383. uchar *data,*pd;
  384. float weight,xpeak,xstep;
  385. float maxweight,bestxpeak,bestxangle,bestxstep;
  386. // Get frequently used variables.
  387. sizex=pdata->sizex;
  388. data=pdata->data;
  389. x0=pdata->searchx0;
  390. y0=pdata->searchy0;
  391. dx=pdata->searchx1-x0;
  392. dy=pdata->searchy1-y0;
  393. // Calculate vertical step. 256 lines are sufficient. Warning: danger of
  394. // moire, especially on synthetic bitmaps!
  395. ystep=dy/256; if (ystep<1) ystep=1;
  396. maxweight=0.0;
  397. xstep=bestxstep=0.0;
  398. // Determine rough angle, step and base for the vertical grid lines. Due to
  399. // the oversimplified conversion, cases a=+-1 are almost identical to a=0.
  400. // Maximal allowed angle is approx. +/-5 degrees (1/10 radian).
  401. for (a=-(NHYST/20)*2; a<=(NHYST/20)*2; a+=2) {
  402. // Clear histogramm.
  403. memset(h,0,dx*sizeof(int));
  404. memset(nh,0,dx*sizeof(int));
  405. // Gather histogramm.
  406. for (j=0; j<dy; j+=ystep) {
  407. y=y0+j;
  408. x=x0+(y0+j)*a/NHYST; // Affine transformation
  409. pd=data+y*sizex+x;
  410. for (i=0; i<dx; i++,x++,pd++) {
  411. if (x<0) continue;
  412. if (x>=sizex) break;
  413. h[i]+=*pd; nh[i]++;
  414. };
  415. };
  416. // Normalize histogramm.
  417. for (i=0; i<dx; i++) {
  418. if (nh[i]>0) h[i]/=nh[i]; };
  419. // Find peaks. On small synthetic bitmaps (height less than NHYST/2
  420. // pixels) weights for a=0 and +/-2 are the same and routine would select
  421. // -2 as a best angle. To solve this problem, I add small correction that
  422. // preferes zero angle.
  423. weight=Findpeaks(h,dx,&xpeak,&xstep)+1.0/(abs(a)+10.0);
  424. if (weight>maxweight) {
  425. bestxpeak=xpeak+x0;
  426. bestxangle=(float)a/NHYST;
  427. bestxstep=xstep;
  428. maxweight=weight;
  429. };
  430. };
  431. // Analyse and save results.
  432. if (maxweight==0.0 || bestxstep<NDOT) {
  433. Reporterror("No grid");
  434. pdata->step=0;
  435. return; };
  436. pdata->xpeak=bestxpeak;
  437. pdata->xstep=bestxstep;
  438. pdata->xangle=bestxangle;
  439. // Step finished.
  440. pdata->step++;
  441. };
  442. // Find angle and step of horizontal grid lines. Very similar to Getxangle().
  443. static void Getyangle(t_procdata *pdata) {
  444. int i,j,a,x,y,x0,y0,dx,dy,sizex,sizey;
  445. int h[NHYST],nh[NHYST],xstep;
  446. uchar *data,*pd;
  447. float weight,ypeak,ystep;
  448. float maxweight,bestypeak,bestyangle,bestystep;
  449. // Get frequently used variables.
  450. sizex=pdata->sizex;
  451. sizey=pdata->sizey;
  452. data=pdata->data;
  453. x0=pdata->searchx0;
  454. y0=pdata->searchy0;
  455. dx=pdata->searchx1-x0;
  456. dy=pdata->searchy1-y0;
  457. // Calculate vertical step. 256 lines are sufficient. Warning: danger of
  458. // moire, especially on synthetic bitmaps!
  459. xstep=dx/256; if (xstep<1) xstep=1;
  460. maxweight=0.0;
  461. ystep=bestystep=0.0;
  462. // Determine rough angle, step and base for the vertical grid lines. I do not
  463. // take into account the changes of angle caused by the X transformation.
  464. for (a=-(NHYST/20)*2; a<=(NHYST/20)*2; a+=2) {
  465. // Clear histogramm.
  466. memset(h,0,dy*sizeof(int));
  467. memset(nh,0,dy*sizeof(int));
  468. for (i=0; i<dx; i+=xstep) {
  469. x=x0+i;
  470. y=y0+(x0+i)*a/NHYST; // Affine transformation
  471. pd=data+y*sizex+x;
  472. for (j=0; j<dy; j++,y++,pd+=sizex) {
  473. if (y<0) continue;
  474. if (y>=sizey) break;
  475. h[j]+=*pd; nh[j]++;
  476. };
  477. };
  478. // Normalize histogramm.
  479. for (j=0; j<dy; j++) {
  480. if (nh[j]>0) h[j]/=nh[j]; };
  481. // Find peaks.
  482. weight=Findpeaks(h,dy,&ypeak,&ystep)+1.0/(abs(a)+10.0);
  483. if (weight>maxweight) {
  484. bestypeak=ypeak+y0;
  485. bestyangle=(float)a/NHYST;
  486. bestystep=ystep;
  487. maxweight=weight;
  488. };
  489. };
  490. // Analyse and save results.
  491. if (maxweight==0.0 || bestystep<NDOT ||
  492. bestystep<pdata->xstep*0.40 ||
  493. bestystep>pdata->xstep*2.50
  494. ) {
  495. Reporterror("No grid");
  496. pdata->step=0;
  497. return; };
  498. pdata->ypeak=bestypeak;
  499. pdata->ystep=bestystep;
  500. pdata->yangle=bestyangle;
  501. // Step finished.
  502. pdata->step++;
  503. };
  504. // Prepare data and allocate memory for data decoding.
  505. static void Preparefordecoding(t_procdata *pdata) {
  506. int sizex,sizey,dx,dy;
  507. float xstep,ystep,border,sharpfactor,shift,maxxshift,maxyshift,dotsize;
  508. // Get frequently used variables.
  509. sizex=pdata->sizex;
  510. sizey=pdata->sizey;
  511. xstep=pdata->xstep;
  512. ystep=pdata->ystep;
  513. border=pdata->blockborder;
  514. sharpfactor=pdata->sharpfactor;
  515. // Empirical formula: the larger the angle, the more imprecise is the
  516. // expected position of the block.
  517. if (border<=0.0) {
  518. border=std::max(fabs(pdata->xangle),fabs(pdata->yangle))*5.0+0.4;
  519. pdata->blockborder=border; };
  520. // Correct sharpness for known dot size. This correction is empirical.
  521. dotsize=std::max(xstep,ystep)/(NDOT+3.0);
  522. sharpfactor+=1.3/dotsize-0.1;
  523. if (sharpfactor<0.0) sharpfactor=0.0;
  524. else if (sharpfactor>2.0) sharpfactor=2.0;
  525. pdata->sharpfactor=sharpfactor;
  526. // Calculate start coordinates and number of block that fit onto the page
  527. // in X direction.
  528. maxxshift=fabs(pdata->xangle*sizey);
  529. if (pdata->xangle<0.0)
  530. shift=0.0;
  531. else
  532. shift=maxxshift;
  533. while (pdata->xpeak-xstep>-shift-xstep*border)
  534. pdata->xpeak-=xstep;
  535. pdata->nposx=(int)((sizex+maxxshift)/xstep);
  536. // The same in Y direction.
  537. maxyshift=fabs(pdata->yangle*sizex);
  538. if (pdata->yangle<0.0)
  539. shift=0.0;
  540. else
  541. shift=maxyshift;
  542. while (pdata->ypeak-ystep>-shift-ystep*border)
  543. pdata->ypeak-=ystep;
  544. pdata->nposy=(int)((sizey+maxyshift)/ystep);
  545. // Start new quality map. Note that this call doesn't force map to be
  546. // displayed.
  547. //Initqualitymap(pdata->nposx,pdata->nposy);
  548. // Allocate block buffers.
  549. dx=xstep*(2.0*border+1.0)+1.0;
  550. dy=ystep*(2.0*border+1.0)+1.0;
  551. pdata->buf1=(uchar *)malloc(dx*dy);
  552. pdata->buf2=(uchar *)malloc(dx*dy);
  553. pdata->bufx=(int *)malloc(dx*sizeof(int));
  554. pdata->bufy=(int *)malloc(sizeof(int));
  555. pdata->blocklist=(t_block *)
  556. malloc(pdata->nposx*pdata->nposy*sizeof(t_block));
  557. // Check that we have enough memory.
  558. if (pdata->buf1==NULL || pdata->buf2==NULL ||
  559. pdata->bufx==NULL || pdata->bufy==NULL || pdata->blocklist==NULL
  560. ) {
  561. if (pdata->buf1!=NULL) free(pdata->buf1);
  562. if (pdata->buf2!=NULL) free(pdata->buf2);
  563. if (pdata->bufx!=NULL) free(pdata->bufx);
  564. if (pdata->bufy!=NULL) free(pdata->bufy);
  565. if (pdata->blocklist!=NULL) free(pdata->blocklist);
  566. Reporterror("Low memory");
  567. pdata->step=0;
  568. return; };
  569. // Determine maximal size of the dot on the bitmap.
  570. if (xstep<2*(NDOT+3) || ystep<2*(NDOT+3))
  571. pdata->maxdotsize=1;
  572. else if (xstep<3*(NDOT+3) || ystep<3*(NDOT+3))
  573. pdata->maxdotsize=2;
  574. else if (xstep<4*(NDOT+3) || ystep<4*(NDOT+3))
  575. pdata->maxdotsize=3;
  576. else
  577. pdata->maxdotsize=4;
  578. // Prepare superblock.
  579. memset(&pdata->superblock,0,sizeof(t_superblock));
  580. // Initialize remaining items.
  581. pdata->bufdx=dx;
  582. pdata->bufdy=dy;
  583. pdata->orientation=-1; // As yet, unknown page orientation
  584. pdata->ngood=0;
  585. pdata->nbad=0;
  586. pdata->nsuper=0;
  587. pdata->nrestored=0;
  588. pdata->posx=pdata->posy=0; // First block to scan
  589. // Step finished.
  590. pdata->step++;
  591. };
  592. // The most important routine, converts scanned blocks into data. Used both by
  593. // data decoder and by block display. Returns -1 if block cannot be located,
  594. // 0 to 16 if block is correctly decoded and 17 if block is unrecoverable.
  595. int Decodeblock(t_procdata *pdata,int posx,int posy,t_data *result) {
  596. int i,j,x,y,x0,y0,dx,dy,sizex,sizey,*bufx,*bufy;
  597. int c,cmin,cmax,dotsize,shift,shiftmax,sum,answer,bestanswer;
  598. float xangle,yangle,xbmp,ybmp,xres,yres,sharpfactor;
  599. float xpeak,xstep,ypeak,ystep,halfdot;
  600. float sy,syy,disp,dispmin,dispmax;
  601. uchar *psrc,*pdest,*data,g[9][NDOT][NDOT],grid[NDOT][NDOT];
  602. t_data uncorrected,bestresult;
  603. // Get frequently used variables.
  604. sizex=pdata->sizex;
  605. sizey=pdata->sizey;
  606. xangle=pdata->xangle;
  607. yangle=pdata->yangle;
  608. data=pdata->data;
  609. cmin=pdata->cmin;
  610. cmax=pdata->cmax;
  611. sharpfactor=pdata->sharpfactor;
  612. bufx=pdata->bufx;
  613. bufy=pdata->bufy;
  614. // Get block coordinates in the bitmap. Note that bitmap in memory is placed
  615. // upside down.
  616. x0=pdata->xpeak+pdata->xstep*(posx-pdata->blockborder);
  617. y0=pdata->ypeak+pdata->ystep*(pdata->nposy-posy-1-pdata->blockborder);
  618. dx=pdata->bufdx;
  619. dy=pdata->bufdy;
  620. // Rotate selected block to 'unsharp' buffer using bilinear interpolation.
  621. // Fast discrete shifts are also thinkable but deliver significantly higher
  622. // error rate.
  623. if (sharpfactor>0.0)
  624. pdest=pdata->buf2; // Sharping necessary
  625. else
  626. pdest=pdata->buf1;
  627. pdata->unsharp=pdest;
  628. for (j=0; j<dy; j++) {
  629. xbmp=x0+(y0+j)*xangle;
  630. if (xbmp>=0.0) x=xbmp; // Integer and fractional parts
  631. else x=xbmp-1.0;
  632. xres=xbmp-x;
  633. for (i=0; i<dx; i++,pdest++,x++) {
  634. ybmp=y0+j+(x0+i)*yangle;
  635. if (ybmp>0.0) y=ybmp;
  636. else y=ybmp-1.0;
  637. yres=ybmp-y;
  638. if (x<0 || x>=sizex-1 || y<0 || y>=sizey-1)
  639. *pdest=(uchar)cmax; // Fill areas outside the page white
  640. else {
  641. psrc=data+y*sizex+x;
  642. *pdest=(psrc[0]+(psrc[1]-psrc[0])*xres)*(1.0-yres)+
  643. (psrc[sizex]+(psrc[sizex+1]-psrc[sizex])*xres)*yres;
  644. };
  645. };
  646. };
  647. // Sharpen rotated block, if necessary.
  648. if (sharpfactor>0.0) {
  649. psrc=pdata->buf2;
  650. pdest=pdata->buf1;
  651. for (j=0; j<dy; j++) {
  652. for (i=0; i<dx; i++,psrc++,pdest++) {
  653. if (i==0 || i==dx-1 || j==0 || j==dy-1)
  654. *pdest=*psrc;
  655. else {
  656. *pdest=(uchar)std::max(cmin,std::min((int)(psrc[0]*(1.0+4.0*sharpfactor)-
  657. (psrc[-dx]+psrc[-1]+psrc[1]+psrc[dx])*sharpfactor),cmax));
  658. };
  659. };
  660. };
  661. };
  662. pdata->sharp=pdata->buf1;
  663. // Find grid lines for the whole block. This works perfectly for laser
  664. // printers. For bidirectional jet printers, splitting left and right
  665. // borders into several pieces may give better results.
  666. memset(bufx,0,dx*sizeof(int));
  667. memset(bufy,0,dy*sizeof(int));
  668. psrc=pdata->buf1;
  669. for (j=0; j<dy; j++) {
  670. for (i=0; i<dx; i++,psrc++) {
  671. bufx[i]+=*psrc;
  672. bufy[j]+=*psrc;
  673. };
  674. };
  675. if (Findpeaks(bufx,dx,&xpeak,&xstep)<=0.0)
  676. return -1; // No X grid
  677. if (fabs(xstep-pdata->xstep)>pdata->xstep/16.0)
  678. return -1; // Invalid grid step
  679. if (Findpeaks(bufy,dy,&ypeak,&ystep)<=0.0)
  680. return -1; // No Y grid
  681. if (fabs(ystep-pdata->ystep)>pdata->ystep/16.0)
  682. return -1; // Invalid grid step
  683. // Save block position for displaying purposes.
  684. pdata->blockxpeak=xpeak;
  685. pdata->blockxstep=xstep;
  686. pdata->blockypeak=ypeak;
  687. pdata->blockystep=ystep;
  688. // Calculate dot step and correct peaks so that they point to first dot.
  689. xstep=xstep/(NDOT+3.0);
  690. xpeak+=2.0*xstep;
  691. ystep=ystep/(NDOT+3.0);
  692. ypeak+=2.0*ystep;
  693. // In search-for-the-best-quality mode, I look for the best possible
  694. // decoding. Helps to estimate the overall quality of the picture.
  695. bestanswer=17;
  696. // Try different dot sizes, starting from 1x1 pixel. If scanner resolution
  697. // is sufficient, 2x2 dot usually gives best results.
  698. for (dotsize=1; dotsize<=pdata->maxdotsize; dotsize++) {
  699. halfdot=dotsize/2.0-1.0;
  700. for (j=0; j<NDOT; j++) {
  701. y=ypeak+ystep*j-halfdot;
  702. for (i=0; i<NDOT; i++) {
  703. x=xpeak+xstep*i-halfdot;
  704. // For each dot size I try +/- 1 pixel shifts in all possible
  705. // directions.
  706. for (shift=0; shift<9; shift++) {
  707. switch (shift) {
  708. case 0: psrc=pdata->buf1+(y-1)*dx+(x-1); break;
  709. case 1: psrc=pdata->buf1+(y-1)*dx+(x+0); break;
  710. case 2: psrc=pdata->buf1+(y-1)*dx+(x+1); break;
  711. case 3: psrc=pdata->buf1+(y+0)*dx+(x-1); break;
  712. case 4: psrc=pdata->buf1+(y+0)*dx+(x+0); break;
  713. case 5: psrc=pdata->buf1+(y+0)*dx+(x+1); break;
  714. case 6: psrc=pdata->buf1+(y+1)*dx+(x-1); break;
  715. case 7: psrc=pdata->buf1+(y+1)*dx+(x+0); break;
  716. case 8: psrc=pdata->buf1+(y+1)*dx+(x+1); break; };
  717. switch (dotsize) {
  718. case 4: // Rounded 4x4 dot (rarely works)
  719. sum=(psrc[1]+psrc[2]+psrc[dx]+psrc[dx+1]+psrc[dx+2]+psrc[dx+3]+
  720. psrc[2*dx]+psrc[2*dx+1]+psrc[2*dx+2]+psrc[2*dx+3]+
  721. psrc[3*dx+1]+psrc[3*dx+2])/12;
  722. break;
  723. case 3: // 3x3 pixel
  724. sum=(psrc[0]+psrc[1]+psrc[2]+psrc[dx]+psrc[dx+1]+psrc[dx+2]+
  725. psrc[2*dx]+psrc[2*dx+1]+psrc[2*dx+2])/9;
  726. break;
  727. case 2: // 2x2 pixel (usually the best)
  728. sum=(psrc[0]+psrc[1]+psrc[dx]+psrc[dx+1])/4;
  729. break;
  730. default: // 1x1 pixel dot (or internal error)
  731. sum=psrc[0];
  732. break; };
  733. g[shift][j][i]=(uchar)sum;
  734. };
  735. };
  736. };
  737. // We have gathered 9 grids with 1-pixel shifts. Non-shifted grid is the
  738. // most probable good candidate, try it first.
  739. answer=Recognizebits(result,g[4],pdata);
  740. // Don't stop if in search-for-the-best-quality mode.
  741. if ((pdata->mode & M_BEST)!=0 && answer<bestanswer) {
  742. bestanswer=answer;
  743. bestresult=*result;
  744. uncorrected=pdata->uncorrected;
  745. if (answer!=0) answer=17; };
  746. // If data recognition fails, combine grid from subblocks SUBDX*SUBDY dots
  747. // with maximal dispersion. This compensates for small distortions, even
  748. // nonlinear, and partially for bidirectional print.
  749. if (answer==17) {
  750. for (j=0; j<NDOT; j+=SUBDY) {
  751. for (i=0; i<NDOT; i+=SUBDX) {
  752. dispmin=1.0e99; dispmax=-1.0e99;
  753. for (shift=0; shift<9; shift++) {
  754. sy=0.0; syy=0.0;
  755. for (y=j; y<j+SUBDY; y++) {
  756. for (x=i; x<i+SUBDX; x++) {
  757. c=g[shift][y][x];
  758. sy+=c; syy+=c*c;
  759. };
  760. };
  761. // Dispersion in the mathematical sense is a bit different beast
  762. // (includes Division, Square Roots and Other Incomprehensible
  763. // Things), but we are interested only in the shift corresponding
  764. // to the maximum.
  765. disp=syy*SUBDX*SUBDY-sy*sy;
  766. if (disp<dispmin) dispmin=disp;
  767. if (disp>dispmax) {
  768. dispmax=disp;
  769. shiftmax=shift;
  770. };
  771. };
  772. // If difference between minimal and maximal dispersion is low (the
  773. // case of mostly black/mostly white dots), I set shift to zero. 20%
  774. // for disp equals to roughly 10% in strict mathematical sense.
  775. if (dispmax-dispmin<dispmax/5.0)
  776. shiftmax=4;
  777. // Copy subblock with maximal dispersion to main grid.
  778. for (y=j; y<j+SUBDY; y++) {
  779. for (x=i; x<i+SUBDX; x++) {
  780. grid[y][x]=g[shiftmax][y][x];
  781. };
  782. };
  783. };
  784. };
  785. // Try to recognize data in the combined grid.
  786. answer=Recognizebits(result,grid,pdata);
  787. // Again, don't stop if in search-for-the-best-quality mode.
  788. if ((pdata->mode & M_BEST)!=0 && answer<bestanswer) {
  789. bestanswer=answer;
  790. bestresult=*result;
  791. uncorrected=pdata->uncorrected;
  792. if (answer!=0) answer=17;
  793. };
  794. };
  795. // If data is restored, we don't need different dot size.
  796. if (answer<17) break;
  797. };
  798. if (pdata->mode & M_BEST) {
  799. answer=bestanswer;
  800. *result=bestresult;
  801. pdata->uncorrected=uncorrected; };
  802. return answer;
  803. };
  804. static void Decodenextblock(t_procdata *pdata) {
  805. int answer,ngroup,percent;
  806. char s[TEXTLEN];
  807. t_data result;
  808. // Display percent of executed data and, if known, data name in progress bar.
  809. if (pdata->superblock.name[0]=='\0')
  810. sprintf(s,"Processing image");
  811. else {
  812. sprintf(s,"%.64s (page %i)",
  813. pdata->superblock.name,pdata->superblock.page);
  814. }
  815. percent=(pdata->posy*pdata->nposx+pdata->posx)*100/
  816. (pdata->nposx*pdata->nposy);
  817. if (percent % 10 == 0)
  818. Message(s,percent);
  819. // Decode block.
  820. answer=Decodeblock(pdata,pdata->posx,pdata->posy,&result);
  821. // If we are unable to locate block, probably we are outside the raster.
  822. if (answer<0)
  823. goto finish;
  824. // If this is the very first block located on the page, show it in the block
  825. // display window.
  826. //if (pdata->ngood==0 && pdata->nbad==0 && pdata->nsuper==0)
  827. // Displayblockimage(pdata,pdata->posx,pdata->posy,answer,&result);
  828. // Analyze answer.
  829. if (answer>=17) {
  830. // Error, block is unreadable.
  831. pdata->nbad++; }
  832. else if (result.addr==SUPERBLOCK) {
  833. // Superblock.
  834. pdata->superblock.addr=SUPERBLOCK;
  835. pdata->superblock.datasize=((t_superdata *)&result)->datasize;
  836. pdata->superblock.pagesize=((t_superdata *)&result)->pagesize;
  837. pdata->superblock.origsize=((t_superdata *)&result)->origsize;
  838. pdata->superblock.mode=((t_superdata *)&result)->mode;
  839. pdata->superblock.page=((t_superdata *)&result)->page;
  840. pdata->superblock.modified=((t_superdata *)&result)->modified;
  841. pdata->superblock.attributes=((t_superdata *)&result)->attributes;
  842. pdata->superblock.filecrc=((t_superdata *)&result)->filecrc;
  843. memcpy(pdata->superblock.name,((t_superdata *)&result)->name,64);
  844. pdata->nsuper++;
  845. pdata->nrestored+=answer; }
  846. else if (pdata->ngood<pdata->nposx*pdata->nposy) {
  847. // Success, place data block into the intermediate buffer.
  848. pdata->blocklist[pdata->ngood].addr=result.addr & 0x0FFFFFFF;
  849. ngroup=(result.addr>>28) & 0x0000000F;
  850. if (ngroup>0) { // Recovery block
  851. pdata->blocklist[pdata->ngood].recsize=ngroup*NDATA;
  852. pdata->superblock.ngroup=ngroup; }
  853. else // Data block
  854. pdata->blocklist[pdata->ngood].recsize=0;
  855. memcpy(pdata->blocklist[pdata->ngood].data,result.data,NDATA);
  856. pdata->ngood++;
  857. // Number of bytes corrected by ECC may be misleading (block is so good
  858. // it can be read with wrong settings), but I have no better indicator
  859. // of quality.
  860. pdata->nrestored+=answer; };
  861. // Add block to quality map.
  862. //Addblocktomap(pdata->posx,pdata->posy,answer);
  863. // Block processed, set new coordinates.
  864. finish:
  865. pdata->posx++;
  866. if (pdata->posx>=pdata->nposx) {
  867. pdata->posx=0;
  868. pdata->posy++;
  869. if (pdata->posy>=pdata->nposy) {
  870. pdata->step++; // Page processed
  871. };
  872. };
  873. };
  874. // Passes gathered data to file processor and frees resources allocated by call
  875. // to Preparefordecoding().
  876. static void Finishdecoding(t_procdata *pdata) {
  877. int i,fileindex;
  878. // Pass gathered data to file processor.
  879. if (pdata->superblock.addr==0)
  880. Reporterror("Page label is not readable");
  881. else {
  882. fileindex=Startnextpage(&pdata->superblock);
  883. if (fileindex>=0) {
  884. for (i=0; i<pdata->ngood; i++)
  885. Addblock(pdata->blocklist+i,fileindex);
  886. Finishpage(fileindex,
  887. pdata->ngood+pdata->nsuper,pdata->nbad,pdata->nrestored);
  888. ;
  889. };
  890. };
  891. // Page processed.
  892. pdata->step=0;
  893. };
  894. // Extracts data from the bitmap in small slices. To start decoding, pass
  895. // bitmap to Startbitmapdecoding().
  896. void Nextdataprocessingstep(t_procdata *pdata) {
  897. if (pdata==NULL)
  898. return; // Invalid data descriptor
  899. switch (pdata->step) {
  900. case 0: // Idle data
  901. return;
  902. case 1: // Remove previous images
  903. //SetWindowPos(hwmain,HWND_TOP,0,0,0,0,
  904. // SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
  905. //Initqualitymap(0,0);
  906. //Displayblockimage(NULL,0,0,0,NULL);
  907. pdata->step++;
  908. break;
  909. case 2: // Determine grid size
  910. Message("Searching for raster...",0);
  911. Getgridposition(pdata);
  912. break;
  913. case 3: // Determine min and max intensity
  914. Getgridintensity(pdata);
  915. break;
  916. case 4: // Determine step and angle in X
  917. Message("Searching for grid lines...",0);
  918. Getxangle(pdata);
  919. break;
  920. case 5: // Determine step and angle in Y
  921. Getyangle(pdata);
  922. break;
  923. case 6: // Prepare for data decoding
  924. Preparefordecoding(pdata);
  925. break;
  926. case 7: // Decode next block of data
  927. Decodenextblock(pdata);
  928. break;
  929. case 8: // Finish data decoding
  930. Finishdecoding(pdata);
  931. break;
  932. default: break; // Internal error
  933. };
  934. //if (pdata->step==0) Updatebuttons(); // Right or wrong, decoding finished
  935. };
  936. // Frees resources allocated by pdata.
  937. void Freeprocdata(t_procdata *pdata) {
  938. // Free data.
  939. if (pdata->data!=NULL) {
  940. free(pdata->data);
  941. pdata->data=NULL; };
  942. // Free allocated buffers.
  943. if (pdata->buf1!=NULL) {
  944. free(pdata->buf1);
  945. pdata->buf1=NULL; };
  946. if (pdata->buf2!=NULL) {
  947. free(pdata->buf2);
  948. pdata->buf2=NULL; };
  949. if (pdata->bufx!=NULL) {
  950. free(pdata->bufx);
  951. pdata->bufx=NULL; };
  952. if (pdata->bufy!=NULL) {
  953. free(pdata->bufy);
  954. pdata->bufy=NULL; };
  955. if (pdata->blocklist!=NULL) {
  956. free(pdata->blocklist);
  957. pdata->blocklist=NULL;
  958. };
  959. };
  960. // Starts decoding of the new bitmap. If previous decoding is still running,
  961. // it will be stopped and all intermediate results will be discarded.
  962. void Startbitmapdecoding(t_procdata *pdata,uchar *data,int sizex,int sizey) {
  963. // Free resources allocated for the previous bitmap. User may want to
  964. // browse bitmap while and after it is processed.
  965. Freeprocdata(pdata);
  966. memset(pdata,0,sizeof(t_procdata));
  967. pdata->data=data;
  968. pdata->sizex=sizex;
  969. pdata->sizey=sizey;
  970. pdata->blockborder=0.0; // Autoselect
  971. pdata->step=1;
  972. if (::pb_bestquality)
  973. pdata->mode|=M_BEST;
  974. //Updatebuttons();
  975. };
  976. // Stops bitmap decoding. Data decoded so far is discarded, but resources
  977. // (especially, bitmap) remain in memory.
  978. void Stopbitmapdecoding(t_procdata *pdata) {
  979. if (pdata->step!=0) {
  980. pdata->step=0;
  981. };
  982. };