Source: papertools/raster.mjs

/**
 * OpenSeadragon paperjs overlay plugin based on paper.js
 * @version 0.4.13
 * 
 * Includes additional open source libraries which are subject to copyright notices
 * as indicated accompanying those segments of code.
 * 
 * Original code:
 * Copyright (c) 2022-2024, Thomas Pearce
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * 
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * 
 * * Neither the name of osd-paperjs-annotation nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

import {AnnotationUITool, AnnotationUIToolbarBase} from './annotationUITool.mjs';
import { paper } from '../paperjs.mjs';
import { makeFaIcon } from '../utils/faIcon.mjs';
/**
 * The RasterTool class extends the AnnotationUITool and provides functionality for rasterizing annotations.
 * @extends AnnotationUITool
 * @class
 * @memberof OSDPaperjsAnnotation
 */
class RasterTool extends AnnotationUITool{
    /**
   * Creates a new RasterTool instance.
   * The constructor initializes the RasterTool by calling the base class (AnnotationUITool) constructor and sets up the necessary toolbar control (RasterToolbar).
   * @memberof OSDPaperjsAnnotation.RasterTool
   * @constructor
   * @param {paper.PaperScope} paperScope - The Paper.js scope for the tool.
   */
    constructor(paperScope){
        super(paperScope);

        this.setToolbarControl(new RasterToolbar(this));
    }
    /**
     * Rasterizes the current annotation item. It converts the vector annotation to a pixel-based raster.
     * After rasterization, it replaces the original annotation with the rasterized version.
     * The rasterized version includes both the raster image and the original annotation's geoJSON data.
     * @property {function} onLoad The function performs rasterization and replacement of the vector annotation with the rasterized version.
     * @property {Object} geoJSON geoJSON data representing the rasterized annotation item.
     * @property {string} geoJSON.type - The type of the geoJSON object (e.g., 'Feature').
     * @property {Object} geoJSON.geometry - The geometry information of the geoJSON object.
     * @property {string} geoJSON.geometry.type - The type of the geometry (e.g., 'GeometryCollection').
     * @property {Object} geoJSON.geometry.properties - Additional properties of the geometry.
     * @property {string} geoJSON.geometry.properties.subtype - The subtype of the geometry (e.g., 'Raster').
     * @property {Object} geoJSON.geometry.properties.raster - The raster data of the geometry.
     * @property {paper.Raster} geoJSON.geometry.properties.raster.data - The pixel-based raster data.
     * @property {Object} geoJSON.geometries - The list of geometries in the geometry collection.
     * @property {Object} geoJSON.properties - The properties of the geoJSON object.
     *
     */
    rasterize(){
        let self = this;
        let item = this.item;
        if(item){
            let raster = this.project.overlay.getViewportRaster();
            item.layer.addChild(raster);
        
        
            raster.onLoad = function(){
                //get the subregion in pixel coordinates of the large raster by inverse transforming the bounding rect of the item
                let offset = new paper.Point(this.width/2,this.height/2);
                
                let newBounds = new paper.Rectangle(
                    offset.add(this.matrix.inverseTransform(this.layer.matrix.transform(item.bounds.topLeft))).floor(), 
                    offset.add(this.matrix.inverseTransform(this.layer.matrix.transform(item.bounds.bottomRight))).ceil()
                );
                
                let subraster = this.getSubRaster(newBounds);
                
                subraster.transform(this.layer.matrix.inverted());
                
                subraster.selectedColor = null;
                let geoJSON = {
                    type:'Feature',
                    geometry:{
                        type:'GeometryCollection',
                        properties:{
                            subtype:'Raster',
                            raster: {
                                data:subraster,
                            },
                        },
                        geometries:[
                            item,
                        ]
                    },
                    properties:{}
                }

                item.replaceWith(paper.Item.fromGeoJSON(geoJSON));
                self.refreshItems();

                this.remove();
            }
        }

    }
    
}
export {RasterTool};
/**
 * The RasterToolbar class extends the AnnotationUIToolbarBase and provides the toolbar functionality for the RasterTool.
 * @extends AnnotationUIToolbarBase
 * @class 
 * @memberof OSDPaperjsAnnotation.RasterTool
 */
class RasterToolbar extends AnnotationUIToolbarBase{
   /**
   * The constructor sets up the toolbar UI with a button to trigger rasterization.
   * It also adds a warning message regarding the irreversible nature of rasterization.   * @constructor
   * @param {RasterTool} tool - The RasterTool instance.
   */
    constructor(tool){
        super(tool);
       
        const i = makeFaIcon('fa-image');
        this.button.configure(i,'raster Tool');

        const d = document.createElement('div');
        this.dropdown.appendChild(d);
        const button = document.createElement('button');
        button.innerHTML = 'Convert to raster';
        d.appendChild(button);
        const span = document.createElement('span');
        span.innerHTML = 'Warning: this cannot be undone!';
        d.appendChild(span);

        button.addEventListener('click',()=>tool.rasterize())
    }
    /**
   * Checks if the RasterTool is enabled for the given mode.
   * @function
   * @param {string} mode - The mode of the annotation, such as 'MultiPolygon', 'Point:Rectangle', or 'Point:Ellipse'.
   * @returns {boolean} - Returns true if the RasterTool is enabled for the given mode, false otherwise.
   */
    isEnabledForMode(mode){
        return ['Polygon','MultiPolygon','Point:Rectangle','Point:Ellipse'].includes(mode);
    }
}