All files / roosterjs-content-model-plugins/lib/imageEdit/utils generateDataURL.ts

93.75% Statements 30/32
67.86% Branches 19/28
100% Functions 1/1
93.75% Lines 30/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 771x                           1x 2x 2x                           18x 2x 2x 2x 2x 2x 2x 2x 2x 2x   2x 2x     2x 2x 4x 2x 2x   2x   2x 2x 2x 2x 2x 2x 2x                       2x          
import { getGeneratedImageSize } from './generateImageSize';
import type { ImageMetadataFormat } from 'roosterjs-content-model-types';
 
/**
 * @internal
 * Generate new dataURL from an image and edit info
 * @param image The image to generate data URL from. It is supposed to have original src loaded
 * @param editInfo Edit info of the image
 * @returns A BASE64 encoded string with image prefix that represents the content of the generated image.
 * If there are rotate/crop/resize info in the edit info, the generated image will also reflect the result.
 * It is possible to throw exception since the original image may not be able to read its content from
 * the code, so better check canRegenerateImage() of the image first.
 * @throws Exception when fail to generate dataURL from canvas
 */
export function generateDataURL(image: HTMLImageElement, editInfo: ImageMetadataFormat): string {
    const generatedImageSize = getGeneratedImageSize(editInfo);
    Iif (!generatedImageSize) {
        return '';
    }
 
    const {
        angleRad,
        widthPx,
        heightPx,
        bottomPercent,
        leftPercent,
        rightPercent,
        topPercent,
        naturalWidth,
        naturalHeight,
    } = editInfo;
    const angle = angleRad || 0;
    const left = leftPercent || 0;
    const right = rightPercent || 0;
    const top = topPercent || 0;
    const bottom = bottomPercent || 0;
    const nHeight = naturalHeight || image.naturalHeight;
    const nWidth = naturalWidth || image.naturalHeight;
    const width = widthPx || image.clientWidth;
    const height = heightPx || image.clientHeight;
 
    const imageWidth = nWidth * (1 - left - right);
    const imageHeight = nHeight * (1 - top - bottom);
 
    // Adjust the canvas size and scaling for high display resolution
    const devicePixelRatio = window.devicePixelRatio || 1;
    const canvas = document.createElement('canvas');
    const { targetWidth, targetHeight } = generatedImageSize;
    canvas.width = targetWidth * devicePixelRatio;
    canvas.height = targetHeight * devicePixelRatio;
 
    const context = canvas.getContext('2d');
 
    try {
        Eif (context) {
            context.scale(devicePixelRatio, devicePixelRatio);
            context.translate(targetWidth / 2, targetHeight / 2);
            context.rotate(angle);
            context.scale(editInfo.flippedHorizontal ? -1 : 1, editInfo.flippedVertical ? -1 : 1);
            context.drawImage(
                image,
                nWidth * left,
                nHeight * top,
                imageWidth,
                imageHeight,
                -width / 2,
                -height / 2,
                width,
                height
            );
        }
        return canvas.toDataURL('image/png', 1.0);
    } catch {
        return image.src;
    }
}