ailon / markerjs2

Add image annotation to your web apps.
https://markerjs.com
Other
142 stars 39 forks source link

using markerArea.renderState(oldState) my image lose quality #174

Open thomasbricchi opened 11 months ago

thomasbricchi commented 11 months ago

hello everybody , i'm using "markerjs2": "^2.31.4", with angular 15

and my code is this

ngAfterViewInit(): void {

    this.markerArea = new markerjs2.MarkerArea(document.getElementById('imageId') as HTMLImageElement);
    this.markerArea.addEventListener('render', (event) => {
        // @ts-ignore
        (document.getElementById('imageId') as HTMLImageElement).src = event.dataUrl;
        this.maState = event.state;
       // old state inside the localStorage just for testing
        window.localStorage.setItem('imag', JSON.stringify(event.state))
    })

    const reader = new FileReader();

    reader.onload = (e) => {
        // @ts-ignore
        (document.getElementById('imageId') as HTMLImageElement).src = e.target.result;
        let state = JSON.parse(window.localStorage.getItem('imag') as string);
        if (state) {
            this.markerArea.renderState(state);
        }
    };

    this.fi.downloadFile('0b74620f-152f-4c83-95c1-75508099ab62')
        .subscribe(value => {
            reader.readAsDataURL(value);
        })

}

and html is

<img id="ciccio" [height]="250" [width]="250" (click)="open()">

but when i restore the old state it seems that my picture lose quality, but when i open and edit it without renderState the quality stays good

do you know why? and how can i fix it?

thanks

ailon commented 11 months ago

Are you setting rendering options according to your needs? Doesn't look like you do based on the provided sample.

Hope this helps.

thomasbricchi commented 11 months ago

with this.imgElement.src = e.target.result; this.markerArea.renderAtNaturalSize = true; this.markerArea.renderImageQuality = 1; this.markerArea.renderState(this.currentState);

        it works with the initial state, but when i open it like here 

           this.markerArea.availableMarkerTypes = MARKERS
    this.markerArea.settings.displayMode = 'popup';
    this.markerArea.show();
    if (this.currentState) {
        this.markerArea.restoreState(this.currentState);
    }

    it doesn't work as expected, i cannot move the old markers 
ailon commented 11 months ago

Not sure about the sequence of events here, but you should try to open the same instance after calling renderState()

Try creating a new MarkerArea() if you want to open the state after rendering it.

thomasbricchi commented 11 months ago

everything is here.

open() { this.markerArea.availableMarkerTypes = MARKERS this.markerArea.settings.displayMode = 'popup'; this.markerArea.show(); if (this.currentState) { this.markerArea.restoreState(this.currentState); } }

ngAfterViewInit(): void {
    this.readImage();
    this.markerArea = new markerjs2.MarkerArea(this.imgElement);
    this.markerArea.targetRoot = this.divElement;
    this.markerArea.addEventListener('render', (event) => {
        // @ts-ignore
        // this.markerView.close();
        console.log('render')
        this.imgElement.src = event.dataUrl;
        this.currentState = event.state;
        this.newState.emit(this.currentState)
    })

}

private readImage() {
    const reader = new FileReader();
    reader.onload = (e) => {
        // @ts-ignore
        this.imgElement.src = e.target.result;
        this.markerArea.renderAtNaturalSize = true;
        this.markerArea.renderImageQuality = 1;
        this.markerArea.renderState(this.currentState);

        // this.markerView = new mjslive.MarkerView(this.imgElement);
        // this.markerView.targetRoot = this.divElement;
        // if (this.currentState) {
        //     this.markerView.show(this.currentState);
        // }
        //
        // this.markerView.addEventListener('select', () => console.log('click'))
    };
    reader.readAsDataURL(this.image);
}

but it isn't nice to recreate a new markerArea to achive my goal
ailon commented 11 months ago

renderState() is method meant to be used when you don't want to open the editor. If you open the editor anyway, maybe you can just use the result of the render event to get the rendered image. Doing both is an uncommon scenario and you may have to live with "not nice" if you really need to do both ;)

thomasbricchi commented 11 months ago

ok so i misunderstood how to use it.

my use case is, show the old state when i enter in the page, but i can still edit it

ailon commented 11 months ago

Yeah, so if you don't store the rendered image anywhere, you may use renderState() to generate the preview but it's conceptually a different MarkerArea to the one used for editing so you may just want to use a different instance for this anyway. Think of that instance as just a discardable single use renderer.

thomasbricchi commented 11 months ago

Just wanted to drop a quick thank you for all your help with my issue. Your effort didn't go unnoticed, and I really appreciate it

SadmanYasar commented 2 months ago

ok so i misunderstood how to use it.

my use case is, show the old state when i enter in the page, but i can still edit it

Hi. I am facing this issue in a React app. At first I was using useRef to reuse the markerArea but the old state was shown but not editable. Then switched to creating a new instance on click but it still has the same issue. I realized that it shows a saved image after looking at the network tab in browser console. May I know how you were able to achieve this? TIA.

SadmanYasar commented 2 months ago

I realized the main issue. The image src is being set to event.dataUrl. So the original image is not kept and replaced with the annotated version. I removed this part and it works correctly but had to use two image tags using the same ref to make it work.