Revize 9508f0fa
Přidáno uživatelem Ondřej Váně před téměř 5 roky(ů)
fe/fulltextsearch/src/Utils.ts | ||
---|---|---|
1 |
import {Position} from './app/model/crates/Position'; |
|
2 |
|
|
1 | 3 |
export default class Utils { |
2 | 4 |
|
3 | 5 |
static removeFileSuffix(file: File): string { |
4 | 6 |
return file.name.substring(0, file.name.indexOf('.')); |
5 | 7 |
} |
8 |
|
|
9 |
static isIterable(obj): boolean { |
|
10 |
// checks for null and undefined |
|
11 |
if (obj == null) { |
|
12 |
return false; |
|
13 |
} |
|
14 |
return typeof obj[Symbol.iterator] === 'function'; |
|
15 |
} |
|
16 |
|
|
17 |
static getAbsolutePositionOfElement(element: HTMLElement): Position { |
|
18 |
let top = 0, left = 0; |
|
19 |
|
|
20 |
do { |
|
21 |
top += element.offsetTop || 0; |
|
22 |
left += element.offsetLeft || 0; |
|
23 |
element = <HTMLElement> element.offsetParent; |
|
24 |
} while (element); |
|
25 |
|
|
26 |
return new Position(top, left); |
|
27 |
} |
|
6 | 28 |
} |
fe/fulltextsearch/src/app/components/pages/search/search-paginator/search-paginator.component.html | ||
---|---|---|
8 | 8 |
{{row.documentName}} |
9 | 9 |
</div> |
10 | 10 |
<div class="row image-div"> |
11 |
<img class="image" src="data:image/jpg;base64,{{row.imageCut}}" /> |
|
11 |
<img id="{{row.documentName + 'Img'}}" |
|
12 |
class="image" src="data:image/jpg;base64,{{row.imageCut}}" |
|
13 |
(load)="draw(row,row.documentName + 'Img' , row.documentName + 'Canvas' )"/> |
|
14 |
<canvas id="{{row.documentName + 'Canvas'}}" style="position: absolute;" title="TEST"> |
|
15 |
Your browser does not support the HTML5 canvas tag. |
|
16 |
</canvas> |
|
12 | 17 |
</div> |
13 | 18 |
</div> |
14 | 19 |
</td> |
fe/fulltextsearch/src/app/components/pages/search/search-paginator/search-paginator.component.ts | ||
---|---|---|
3 | 3 |
import { MatTableDataSource } from '@angular/material/table'; |
4 | 4 |
import { TextRegion } from '../../../../model/parts/TextRegion'; |
5 | 5 |
import { SearchResponse } from '../../../../model/SearchResponse'; |
6 |
import Utils from '../../../../../Utils'; |
|
7 |
import {DrawerService} from '../../../../services/drawer/drawer.service'; |
|
8 |
import {LoggerService} from '../../../../services/logger/logger.service'; |
|
6 | 9 |
|
7 | 10 |
@Component({ |
8 | 11 |
selector: 'app-search-paginator', |
... | ... | |
17 | 20 |
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ |
18 | 21 |
displayedColumns = ['image']; |
19 | 22 |
|
23 |
constructor(private LOGGER: LoggerService, private drawer: DrawerService) {} |
|
24 |
|
|
20 | 25 |
ngOnChanges(changes: SimpleChanges): void { |
21 | 26 |
this.tableDataSource = new MatTableDataSource<TextRegion>(this.inputData.textRegions); |
22 | 27 |
this.tableDataSource.paginator = this.paginator; |
23 | 28 |
} |
24 | 29 |
|
30 |
draw(result: TextRegion, imageId: string, canvasId: string) { |
|
31 |
this.LOGGER.debug('Drawing method'); |
|
32 |
this.drawer.drawResult(result, imageId, canvasId); |
|
33 |
} |
|
25 | 34 |
} |
fe/fulltextsearch/src/app/model/crates/Position.ts | ||
---|---|---|
1 |
export class Position { |
|
2 |
public top: number; |
|
3 |
public left: number; |
|
4 |
|
|
5 |
constructor(top: number, left: number) { |
|
6 |
this.top = top; |
|
7 |
this.left = left; |
|
8 |
} |
|
9 |
} |
fe/fulltextsearch/src/app/model/parts/DocumentSize.ts | ||
---|---|---|
1 |
export class DocumentSize { |
|
2 |
public height: number; |
|
3 |
public width: number; |
|
4 |
|
|
5 |
constructor(height: number, width: number) { |
|
6 |
this.height = height; |
|
7 |
this.width = width; |
|
8 |
} |
|
9 |
} |
fe/fulltextsearch/src/app/model/parts/TextRegion.ts | ||
---|---|---|
1 | 1 |
import { Coords } from './Coords'; |
2 | 2 |
import { TextLine } from './TextLine'; |
3 |
import {DocumentSize} from './DocumentSize'; |
|
3 | 4 |
|
4 | 5 |
export class TextRegion { |
5 | 6 |
public imageCut: string; |
... | ... | |
7 | 8 |
public regionText: string; |
8 | 9 |
public textLines: TextLine[]; |
9 | 10 |
public documentName: string; |
11 |
public documentSize: DocumentSize; |
|
10 | 12 |
} |
fe/fulltextsearch/src/app/services/drawer/drawer.service.spec.ts | ||
---|---|---|
1 |
import { TestBed } from '@angular/core/testing'; |
|
2 |
|
|
3 |
import { DrawerService } from './drawer.service'; |
|
4 |
|
|
5 |
describe('DrawerService', () => { |
|
6 |
let service: DrawerService; |
|
7 |
|
|
8 |
beforeEach(() => { |
|
9 |
TestBed.configureTestingModule({}); |
|
10 |
service = TestBed.inject(DrawerService); |
|
11 |
}); |
|
12 |
|
|
13 |
it('should be created', () => { |
|
14 |
expect(service).toBeTruthy(); |
|
15 |
}); |
|
16 |
}); |
fe/fulltextsearch/src/app/services/drawer/drawer.service.ts | ||
---|---|---|
1 |
import { Injectable } from '@angular/core'; |
|
2 |
import {LoggerService} from '../logger/logger.service'; |
|
3 |
import {TextRegion} from '../../model/parts/TextRegion'; |
|
4 |
import {Point} from '../../model/parts/Point'; |
|
5 |
import Utils from '../../../Utils'; |
|
6 |
|
|
7 |
@Injectable({ |
|
8 |
providedIn: 'root' |
|
9 |
}) |
|
10 |
export class DrawerService { |
|
11 |
|
|
12 |
constructor(private LOGGER: LoggerService) { } |
|
13 |
|
|
14 |
public drawResult(textRegion: TextRegion, imageId: string, canvasId: string) { |
|
15 |
const canvasContext = this.initCanvas(imageId, canvasId); |
|
16 |
|
|
17 |
if (textRegion !== null) { |
|
18 |
if (Utils.isIterable(textRegion.textLines) && textRegion.textLines.length !== 0) { |
|
19 |
for (const textLine of textRegion.textLines) { |
|
20 |
if (Utils.isIterable(textLine.textWords) && textLine.textWords.length !== 0) { |
|
21 |
for (const textWord of textLine.textWords) { |
|
22 |
if (textWord !== null) { |
|
23 |
// print words |
|
24 |
this.draw(textWord.wordCoords.points, canvasContext); |
|
25 |
this.LOGGER.info('printing words'); |
|
26 |
} |
|
27 |
} |
|
28 |
return; |
|
29 |
} else { |
|
30 |
// print lines |
|
31 |
this.draw(textLine.lineCoords.points, canvasContext); |
|
32 |
this.LOGGER.info('Print lines'); |
|
33 |
} |
|
34 |
} |
|
35 |
return; |
|
36 |
} else { |
|
37 |
// all region |
|
38 |
this.draw(textRegion.regionCoords.points, canvasContext); |
|
39 |
this.LOGGER.info('Print region'); |
|
40 |
} |
|
41 |
} else { |
|
42 |
// all document |
|
43 |
// TODO : obarvit celý výřez |
|
44 |
this.LOGGER.warn('Print all document'); |
|
45 |
} |
|
46 |
} |
|
47 |
|
|
48 |
private initCanvas(imageId: string, canvasId: string) { |
|
49 |
const img = document.getElementById(imageId); |
|
50 |
const canvasElement = document.getElementById(canvasId); |
|
51 |
const canvas = <HTMLCanvasElement> document.getElementById(canvasId); |
|
52 |
|
|
53 |
const absolutePosition = Utils.getAbsolutePositionOfElement(document.getElementById(imageId)); |
|
54 |
|
|
55 |
canvasElement.style.display = 'block'; |
|
56 |
canvasElement.style.left = absolutePosition.left + 'px'; |
|
57 |
canvasElement.style.top = absolutePosition.top + 'px'; |
|
58 |
|
|
59 |
const ctx = canvas.getContext('2d'); |
|
60 |
ctx.canvas.width = img.offsetWidth; |
|
61 |
ctx.canvas.height = img.offsetHeight; |
|
62 |
|
|
63 |
return ctx; |
|
64 |
} |
|
65 |
|
|
66 |
private draw(points: Point[], context: CanvasRenderingContext2D) { |
|
67 |
let firstPoint = true; |
|
68 |
context.beginPath(); |
|
69 |
|
|
70 |
for (const point of points) { |
|
71 |
if (firstPoint) { |
|
72 |
context.moveTo(point.x / 1.676, point.y / 1.676); |
|
73 |
firstPoint = false; |
|
74 |
} else { |
|
75 |
context.lineTo(point.x / 1.676, point.y / 1.676); |
|
76 |
} |
|
77 |
} |
|
78 |
context.closePath(); |
|
79 |
|
|
80 |
context.lineWidth = 2; |
|
81 |
context.strokeStyle = '#ff253b'; |
|
82 |
context.fillStyle = 'hsla(14, 100%, 53%, 0.3)'; |
|
83 |
context.fill(); |
|
84 |
context.stroke(); |
|
85 |
} |
|
86 |
} |
Také k dispozici: Unified diff
Re #7820: Vykreslení rámečku do výřezu dokumentu
- implementována service pro vykreslení rámečku do obrázku
- vykreslování pomocí html5 tagu canvas
- nutno dopočítat posun oproti původnímu obrázku (velikost bude posílána z BE)