static void wrapbmp_hyphen_erase(WRAPBMP *wrapbmp,K2PDFOPT_SETTINGS *k2settings) { WILLUSBITMAP *bmp,_bmp; int bw,bpp,c0,c1,c2,i; if (wrapbmp->hyphen.ch<0) return; #if (WILLUSDEBUGX & 16) printf("@hyphen_erase, bmp=%d x %d x %d\n",wrapbmp->bmp.width,wrapbmp->bmp.height,wrapbmp->bmp.bpp); printf(" ch=%d, c2=%d, r1=%d, r2=%d\n",wrapbmp->hyphen.ch,wrapbmp->hyphen.c2,wrapbmp->hyphen.r1,wrapbmp->hyphen.r2); #endif bmp=&_bmp; bmp_init(bmp); bmp->bpp = wrapbmp->bmp.bpp; if (bmp->bpp==8) for (i=0;i<256;i++) bmp->red[i]=bmp->blue[i]=bmp->green[i]=i; bmp->height = wrapbmp->bmp.height; if (k2settings->src_left_to_right) { bmp->width = wrapbmp->hyphen.c2+1; c0=0; c1=wrapbmp->hyphen.ch; c2=bmp->width-1; } else { bmp->width = wrapbmp->bmp.width - wrapbmp->hyphen.c2; c0=wrapbmp->hyphen.c2; c1=0; c2=wrapbmp->hyphen.ch-wrapbmp->hyphen.c2; } bmp_alloc(bmp); bpp=bmp->bpp==24 ? 3 : 1; bw=bpp*bmp->width; for (i=0;i<bmp->height;i++) memcpy(bmp_rowptr_from_top(bmp,i),bmp_rowptr_from_top(&wrapbmp->bmp,i)+bpp*c0,bw); bw=(c2-c1+1)*bpp; if (bw>0) for (i=wrapbmp->hyphen.r1;i<=wrapbmp->hyphen.r2;i++) memset(bmp_rowptr_from_top(bmp,i)+bpp*c1,255,bw); #if (WILLUSDEBUGX & 16) { static int count=1; char filename[256]; sprintf(filename,"be%04d.png",count); bmp_write(&wrapbmp->bmp,filename,stdout,100); sprintf(filename,"ae%04d.png",count); bmp_write(bmp,filename,stdout,100); count++; } #endif bmp_copy(&wrapbmp->bmp,bmp); bmp_free(bmp); }
/* ** bmp8 must be grayscale ** (x1,y1) and (x2,y2) from top left of bitmap */ void jocr_single_word_from_bmp8(char *text,int maxlen,WILLUSBITMAP *bmp8, int x1,int y1,int x2,int y2,int allow_spaces, int std_proc) { job_t *job,_job; int i,w,h,dw,dh,bw; unsigned char *src,*dst; // static char *funcname="jocr_single_word_from_bmp8"; char *buf; int pgm2asc(job_t *job); char *getTextLine(int); if (x1>x2) { w=x1; x1=x2; x2=w; } w=x2-x1+1; bw=w/40; if (bw<6) bw=6; dw=w+bw*2; if (y1>y2) { h=y1; y1=y2; y2=h; } h=y2-y1+1; dh=h+bw*2; job=&_job; job_init(job); job_init_image(job); // willus_mem_alloc_warn((void **)&job->src.p.p,w*h,funcname,10); /* Must use malloc since job_free_image counts on this. */ job->src.p.p=malloc(dw*dh); job->src.p.x=dw; job->src.p.y=dh; job->src.p.bpp=1; src=bmp_rowptr_from_top(bmp8,y1)+x1; memset(job->src.p.p,255,dw*dh); dst=(unsigned char *)job->src.p.p + dw*bw + bw; for (i=y1;i<=y2;i++,dst+=dw,src+=bmp8->width) memcpy(dst,src,w); pgm2asc(job); buf=getTextLine(0); if (buf) { strncpy(text,buf,maxlen-1); text[maxlen-1]='\0'; if (std_proc) ocr_text_proc(text,allow_spaces); } else text[0]='\0'; // willus_mem_free((double **)&job->src.p.p,funcname); job_free_image(job); }
static int bmpmupdf_pixmap_to_bmp(WILLUSBITMAP *bmp,fz_context *ctx,fz_pixmap *pixmap) { unsigned char *p; int ncomp,i,row,col; bmp->width=fz_pixmap_width(ctx,pixmap); bmp->height=fz_pixmap_height(ctx,pixmap); ncomp=fz_pixmap_components(ctx,pixmap); /* Has to be 8-bit or RGB */ if (ncomp != 2 && ncomp != 4) return(-1); bmp->bpp=(ncomp==2) ? 8 : 24; bmp_alloc(bmp); if (ncomp==2) for (i=0;i<256;i++) bmp->red[i]=bmp->green[i]=bmp->blue[i]=i; p = fz_pixmap_samples(ctx,pixmap); if (ncomp==1) for (row=0;row<bmp->height;row++) { unsigned char *dest; dest=bmp_rowptr_from_top(bmp,row); memcpy(dest,p,bmp->width); p+=bmp->width; } else if (ncomp==2) for (row=0;row<bmp->height;row++) { unsigned char *dest; dest=bmp_rowptr_from_top(bmp,row); for (col=0;col<bmp->width;col++,dest++,p+=2) dest[0]=p[0]; } else for (row=0;row<bmp->height;row++) { unsigned char *dest; dest=bmp_rowptr_from_top(bmp,row); for (col=0;col<bmp->width;col++,dest+=ncomp-1,p+=ncomp) memcpy(dest,p,ncomp-1); } return(0); }
/* ** bmpgray must be 8-bit grayscale. bmp can be either 8-bit or 24-bit. */ void bmp_paint_white(WILLUSBITMAP *bmpgray,WILLUSBITMAP *bmp,int white_thresh) { int i,bpp; bpp=bmp->bpp==24 ? 3 : 1; for (i=0;i<bmpgray->height;i++) { unsigned char *pgray,*p; int j; pgray=bmp_rowptr_from_top(bmpgray,i); p=bmp_rowptr_from_top(bmp,i); for (j=0;j<bmpgray->width;j++,pgray++,p+=bpp) if ((*pgray) >= white_thresh) { (*pgray) = 255; memset(p,255,bpp); } } }
double bmp_inflections_horizontal(WILLUSBITMAP *srcgrey,int ndivisions,int delta,int *wthresh) { int x0,x1,nx,bw,i,nh,nisum,ni,wt,wtmax; double *g; char *funcname="bmp_inflections_vertical"; nh=srcgrey->height/ndivisions; x0=srcgrey->width/6; x1=srcgrey->width-x0; nx=x1-x0; bw=bmp_bytewidth(srcgrey); willus_dmem_alloc_warn(22,(void **)&g,nx*sizeof(double),funcname,10); wtmax=-1; for (nisum=0,i=0;i<10;i++) { int y0,y1,ny,j; y0=(srcgrey->height-nh)*(i+2)/13; y1=y0+nh; if (y1>srcgrey->height) y1=srcgrey->height; ny=y1-y0; for (j=x0;j<x1;j++) { int k,rsum; unsigned char *p; p=bmp_rowptr_from_top(srcgrey,y0)+j; for (rsum=k=0;k<ny;k++,p+=bw) rsum+=p[0]; g[j-x0]=(double)rsum/ny; } wt=(*wthresh); ni=inflection_count(g,nx,delta,&wt); if ((*wthresh)<0 && ni>=3 && wt>wtmax) wtmax=wt; if (ni>nisum) nisum=ni; } willus_dmem_free(22,&g,funcname); if ((*wthresh)<0) (*wthresh)=wtmax; return(nisum); }
double bmp_inflections_vertical(WILLUSBITMAP *srcgrey,int ndivisions,int delta,int *wthresh) { int y0,y1,ny,i,nw,nisum,ni,wt,wtmax; double *g; char *funcname="bmp_inflections_vertical"; nw=srcgrey->width/ndivisions; y0=srcgrey->height/6; y1=srcgrey->height-y0; ny=y1-y0; willus_dmem_alloc_warn(21,(void **)&g,ny*sizeof(double),funcname,10); wtmax=-1; for (nisum=0,i=0;i<10;i++) { int x0,x1,nx,j; x0=(srcgrey->width-nw)*(i+2)/13; x1=x0+nw; if (x1>srcgrey->width) x1=srcgrey->width; nx=x1-x0; for (j=y0;j<y1;j++) { int k,rsum; unsigned char *p; p=bmp_rowptr_from_top(srcgrey,j)+x0; for (rsum=k=0;k<nx;k++,p++) rsum+=p[0]; g[j-y0]=(double)rsum/nx; } wt=(*wthresh); ni=inflection_count(g,ny,delta,&wt); if ((*wthresh)<0 && ni>=3 && wt>wtmax) wtmax=wt; if (ni>nisum) nisum=ni; } willus_dmem_free(21,&g,funcname); if ((*wthresh)<0) (*wthresh)=wtmax; return(nisum); }
/* ** Mark the region ** mark_flags & 1 : Mark top ** mark_flags & 2 : Mark bottom ** mark_flags & 4 : Mark left ** mark_flags & 8 : Mark right ** */ void mark_source_page(K2PDFOPT_SETTINGS *k2settings,BMPREGION *region0,int caller_id,int mark_flags) { static int display_order=0; int i,n,nn,r,g,b; #ifndef K2PDFOPT_KINDLEPDFVIEWER int shownum,nval,fontsize; char num[16]; #endif BMPREGION *region,_region; BMPREGION *clip,_clip; if (!k2settings->show_marked_source) return; /* Don't waste time marking this page if we're previewing and this isn't the preview page */ if (k2settings->preview_page!=0 && abs(k2settings->preview_page)!=k2mark_page_count) return; if (region0==NULL) { display_order=0; return; } region=&_region; (*region)=(*region0); /* Clip the region w/ignored margins */ clip=&_clip; clip->bmp=region0->bmp; clip->dpi=region0->dpi; bmpregion_trim_to_crop_margins(clip,k2settings); if (region->c1 < clip->c1) region->c1 = clip->c1; if (region->c2 > clip->c2) region->c2 = clip->c2; if (region->r1 < clip->r1) region->r1 = clip->r1; if (region->r2 > clip->r2) region->r2 = clip->r2; if (region->r2 <= region->r1 || region->c2 <= region->c1) return; /* k2printf("@mark_source_page(display_order=%d)\n",display_order); */ #ifndef K2PDFOPT_KINDLEPDFVIEWER shownum=0; nval=0; #endif if (caller_id==1) { display_order++; #ifndef K2PDFOPT_KINDLEPDFVIEWER shownum=1; nval=display_order; #endif n=(int)(region->dpi/60.+0.5); if (n<5) n=5; r=255; g=b=0; } else if (caller_id==2) { n=2; r=0; g=0; b=255; } else if (caller_id==3) { n=(int)(region->dpi/80.+0.5); if (n<4) n=4; r=0; g=255; b=0; } else if (caller_id==4) { n=2; r=255; g=0; b=255; } else if (caller_id>=100 && caller_id<=199) { #ifndef K2PDFOPT_KINDLEPDFVIEWER shownum=1; nval=caller_id-100; #endif n=3; r=255; g=90; b=40; } else { n=2; r=140; g=140; b=140; } if (n<2) n=2; nn=(region->c2+1-region->c1)/2; if (n>nn) n=nn; nn=(region->r2+1-region->r1)/2; if (n>nn) n=nn; if (n<1) n=1; for (i=0;i<n;i++) { int j; unsigned char *p; if (mark_flags & 1) { p=bmp_rowptr_from_top(region->marked,region->r1+i)+region->c1*3; for (j=region->c1;j<=region->c2;j++,p+=3) { p[0]=r; p[1]=g; p[2]=b; } } if (mark_flags & 2) { p=bmp_rowptr_from_top(region->marked,region->r2-i)+region->c1*3; for (j=region->c1;j<=region->c2;j++,p+=3) { p[0]=r; p[1]=g; p[2]=b; } } /* rowbase */ if ((mark_flags & 16) && region->bbox.type!=REGION_TYPE_FIGURE && region->bbox.rowbase>=region->r1 && region->bbox.rowbase<=region->r2) { p=bmp_rowptr_from_top(region->marked,region->bbox.rowbase-i)+region->c1*3; for (j=region->c1;j<=region->c2;j++,p+=3) { p[0]=r; p[1]=g; p[2]=b; } } if (mark_flags & 4) for (j=region->r1;j<=region->r2;j++) { p=bmp_rowptr_from_top(region->marked,j)+(region->c1+i)*3; p[0]=r; p[1]=g; p[2]=b; } if (mark_flags & 8) for (j=region->r1;j<=region->r2;j++) { p=bmp_rowptr_from_top(region->marked,j)+(region->c2-i)*3; p[0]=r; p[1]=g; p[2]=b; } } /* ** Compiling out the fontrender...() functions reduces the exe size ** considerably because it eliminates the font data from being compiled in. */ #ifndef K2PDFOPT_KINDLEPDFVIEWER if (!shownum) return; fontsize=region->c2-region->c1+1; if (fontsize > region->r2-region->r1+1) fontsize=region->r2-region->r1+1; fontsize /= 2; if (fontsize > region->dpi) fontsize = region->dpi; if (fontsize < 5) return; fontrender_set_typeface("helvetica-bold"); fontrender_set_fgcolor(r,g,b); fontrender_set_bgcolor(255,255,255); fontrender_set_pixel_size(fontsize); fontrender_set_justification(4); fontrender_set_or(1); sprintf(num,"%d",nval); fontrender_render(region->marked,(double)(region->c1+region->c2)/2., (double)(region->marked->height-((region->r1+region->r2)/2.)),num,0,NULL); #endif /* k2printf(" done mark_source_page.\n"); */ }
void k2pdfopt_reflow_bmp(KOPTContext *kctx) { K2PDFOPT_SETTINGS _k2settings, *k2settings; MASTERINFO _masterinfo, *masterinfo; WILLUSBITMAP _srcgrey, *srcgrey; WILLUSBITMAP *src, *dst; BMPREGION region; int i, bw, marbot, marleft; src = &kctx->src; srcgrey = &_srcgrey; bmp_init(srcgrey); k2settings = &_k2settings; masterinfo = &_masterinfo; /* Initialize settings */ k2pdfopt_settings_init_from_koptcontext(k2settings, kctx); k2pdfopt_settings_quick_sanity_check(k2settings); /* Init for new source doc */ k2pdfopt_settings_new_source_document_init(k2settings); /* Init master output structure */ masterinfo_init(masterinfo, k2settings); wrapbmp_init(&masterinfo->wrapbmp, k2settings->dst_color); /* Init new source bitmap */ bmpregion_init(®ion); masterinfo_new_source_page_init(masterinfo, k2settings, src, srcgrey, NULL, ®ion, k2settings->src_rot, NULL, NULL, 1, -1, NULL ); /* Set output size */ k2pdfopt_settings_set_margins_and_devsize(k2settings,®ion,masterinfo,-1.,0); /* Process single source page */ bmpregion_source_page_add(®ion, k2settings, masterinfo, 1, 0); wrapbmp_flush(masterinfo, k2settings, 0); if (fabs(k2settings->dst_gamma - 1.0) > .001) bmp_gamma_correct(&masterinfo->bmp, &masterinfo->bmp, k2settings->dst_gamma); /* copy master bitmap to context dst bitmap */ dst = &kctx->dst; marbot = (int) (k2settings->dst_dpi * k2settings->dstmargins.box[1] + .5); marleft = (int) (k2settings->dst_dpi * k2settings->dstmargins.box[0] + .5); dst->bpp = masterinfo->bmp.bpp; dst->width = masterinfo->bmp.width; dst->height = masterinfo->rows > kctx->page_height ? masterinfo->rows + marbot : kctx->page_height; bmp_alloc(dst); bmp_fill(dst, 255, 255, 255); bw = bmp_bytewidth(&masterinfo->bmp); for (i = 0; i < masterinfo->rows; i++) memcpy(bmp_rowptr_from_top(dst, i), bmp_rowptr_from_top(&masterinfo->bmp, i), bw); kctx->page_width = kctx->dst.width; kctx->page_height = kctx->dst.height; kctx->precache = 0; int j; BOXA *rboxa = boxaCreate(masterinfo->rectmaps.n); BOXA *nboxa = boxaCreate(masterinfo->rectmaps.n); for (j = 0; j < masterinfo->rectmaps.n; j++) { WRECTMAP * rectmap = &masterinfo->rectmaps.wrectmap[j]; rectmap->coords[1].x += marleft; BOX* rlbox = boxCreate(rectmap->coords[1].x, rectmap->coords[1].y, rectmap->coords[2].x, rectmap->coords[2].y); BOX* nlbox = boxCreate(rectmap->coords[0].x*k2settings->src_dpi/rectmap->srcdpiw/kctx->zoom + kctx->bbox.x0, rectmap->coords[0].y*k2settings->src_dpi/rectmap->srcdpih/kctx->zoom + kctx->bbox.y0, rectmap->coords[2].x*k2settings->src_dpi/rectmap->srcdpiw/kctx->zoom, rectmap->coords[2].y*k2settings->src_dpi/rectmap->srcdpih/kctx->zoom); boxaAddBox(rboxa, rlbox, L_INSERT); boxaAddBox(nboxa, nlbox, L_INSERT); wrectmaps_add_wrectmap(&kctx->rectmaps, rectmap); /*printf("rectmap:coords:\t%.1f %.1f\t%.1f %.1f\t%.1f %.1f\t%.1f %.1f\n", rectmap->coords[0].x, rectmap->coords[0].y, rectmap->coords[1].x, rectmap->coords[1].y, rectmap->coords[2].x, rectmap->coords[2].y, rectmap->srcdpiw, rectmap->srcdpih);*/ } /* 2D sort the bounding boxes of these words. */ BOXAA *rbaa = boxaSort2d(rboxa, NULL, 3, -5, 5); BOXAA *nbaa = boxaSort2d(nboxa, NULL, 3, -5, 5); /* Flatten the boxaa, saving the boxa index for each box */ kctx->rboxa = boxaaFlattenToBoxa(rbaa, &kctx->rnai, L_CLONE); kctx->nboxa = boxaaFlattenToBoxa(nbaa, &kctx->nnai, L_CLONE); boxaDestroy(&rboxa); boxaaDestroy(&rbaa); boxaDestroy(&nboxa); boxaaDestroy(&nbaa); bmp_free(src); bmp_free(srcgrey); bmpregion_free(®ion); masterinfo_free(masterinfo, k2settings); }
// static int bcount=0; void wrapbmp_add(WRAPBMP *wrapbmp,BMPREGION *region,K2PDFOPT_SETTINGS *k2settings, MASTERINFO *masterinfo,int colgap,int just_flags) { WILLUSBITMAP *tmp,_tmp; int i,rh,th,bw,new_base,h2,bpp,width0; // static char filename[256]; #if (WILLUSDEBUGX & 205) k2printf("@wrapbmp->add %d x %d (w=%d).\n",region->c2-region->c1+1,region->r2-region->r1+1,wrapbmp->bmp.width); printf(" line_spacing=%d\n",region->bbox.rowheight); #endif /* Figure out if what we're adding ends in a hyphen */ bmpregion_hyphen_detect(region,k2settings->hyphen_detect,k2settings->src_left_to_right); if (wrapbmp_ends_in_hyphen(wrapbmp)) colgap=0; wrapbmp_hyphen_erase(wrapbmp,k2settings); wrapbmp->just_flushed_internal=0; // Reset "just flushed" flag if (wrapbmp->bmp.width==0) wrapbmp->textrow=region->bbox; else { if (region->bbox.rowheight > wrapbmp->textrow.rowheight) wrapbmp->textrow.rowheight = region->bbox.rowheight; if (region->bbox.gap > wrapbmp->textrow.gap) wrapbmp->textrow.gap = region->bbox.gap; if (region->bbox.gapblank > wrapbmp->textrow.gapblank) wrapbmp->textrow.gapblank = region->bbox.gapblank; } wrapbmp->bgcolor=region->bgcolor; wrapbmp->just=just_flags; if (wrapbmp->mandatory_region_gap<0) { wrapbmp->mandatory_region_gap=masterinfo->mandatory_region_gap; wrapbmp->page_region_gap_in=masterinfo->page_region_gap_in; masterinfo->mandatory_region_gap=0; masterinfo->page_region_gap_in=-1.; #if (WILLUSDEBUGX & 0x200) aprintf(ANSI_RED "mi->mandatory_region_gap change to %d by wrap_add." ANSI_NORMAL "\n",masterinfo->mandatory_region_gap); #endif } #if (WILLUSDEBUGX & 4) k2printf(" c1=%d, c2=%d, r1=%d, r2=%d\n",region->c1,region->c2,region->r1,region->r2); k2printf(" colgap=%d, line_spacing=%d, rowbase=%d, row gap=%d\n",colgap,region->bbox.rowheight,region->bbox.rowbase,region->bbox.gap); #endif bpp=k2settings->dst_color?3:1; rh=region->bbox.rowbase-region->r1+1; if (rh > wrapbmp->rhmax) wrapbmp->rhmax=rh; th = rh + (region->r2-region->bbox.rowbase); if (th > wrapbmp->thmax) wrapbmp->thmax=th; #if (WILLUSDEBUGX & 4) { static int bcount=0; char filename[256]; sprintf(filename,"out%05d.png",bcount++); bmpregion_write(region,filename); } #endif if (wrapbmp->bmp.width==0) { /* Put appropriate gap in */ /* if (k2settings->last_rowbase_internal>=0 && rh < wrapbmp->textrow.rowheight-k2settings->last_rowbase_internal) { rh = wrapbmp->textrow.rowheight - k2settings->last_rowbase_internal; if (rh<2) rh=2; th = rh + (region->r2-region->bbox.rowbase); wrapbmp->height_extended=0; } else wrapbmp->height_extended=(k2settings->last_rowbase_internal>=0); */ wrapbmp->base = rh-1; wrapbmp->bmp.height = th; #if (WILLUSDEBUGX & 4) k2printf(" bmpheight set to %d (line spacing=%d)\n",wrapbmp->bmp.height,wrapbmp->textrow.rowheight); #endif wrapbmp->bmp.width=region->c2-region->c1+1; bmp_alloc(&wrapbmp->bmp); bw=bmp_bytewidth(&wrapbmp->bmp); memset(bmp_rowptr_from_top(&wrapbmp->bmp,0),255,bw*wrapbmp->bmp.height); for (i=region->r1;i<=region->r2;i++) { unsigned char *d,*s; d=bmp_rowptr_from_top(&wrapbmp->bmp,wrapbmp->base+(i-region->bbox.rowbase)); s=bmp_rowptr_from_top(k2settings->dst_color?region->bmp:region->bmp8,i)+bpp*region->c1; memcpy(d,s,bw); } #ifdef WILLUSDEBUG if (wrapbmp->bmp.height<=wrapbmp->base) { k2printf("1. SCREEECH!\n"); k2printf("wrapbmp = %d x %d, base=%d\n",wrapbmp->bmp.width,wrapbmp->bmp.height,wrapbmp->base); exit(10); } #endif /* Copy hyphen info from added region */ wrapbmp->hyphen = region->bbox.hyphen; if (wrapbmp_ends_in_hyphen(wrapbmp)) { wrapbmp->hyphen.r1 += (wrapbmp->base-region->bbox.rowbase); wrapbmp->hyphen.r2 += (wrapbmp->base-region->bbox.rowbase); wrapbmp->hyphen.ch -= region->c1; wrapbmp->hyphen.c2 -= region->c1; } /* Map to source page */ { WRECTMAP _wrmap,*wrmap; wrmap=&_wrmap; wrmap->srcpageno = region->pageno; wrmap->srcwidth = region->bmp8->width; wrmap->srcheight = region->bmp8->height; wrmap->srcdpiw = wrmap->srcdpih = region->dpi; wrmap->srcrot = region->rotdeg; wrmap->coords[0].x = region->c1; wrmap->coords[0].y = region->r1; wrmap->coords[1].x = 0; wrmap->coords[1].y = wrapbmp->base+(region->r1-region->bbox.rowbase); wrmap->coords[2].x = region->c2-region->c1+1; wrmap->coords[2].y = region->r2-region->r1+1; #if (WILLUSDEBUGX & 0x400) printf("@wrapbmp: (x0,y0) = (%5.1f,%5.1f)\n",region->c1*72./region->dpi,region->r1*72./region->dpi); printf(" %5.1f x %5.1f\n",(region->c2-region->c1+1)*72./region->dpi,(region->r2-region->r1+1)*72./region->dpi); printf(" New bitmap = %d x %d\n",wrapbmp->bmp.width,wrapbmp->bmp.height); #endif wrectmaps_add_wrectmap(&wrapbmp->wrectmaps,wrmap); } return; } width0=wrapbmp->bmp.width; /* Starting wrapbmp width */ tmp=&_tmp; bmp_init(tmp); bmp_copy(tmp,&wrapbmp->bmp); tmp->width += colgap+region->c2-region->c1+1; if (rh > wrapbmp->base) { /* wrapbmp->height_extended=1; */ new_base = rh-1; } else new_base = wrapbmp->base; if (region->r2-region->bbox.rowbase > wrapbmp->bmp.height-1-wrapbmp->base) h2=region->r2-region->bbox.rowbase; else h2=wrapbmp->bmp.height-1-wrapbmp->base; tmp->height = new_base + h2 + 1; bmp_alloc(tmp); bw=bmp_bytewidth(tmp); memset(bmp_rowptr_from_top(tmp,0),255,bw*tmp->height); bw=bmp_bytewidth(&wrapbmp->bmp); #if (WILLUSDEBUGX & 4) k2printf("3. wbh=%d x %d, tmp=%d x %d x %d, new_base=%d, wbbase=%d\n",wrapbmp->bmp.width,wrapbmp->bmp.height,tmp->width,tmp->height,tmp->bpp,new_base,wrapbmp->base); #endif /* Adjust previous mappings to source pages since WRAPBMP rectangle has been re-sized */ if (new_base!=wrapbmp->base) for (i=0;i<wrapbmp->wrectmaps.n;i++) { wrapbmp->wrectmaps.wrectmap[i].coords[1].y += (new_base-wrapbmp->base); if (k2settings->src_left_to_right==0) wrapbmp->wrectmaps.wrectmap[i].coords[1].x += tmp->width-1-wrapbmp->bmp.width; } for (i=0;i<wrapbmp->bmp.height;i++) { unsigned char *d,*s; d=bmp_rowptr_from_top(tmp,i+new_base-wrapbmp->base) + (k2settings->src_left_to_right ? 0 : tmp->width-1-wrapbmp->bmp.width)*bpp; s=bmp_rowptr_from_top(&wrapbmp->bmp,i); memcpy(d,s,bw); } bw=bpp*(region->c2-region->c1+1); if (region->r1+new_base-region->bbox.rowbase<0 || region->r2+new_base-region->bbox.rowbase>tmp->height-1) { k2printf(ANSI_YELLOW "INTERNAL ERROR--TMP NOT DIMENSIONED PROPERLY.\n"); k2printf("(%d-%d), tmp->height=%d\n" ANSI_NORMAL, region->r1+new_base-region->bbox.rowbase, region->r2+new_base-region->bbox.rowbase,tmp->height); exit(10); } for (i=region->r1;i<=region->r2;i++) { unsigned char *d,*s; d=bmp_rowptr_from_top(tmp,i+new_base-region->bbox.rowbase) + (k2settings->src_left_to_right ? wrapbmp->bmp.width+colgap : 0)*bpp; s=bmp_rowptr_from_top(k2settings->dst_color?region->bmp:region->bmp8,i)+bpp*region->c1; memcpy(d,s,bw); } { WRECTMAP _wrmap,*wrmap; wrmap=&_wrmap; wrmap->srcpageno = region->pageno; wrmap->srcwidth = region->bmp8->width; wrmap->srcheight = region->bmp8->height; wrmap->srcdpiw = wrmap->srcdpih = region->dpi; wrmap->srcrot = region->rotdeg; wrmap->coords[0].x = region->c1; wrmap->coords[0].y = region->r1; wrmap->coords[1].x = k2settings->src_left_to_right ? wrapbmp->bmp.width+colgap : 0; wrmap->coords[1].y = region->r1+new_base-region->bbox.rowbase; wrmap->coords[2].x = region->c2-region->c1+1; wrmap->coords[2].y = region->r2-region->r1+1; #if (WILLUSDEBUGX & 0x400) printf("@wrapbmp: (x0,y0) = (%5.1f,%5.1f)\n",region->c1*72./region->dpi,region->r1*72./region->dpi); printf(" org bmp = %d x %d\n",wrapbmp->bmp.width,wrapbmp->bmp.height); printf(" new_base=%d, r_base=%d\n",new_base,region->bbox.rowbase); printf(" (x1,y1) = (%g,%g)\n",wrmap->coords[1].x,wrmap->coords[1].y); printf(" %5.1f x %5.1f\n",(region->c2-region->c1+1)*72./region->dpi,(region->r2-region->r1+1)*72./region->dpi); printf(" New bitmap = %d x %d\n",tmp->width,tmp->height); #endif wrectmaps_add_wrectmap(&wrapbmp->wrectmaps,wrmap); } bmp_copy(&wrapbmp->bmp,tmp); #if (WILLUSDEBUGX & 4) { static int rcount=0; char filename[256]; sprintf(filename,"result%03d.png",rcount++); bmp_write(tmp,filename,stdout,100); } #endif bmp_free(tmp); /* Copy region's hyphen info */ wrapbmp->hyphen = region->bbox.hyphen; if (wrapbmp_ends_in_hyphen(wrapbmp)) { wrapbmp->hyphen.r1 += (new_base-region->bbox.rowbase); wrapbmp->hyphen.r2 += (new_base-region->bbox.rowbase); if (k2settings->src_left_to_right) { wrapbmp->hyphen.ch += width0+colgap-region->c1; wrapbmp->hyphen.c2 += width0+colgap-region->c1; } else { wrapbmp->hyphen.ch -= region->c1; wrapbmp->hyphen.c2 -= region->c1; } } wrapbmp->base=new_base; /* Doesn't seem to work? v2.00 */ /* wrapbmp->textrow.gap = (wrapbmp->bmp.height-1)-new_base; wrapbmp->textrow.gapblank = 0; */ #ifdef WILLUSDEBUG if (wrapbmp->bmp.height<=wrapbmp->base) { k2printf("2. SCREEECH!\n"); k2printf("wrapbmp = %d x %d, base=%d\n",wrapbmp->bmp.width,wrapbmp->bmp.height,wrapbmp->base); exit(10); } #endif }
// static int bcount=0; void wrapbmp_add(WRAPBMP *wrapbmp,BMPREGION *region,K2PDFOPT_SETTINGS *k2settings, int gap,int line_spacing,int rbase,int gio,int just_flags) { WILLUSBITMAP *tmp,_tmp; int i,rh,th,bw,new_base,h2,bpp,width0; // static char filename[256]; #ifdef WILLUSDEBUG printf("@wrapbmp->add %d x %d (w=%d).\n",region->c2-region->c1+1,region->r2-region->r1+1,wrapbmp->bmp.width); #endif /* Figure out if what we're adding ends in a hyphen */ bmpregion_hyphen_detect(region,k2settings->hyphen_detect,k2settings->src_left_to_right); if (wrapbmp_ends_in_hyphen(wrapbmp)) gap=0; wrapbmp_hyphen_erase(wrapbmp,k2settings); wrapbmp->just_flushed_internal=0; // Reset "just flushed" flag wrapbmp->beginning_gap_internal = -1; // Reset top-of-page or top-of-column gap wrapbmp->last_h5050_internal = -1; // Reset last row font size if (line_spacing > wrapbmp->line_spacing) wrapbmp->line_spacing = line_spacing; if (gio > wrapbmp->gap) wrapbmp->gap = gio; wrapbmp->bgcolor=region->bgcolor; wrapbmp->just=just_flags; /* printf(" c1=%d, c2=%d, r1=%d, r2=%d\n",region->c1,region->c2,region->r1,region->r2); printf(" gap=%d, line_spacing=%d, rbase=%d, gio=%d\n",gap,line_spacing,rbase,gio); */ bpp=k2settings->dst_color?3:1; rh=rbase-region->r1+1; if (rh > wrapbmp->rhmax) wrapbmp->rhmax=rh; th = rh + (region->r2-rbase); if (th > wrapbmp->thmax) wrapbmp->thmax=th; /* { WILLUSBITMAP *bmp,_bmp; bmp=&_bmp; bmp_init(bmp); bmp->height=region->r2-region->r1+1; bmp->width=region->c2-region->c1+1; bmp->bpp=bpp*8; if (bpp==1) for (i=0;i<256;i++) bmp->red[i]=bmp->blue[i]=bmp->green[i]=i; bmp_alloc(&wrapbmp->bmp); bw=bmp_bytewidth(&wrapbmp->bmp); memset(bmp_rowptr_from_top(bmp,0),255,bw*bmp->height); for (i=region->r1;i<=region->r2;i++) { unsigned char *d,*s; d=bmp_rowptr_from_top(bmp,i-region->r1); s=bmp_rowptr_from_top(k2settings->dst_color?region->bmp:region->bmp8,i)+bpp*region->c1; if (i==rbase) memset(d,0,bw); else memcpy(d,s,bw); } sprintf(filename,"out%05d.png",bcount++); bmp_write(bmp,filename,stdout,100); bmp_free(bmp); } */ if (wrapbmp->bmp.width==0) { /* Put appropriate gap in */ if (k2settings->last_rowbase_internal>=0 && rh < wrapbmp->line_spacing-k2settings->last_rowbase_internal) { rh = wrapbmp->line_spacing - k2settings->last_rowbase_internal; if (rh<2) rh=2; th = rh + (region->r2-rbase); wrapbmp->height_extended=0; } else wrapbmp->height_extended=(k2settings->last_rowbase_internal>=0); wrapbmp->base = rh-1; wrapbmp->bmp.height = th; #ifdef WILLUSDEBUG printf("@wrapbmp->add: bmpheight set to %d (wls=%d, lrbi=%d)\n",wrapbmp->bmp.height,wrapbmp->line_spacing,k2settings->last_rowbase_internal); #endif wrapbmp->bmp.width=region->c2-region->c1+1; bmp_alloc(&wrapbmp->bmp); bw=bmp_bytewidth(&wrapbmp->bmp); memset(bmp_rowptr_from_top(&wrapbmp->bmp,0),255,bw*wrapbmp->bmp.height); for (i=region->r1;i<=region->r2;i++) { unsigned char *d,*s; d=bmp_rowptr_from_top(&wrapbmp->bmp,wrapbmp->base+(i-rbase)); s=bmp_rowptr_from_top(k2settings->dst_color?region->bmp:region->bmp8,i)+bpp*region->c1; memcpy(d,s,bw); } #ifdef WILLUSDEBUG if (wrapbmp->bmp.height<=wrapbmp->base) { printf("1. SCREEECH!\n"); printf("wrapbmp = %d x %d, base=%d\n",wrapbmp->bmp.width,wrapbmp->bmp.height,wrapbmp->base); exit(10); } #endif /* Copy hyphen info from added region */ wrapbmp->hyphen = region->hyphen; if (wrapbmp_ends_in_hyphen(wrapbmp)) { wrapbmp->hyphen.r1 += (wrapbmp->base-rbase); wrapbmp->hyphen.r2 += (wrapbmp->base-rbase); wrapbmp->hyphen.ch -= region->c1; wrapbmp->hyphen.c2 -= region->c1; } return; } width0=wrapbmp->bmp.width; /* Starting wrapbmp width */ tmp=&_tmp; bmp_init(tmp); bmp_copy(tmp,&wrapbmp->bmp); tmp->width += gap+region->c2-region->c1+1; if (rh > wrapbmp->base) { wrapbmp->height_extended=1; new_base = rh-1; } else new_base = wrapbmp->base; if (region->r2-rbase > wrapbmp->bmp.height-1-wrapbmp->base) h2=region->r2-rbase; else h2=wrapbmp->bmp.height-1-wrapbmp->base; tmp->height = new_base + h2 + 1; bmp_alloc(tmp); bw=bmp_bytewidth(tmp); memset(bmp_rowptr_from_top(tmp,0),255,bw*tmp->height); bw=bmp_bytewidth(&wrapbmp->bmp); /* printf("3. wbh=%d x %d, tmp=%d x %d x %d, new_base=%d, wbbase=%d\n",wrapbmp->bmp.width,wrapbmp->bmp.height,tmp->width,tmp->height,tmp->bpp,new_base,wrapbmp->base); */ for (i=0;i<wrapbmp->bmp.height;i++) { unsigned char *d,*s; d=bmp_rowptr_from_top(tmp,i+new_base-wrapbmp->base) + (k2settings->src_left_to_right ? 0 : tmp->width-1-wrapbmp->bmp.width)*bpp; s=bmp_rowptr_from_top(&wrapbmp->bmp,i); memcpy(d,s,bw); } bw=bpp*(region->c2-region->c1+1); if (region->r1+new_base-rbase<0 || region->r2+new_base-rbase>tmp->height-1) { aprintf(ANSI_YELLOW "INTERNAL ERROR--TMP NOT DIMENSIONED PROPERLY.\n"); aprintf("(%d-%d), tmp->height=%d\n" ANSI_NORMAL, region->r1+new_base-rbase, region->r2+new_base-rbase,tmp->height); exit(10); } for (i=region->r1;i<=region->r2;i++) { unsigned char *d,*s; d=bmp_rowptr_from_top(tmp,i+new_base-rbase) + (k2settings->src_left_to_right ? wrapbmp->bmp.width+gap : 0)*bpp; s=bmp_rowptr_from_top(k2settings->dst_color?region->bmp:region->bmp8,i)+bpp*region->c1; memcpy(d,s,bw); } bmp_copy(&wrapbmp->bmp,tmp); bmp_free(tmp); /* Copy region's hyphen info */ wrapbmp->hyphen = region->hyphen; if (wrapbmp_ends_in_hyphen(wrapbmp)) { wrapbmp->hyphen.r1 += (new_base-rbase); wrapbmp->hyphen.r2 += (new_base-rbase); if (k2settings->src_left_to_right) { wrapbmp->hyphen.ch += width0+gap-region->c1; wrapbmp->hyphen.c2 += width0+gap-region->c1; } else { wrapbmp->hyphen.ch -= region->c1; wrapbmp->hyphen.c2 -= region->c1; } } wrapbmp->base=new_base; #ifdef WILLUSDEBUG if (wrapbmp->bmp.height<=wrapbmp->base) { printf("2. SCREEECH!\n"); printf("wrapbmp = %d x %d, base=%d\n",wrapbmp->bmp.width,wrapbmp->bmp.height,wrapbmp->base); exit(10); } #endif }
void bmp_adjust_contrast(WILLUSBITMAP *src,WILLUSBITMAP *srcgrey, K2PDFOPT_SETTINGS *k2settings,int *white) { int i,j,tries,wc,tc,hist[256]; double contrast,rat0; WILLUSBITMAP *dst,_dst; if (k2settings->debug && k2settings->verbose) k2printf("\nAt adjust_contrast.\n"); if ((*white) <= 0) (*white)=192; /* If contrast_max negative, use it as fixed contrast adjustment. */ if (k2settings->contrast_max < 0.) { bmp_contrast_adjust(srcgrey,srcgrey,-k2settings->contrast_max); if (k2settings->dst_color && fabs(k2settings->contrast_max+1.0)>1e-4) bmp_contrast_adjust(src,src,-k2settings->contrast_max); return; } dst=&_dst; bmp_init(dst); wc=0; /* Avoid compiler warning */ tc=srcgrey->width*srcgrey->height; rat0=0.5; /* Avoid compiler warning */ for (contrast=1.0,tries=0;contrast<k2settings->contrast_max+.01;tries++) { if (fabs(contrast-1.0)>1e-4) bmp_contrast_adjust(dst,srcgrey,contrast); else bmp_copy(dst,srcgrey); /*Get bitmap histogram */ for (i=0;i<256;i++) hist[i]=0; for (j=0;j<dst->height;j++) { unsigned char *p; p=bmp_rowptr_from_top(dst,j); for (i=0;i<dst->width;i++,p++) hist[p[0]]++; } if (tries==0) { int h1; for (h1=0,j=(*white);j<256;j++) h1+=hist[j]; rat0=(double)h1/tc; if (k2settings->debug && k2settings->verbose) k2printf(" rat0 = rat[%d-255]=%.4f\n",(*white),rat0); } /* Find white ratio */ /* for (wc=hist[254],j=253;j>=252;j--) if (hist[j]>wc1) wc1=hist[j]; */ for (wc=0,j=252;j<=255;j++) wc += hist[j]; /* if ((double)wc/tc >= rat0*0.7 && (double)hist[255]/wc > 0.995) break; */ if (k2settings->debug && k2settings->verbose) k2printf(" %2d. Contrast=%7.2f, rat[252-255]/rat0=%.4f\n", tries+1,contrast,(double)wc/tc/rat0); if ((double)wc/tc >= rat0*0.94) break; contrast *= 1.05; } if (k2settings->debug) k2printf("Contrast=%7.2f, rat[252-255]/rat0=%.4f\n", contrast,(double)wc/tc/rat0); /* bmp_write(dst,"outc.png",stdout,100); wfile_written_info("outc.png",stdout); exit(10); */ bmp_copy(srcgrey,dst); /* Maybe don't adjust the contrast for the color bitmap? */ if (k2settings->dst_color && fabs(contrast-1.0)>1e-4) bmp_contrast_adjust(src,src,contrast); bmp_free(dst); }
/* ** Calculate max vert line length. Line is terminated by nw consecutive white pixels ** on either side. ** ** v2.10--handle cbmp 8-bit correctly. */ static int vert_line_erase(WILLUSBITMAP *bmp,WILLUSBITMAP *cbmp,WILLUSBITMAP *tmp, int row0,int col0,double tanth,double minheight_in, /* double minwidth_in,*/ double maxwidth_in,int white_thresh, double dpi,int erase_vertical_lines) { int lw,cc,maxdev,nw,dir,i,n,cbpp; int *c1,*c2,*w; static char *funcname="vert_line_erase"; #if (WILLUSDEBUGX & 0x8000) printf("@vert_line_erase(row0=%d,col0=%d,tanth=%g,minheight_in=%g\n" " maxwidth_in=%g,white_thresh=%d,dpi=%g,evl=%d\n", row0,col0,tanth,minheight_in, maxwidth_in,white_thresh,dpi,erase_vertical_lines); printf(" bmp = %d x %d x %d\n",bmp->width,bmp->height,bmp->bpp); if (cbmp!=NULL) printf(" cbmp = %d x %d x %d\n",cbmp->width,cbmp->height,cbmp->bpp); if (tmp!=NULL) printf(" tmp = %d x %d x %d\n",tmp->width,tmp->height,tmp->bpp); #endif cbpp = (cbmp!=NULL && cbmp->bpp==24) ? 3 : 1; willus_dmem_alloc_warn(26,(void **)&c1,sizeof(int)*3*bmp->height,funcname,10); c2=&c1[bmp->height]; w=&c2[bmp->height]; /* maxdev = (int)((double)bmp->height / minheight_in +.5); if (maxdev < 3) maxdev=3; */ nw = (int)(dpi/100.+.5); if (nw<2) nw=2; maxdev=nw; for (i=0;i<bmp->height;i++) c1[i]=c2[i]=-1; n=0; for (dir=-1;dir<=1;dir+=2) { int del,brc; #if (WILLUSDEBUGX & 0x8000) printf("dir=%d\n",dir); #endif brc = 0; for (del=(dir==-1)?0:1;1;del++) { int r,c; unsigned char *p; #if (WILLUSDEBUGX & 0x8000) printf("del=%d\n",del); #endif r=row0+dir*del; if (r<0 || r>bmp->height-1) break; c=col0+(r-row0)*tanth; if (c<0 || c>bmp->width-1) break; p=bmp_rowptr_from_top(bmp,r); for (i=c;i<=c+maxdev && i<bmp->width;i++) if (p[i]<white_thresh) break; if (i>c+maxdev || i>=bmp->width) { for (i=c-1;i>=c-maxdev && i>=0;i--) if (p[i]<white_thresh) break; if (i<c-maxdev || i<0) { brc++; if (brc>=nw) break; continue; } } brc=0; for (c=i,cc=0;i<bmp->width;i++) if (p[i]<white_thresh) cc=0; else { cc++; if (cc>=nw) break; } c2[r]=i-cc; if (c2[r]>bmp->width-1) c2[r]=bmp->width-1; for (cc=0,i=c;i>=0;i--) if (p[i]<white_thresh) cc=0; else { cc++; if (cc>=nw) break; } c1[r]=i+cc; if (c1[r]<0) c1[r]=0; w[n++]=c2[r]-c1[r]+1; c1[r]-=cc; if (c1[r]<0) c1[r]=0; c2[r]+=cc; if (c2[r]>bmp->width-1) c2[r]=bmp->width-1; } } #if (WILLUSDEBUGX & 0x8000) printf("n=%d\n",n); #endif if (n>1) sorti(w,n); /* printf("n=%d, w[%d]=%d, w[%d]=%d (mw=%g)\n",n,n/4,w[n/4],3*n/4,w[3*n/4],maxwidth_in*dpi); */ if (n < 10 || n < minheight_in*dpi || w[n/4] < 1 /* (int)(minwidth_in*dpi + .5) */ || w[3*n/4] > (int)(maxwidth_in*dpi) || (erase_vertical_lines==1 && w[n-1] > maxwidth_in*dpi)) { #if (WILLUSDEBUGX & 0x8000) printf("Erasing area in temp bitmap.\n"); #endif /* Erase area in temp bitmap */ for (i=0;i<bmp->height;i++) { unsigned char *p; int cmax; if (c1[i]<0 || c2[i]<0) continue; cmax=(c2[i]-c1[i])+1; p=bmp_rowptr_from_top(tmp,i)+c1[i]; for (;cmax>0;cmax--,p++) (*p)=255; } } else { #if (WILLUSDEBUGX & 0x8000) printf("Erasing line width in source\n"); #endif /* Erase line width in source bitmap */ lw=w[3*n/4]+nw*2; #if (WILLUSDEBUGX & 0x8000) printf("1. lw=%d\n",lw); #endif if (lw > maxwidth_in*dpi/2) lw=maxwidth_in*dpi/2; #if (WILLUSDEBUGX & 0x8000) printf("2. lw=%d\n",lw); #endif for (i=0;i<bmp->height;i++) { unsigned char *p; int c0,cmin,cmax,count,white; #if (WILLUSDEBUGX & 0x8000) printf("i=%d\n",i); #endif if (c1[i]<0 || c2[i]<0) continue; c0=col0+(i-row0)*tanth; cmin=c0-lw-1; if (cmin<c1[i]) cmin=c1[i]; cmax=c0+lw+1; if (cmax>c2[i]) cmax=c2[i]; #if (WILLUSDEBUGX & 0x8000) printf("A\n"); #endif p=bmp_rowptr_from_top(bmp,i); c0 = (p[cmin] > p[cmax]) ? cmin : cmax; white=p[c0]; #if (WILLUSDEBUGX & 0x8000) printf("B\n"); #endif if (white <= white_thresh) white = white_thresh+1; if (white>255) white=255; #if (WILLUSDEBUGX & 0x8000) printf("C\n"); #endif count=(cmax-cmin)+1; p=&p[cmin]; #if (WILLUSDEBUGX & 0x8000) printf("D\n"); #endif for (;count>0;count--,p++) (*p)=white; #if (WILLUSDEBUGX & 0x8000) printf("E\n"); #endif if (cbmp!=NULL) { unsigned char *p0; p=bmp_rowptr_from_top(cbmp,i); p0=p+c0*cbpp; p=p+cmin*cbpp; count=(cmax-cmin)+1; #if (WILLUSDEBUGX & 0x8000) printf("F width=%d, ht=%d, bpp=%d, c0=%d, cmin=%d, i=%d, count=%d\n",cbmp->width,cbmp->height,cbmp->bpp,c0,cmin,i,count); #endif if (cbpp==3) for (;count>0;count--,p+=3) { p[0]=p0[0]; p[1]=p0[1]; p[2]=p0[2]; } else memset(p,p0[0],count); #if (WILLUSDEBUGX & 0x8000) printf("G\n"); #endif } } #if (WILLUSDEBUGX & 0x8000) printf(" done.\n"); #endif } willus_dmem_free(26,(double **)&c1,funcname); return(1); }
/* ** bmp must be grayscale! (cbmp might be color, might be grayscale, can be null) ** Handles cbmp either 8-bit or 24-bit in v2.10. */ void bmp_detect_vertical_lines(WILLUSBITMAP *bmp,WILLUSBITMAP *cbmp, double dpi,/* double minwidth_in, */ double maxwidth_in,double minheight_in,double anglemax_deg, int white_thresh,int erase_vertical_lines,int debug,int verbose) { int tc,iangle,irow,icol; int rowstep,na,angle_sign,ccthresh; int halfwidth,bytewidth; int bs1,nrsteps; double anglestep; WILLUSBITMAP *tmp,_tmp; unsigned char *p0; unsigned char *t0; if (debug) k2printf("At bmp_detect_vertical_lines...\n"); if (!bmp_is_grayscale(bmp)) { k2printf("Internal error. bmp_detect_vertical_lines passed a non-grayscale bitmap.\n"); exit(10); } tmp=&_tmp; bmp_init(tmp); bmp_copy(tmp,bmp); p0=bmp_rowptr_from_top(bmp,0); t0=bmp_rowptr_from_top(tmp,0); bytewidth=bmp_bytewidth(bmp); /* pixmin = (int)(minwidth_in*dpi+.5); if (pixmin<1) pixmin=1; halfwidth=pixmin/4; if (halfwidth<1) halfwidth=1; */ halfwidth=1; anglestep=atan2((double)halfwidth/dpi,minheight_in); na=(int)((anglemax_deg*PI/180.)/anglestep+.5); if (na<1) na=1; rowstep=(int)(dpi/40.+.5); if (rowstep<2) rowstep=2; nrsteps=bmp->height/rowstep; bs1=bytewidth*rowstep; ccthresh=(int)(minheight_in*dpi/rowstep+.5); if (ccthresh<2) ccthresh=2; if (debug && verbose) k2printf(" na = %d, rowstep = %d, ccthresh = %d, white_thresh = %d, nrsteps=%d\n",na,rowstep,ccthresh,white_thresh,nrsteps); /* bmp_write(bmp,"out.png",stdout,97); wfile_written_info("out.png",stdout); */ for (tc=0;tc<100;tc++) { int ccmax,ic0max,ir0max; double tanthmax; ccmax=-1; ic0max=ir0max=0; tanthmax=0.; for (iangle=0;iangle<=na;iangle++) { for (angle_sign=1;angle_sign>=-1;angle_sign-=2) { double th,tanth,tanthx; int ic1,ic2; if (iangle==0 && angle_sign==-1) continue; th=(PI/180.)*iangle*angle_sign*fabs(anglemax_deg)/na; tanth=tan(th); tanthx=tanth*rowstep; if (angle_sign==1) { ic1=-(int)(bmp->height*tanth+1.); ic2=bmp->width-1; } else { ic1=(int)(-bmp->height*tanth+1.); ic2=bmp->width-1+(int)(-bmp->height*tanth+1.); } // k2printf("iangle=%2d, angle_sign=%2d, ic1=%4d, ic2=%4d\n",iangle,angle_sign,ic1,ic2); for (icol=ic1;icol<=ic2;icol++) { unsigned char *p,*t; int cc,ic0,ir0; p=p0; t=t0; if (icol<0 || icol>bmp->width-1) for (irow=0;irow<nrsteps;irow++,p+=bs1,t+=bs1) { int ic; ic=icol+irow*tanthx; if (ic>=0 && ic<bmp->width) break; } else irow=0; for (ir0=ic0=cc=0;irow<nrsteps;irow++,p+=bs1,t+=bs1) { int ic; ic=icol+irow*tanthx; if (ic<0 || ic>=bmp->width) break; if ((p[ic]<white_thresh || p[ic+bytewidth]<white_thresh) && (t[ic]<white_thresh || t[ic+bytewidth]<white_thresh)) { if (cc==0) { ic0=ic; ir0=irow*rowstep; } cc++; if (cc>ccmax) { ccmax=cc; tanthmax=tanth; ic0max=ic0; ir0max=ir0; } } else cc=0; } } } } if (ccmax<ccthresh) break; if (debug) k2printf(" Vert line detected: ccmax=%d (pix=%d), tanthmax=%g, ic0max=%d, ir0max=%d\n",ccmax,ccmax*rowstep,tanthmax,ic0max,ir0max); if (!vert_line_erase(bmp,cbmp,tmp,ir0max,ic0max,tanthmax,minheight_in, /*minwidth_in,*/ maxwidth_in,white_thresh,dpi,erase_vertical_lines)) break; } /* bmp_write(tmp,"outt.png",stdout,95); wfile_written_info("outt.png",stdout); bmp_write(bmp,"out2.png",stdout,95); wfile_written_info("out2.png",stdout); exit(10); */ /* v2.20--fix memory leak here */ bmp_free(tmp); }
/* ** src is only allocated if dst_color != 0 */ void bmp_clear_outside_crop_border(MASTERINFO *masterinfo,WILLUSBITMAP *src, WILLUSBITMAP *srcgrey,K2PDFOPT_SETTINGS *k2settings) { int i,n; BMPREGION *region,_region; region=&_region; bmpregion_init(region); region->bmp = k2settings->dst_color ? src : srcgrey; region->bmp8 = srcgrey; region->dpi = k2settings->src_dpi; bmpregion_trim_to_crop_margins(region,masterinfo,k2settings); n=region->c1; for (i=0;i<srcgrey->height;i++) { unsigned char *p; if (k2settings->dst_color) { p=bmp_rowptr_from_top(src,i); memset(p,255,n*3); } p=bmp_rowptr_from_top(srcgrey,i); memset(p,255,n); } n=srcgrey->width-1-region->c2; for (i=0;i<srcgrey->height;i++) { unsigned char *p; if (k2settings->dst_color) { p=bmp_rowptr_from_top(src,i)+3*(src->width-n); memset(p,255,n*3); } p=bmp_rowptr_from_top(srcgrey,i)+srcgrey->width-n; memset(p,255,n); } n=region->r1; for (i=0;i<n;i++) { unsigned char *p; if (k2settings->dst_color) { p=bmp_rowptr_from_top(src,i); memset(p,255,src->width*3); } p=bmp_rowptr_from_top(srcgrey,i); memset(p,255,srcgrey->width); } n=srcgrey->height-1-region->r2; for (i=srcgrey->height-n;i<srcgrey->height;i++) { unsigned char *p; if (k2settings->dst_color) { p=bmp_rowptr_from_top(src,i); memset(p,255,src->width*3); } p=bmp_rowptr_from_top(srcgrey,i); memset(p,255,srcgrey->width); } /* Free region--v2.15 memory leak fix, 2-1-14 */ bmpregion_free(region); }
/* ** bmp8 must be grayscale ** (x1,y1) and (x2,y2) from top left of bitmap */ void ocrtess_single_word_from_bmp8(char *text,int maxlen,WILLUSBITMAP *bmp8, int x1,int y1,int x2,int y2, int ocr_type,int allow_spaces, int std_proc,FILE *out) { PIX *pix; int i,w,h,dw,dh,bw,status; unsigned char *src,*dst; if (x1>x2) { w = x1; x1 = x2; x2 = w; } w = x2-x1+1; bw = w/40; if (bw < 6) bw = 6; dw = w + bw * 2; dw = (dw + 3) & (~3); if (y1>y2) { h = y1; y1 = y2; y2 = h; } h = y2 - y1 + 1; dh = h + bw * 2; // __android_log_print(ANDROID_LOG_INFO, "K2PDFOPT - OCR>> ", "BEFORE CREATE"); pix = pixCreate(dw, dh, 8); // __android_log_print(ANDROID_LOG_INFO, "K2PDFOPT - OCR>> ", "AFTER CREATE"); src = bmp_rowptr_from_top(bmp8, y1) + x1; // __android_log_print(ANDROID_LOG_INFO, "K2PDFOPT - OCR>> ", "BEFORE FROM TOP"); dst = (unsigned char *)pixGetData(pix); // __android_log_print(ANDROID_LOG_INFO, "K2PDFOPT - OCR>> ", "AFTER GET DATA"); memset(dst, 255, dw*dh); // __android_log_print(ANDROID_LOG_INFO, "K2PDFOPT - OCR>> ", "AFTER MEMSET"); dst = (unsigned char *)pixGetData(pix); // __android_log_print(ANDROID_LOG_INFO, "K2PDFOPT - OCR>> ", "AFTER ANOTHER GET"); dst += bw + dw * bw; // __android_log_print(ANDROID_LOG_INFO, "K2PDFOPT - OCR>> CONDITION", "dw: %d, src_inc: %d", dw, bmp8->width); for (i=y1; i<=y2; i++, dst+=dw, src+=bmp8->width) memcpy(dst, src, w); // __android_log_print(ANDROID_LOG_INFO, "K2PDFOPT - OCR>> ", "AFTER MEMCOPY"); endian_flip((char *)pixGetData(pix), pixGetWpl(pix) * pixGetHeight(pix)); // __android_log_print(ANDROID_LOG_INFO, "K2PDFOPT - OCR>> ", "BEFORE OCR"); status = tess_capi_get_ocr(pix, text, maxlen, out); // __android_log_print(ANDROID_LOG_INFO, "K2PDFOPT - OCR>> ", "AFTER OCR"); pixDestroy(&pix); if (status<0) text[0]='\0'; // clean_line(text); if (std_proc) ocr_text_proc(text,allow_spaces); }