Demotes inpainting to img2img when mask is empty

This commit is contained in:
psychedelicious 2022-10-30 23:17:51 +11:00
parent fe700d27df
commit 12c4c715aa

View File

@ -5,21 +5,19 @@ import { MaskLine } from '../inpaintingSlice';
/** /**
* Re-draws the mask canvas onto a new Konva stage. * Re-draws the mask canvas onto a new Konva stage.
*/ */
export const generateMaskCanvas = ( const generateMask = (
image: HTMLImageElement, image: HTMLImageElement,
lines: MaskLine[] lines: MaskLine[],
): { boundingBox: IRect
stage: Konva.Stage; ) => {
layer: Konva.Layer; const { x, y, width, height } = boundingBox;
} => {
const { width, height } = image;
const offscreenContainer = document.createElement('div'); const offscreenContainer = document.createElement('div');
const stage = new Konva.Stage({ const stage = new Konva.Stage({
container: offscreenContainer, container: offscreenContainer,
width: width, width: image.width,
height: height, height: image.height,
}); });
const layer = new Konva.Layer(); const layer = new Konva.Layer();
@ -42,67 +40,30 @@ export const generateMaskCanvas = (
) )
); );
layer.draw(); // check if mask is empty
const pixelBuffer = new Uint32Array(
layer.getContext().getImageData(x, y, width, height).data.buffer
);
offscreenContainer.remove(); const isMaskEmpty = !pixelBuffer.some((color) => color !== 0);
return { stage, layer }; if (isMaskEmpty) {
}; layer.add(
new Konva.Rect({
/** ...boundingBox,
* Check if the bounding box region has only fully transparent pixels. fill: 'rgb(0,0,0)',
*/ })
export const checkIsRegionEmpty = (
stage: Konva.Stage,
boundingBox: IRect
): boolean => {
const imageData = stage
.toCanvas()
.getContext('2d')
?.getImageData(
boundingBox.x,
boundingBox.y,
boundingBox.width,
boundingBox.height
); );
if (!imageData) {
throw new Error('Unable to get image data from generated canvas');
} }
const pixelBuffer = new Uint32Array(imageData.data.buffer);
return !pixelBuffer.some((color) => color !== 0);
};
/**
* Generating a mask image from InpaintingCanvas.tsx is not as simple
* as calling toDataURL() on the canvas, because the mask may be represented
* by colored lines or transparency, or the user may have inverted the mask
* display.
*
* So we need to regenerate the mask image by creating an offscreen canvas,
* drawing the mask and compositing everything correctly to output a valid
* mask image.
*/
const generateMask = (
image: HTMLImageElement,
lines: MaskLine[],
boundingBox: IRect
): { maskDataURL: string; isMaskEmpty: boolean } => {
// create an offscreen canvas and add the mask to it
const { stage, layer } = generateMaskCanvas(image, lines);
// check if the mask layer is empty
const isMaskEmpty = checkIsRegionEmpty(stage, boundingBox);
// composite the image onto the mask layer
layer.add( layer.add(
new Konva.Image({ image: image, globalCompositeOperation: 'source-out' }) new Konva.Image({ image: image, globalCompositeOperation: 'source-out' })
); );
const maskDataURL = stage.toDataURL(); const maskDataURL = stage.toDataURL();
offscreenContainer.remove();
return { maskDataURL, isMaskEmpty }; return { maskDataURL, isMaskEmpty };
}; };