mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): colored mask preview image
This commit is contained in:
parent
9f86605049
commit
5e59a4f43a
@ -1,13 +1,36 @@
|
|||||||
import { Box, chakra, Flex } from '@invoke-ai/ui-library';
|
import { Box, chakra, Flex } from '@invoke-ai/ui-library';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { rgbColorToString } from 'common/util/colorCodeTransformers';
|
||||||
import { useEntityAdapter } from 'features/controlLayers/contexts/EntityAdapterContext';
|
import { useEntityAdapter } from 'features/controlLayers/contexts/EntityAdapterContext';
|
||||||
|
import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext';
|
||||||
import { TRANSPARENCY_CHECKER_PATTERN } from 'features/controlLayers/konva/constants';
|
import { TRANSPARENCY_CHECKER_PATTERN } from 'features/controlLayers/konva/constants';
|
||||||
import { memo, useEffect, useRef } from 'react';
|
import { selectCanvasV2Slice, selectEntity } from 'features/controlLayers/store/canvasV2Slice';
|
||||||
|
import { memo, useEffect, useMemo, useRef } from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
const ChakraCanvas = chakra.canvas;
|
const ChakraCanvas = chakra.canvas;
|
||||||
|
|
||||||
|
const PADDING = 4;
|
||||||
|
|
||||||
export const CanvasEntityPreviewImage = memo(() => {
|
export const CanvasEntityPreviewImage = memo(() => {
|
||||||
|
const entityIdentifier = useEntityIdentifierContext();
|
||||||
const adapter = useEntityAdapter();
|
const adapter = useEntityAdapter();
|
||||||
|
const selectMaskColor = useMemo(
|
||||||
|
() =>
|
||||||
|
createSelector(selectCanvasV2Slice, (state) => {
|
||||||
|
const entity = selectEntity(state, entityIdentifier);
|
||||||
|
if (!entity) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (entity.type === 'inpaint_mask' || entity.type === 'regional_guidance') {
|
||||||
|
return rgbColorToString(entity.fill.color);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}),
|
||||||
|
[entityIdentifier]
|
||||||
|
);
|
||||||
|
const maskColor = useSelector(selectMaskColor);
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
const cache = useStore(adapter.renderer.$canvasCache);
|
const cache = useStore(adapter.renderer.$canvasCache);
|
||||||
@ -26,8 +49,25 @@ export const CanvasEntityPreviewImage = memo(() => {
|
|||||||
canvasRef.current.width = rect.width;
|
canvasRef.current.width = rect.width;
|
||||||
canvasRef.current.height = rect.height;
|
canvasRef.current.height = rect.height;
|
||||||
|
|
||||||
ctx.drawImage(canvas, rect.x, rect.y, rect.width, rect.height, 0, 0, rect.width, rect.height);
|
const scale = containerRef.current.offsetWidth / rect.width;
|
||||||
}, [adapter.transformer, adapter.transformer.nodeRect, adapter.transformer.pixelRect, cache]);
|
|
||||||
|
const sx = rect.x;
|
||||||
|
const sy = rect.y;
|
||||||
|
const sWidth = rect.width;
|
||||||
|
const sHeight = rect.height;
|
||||||
|
const dx = PADDING / scale;
|
||||||
|
const dy = PADDING / scale;
|
||||||
|
const dWidth = rect.width - (PADDING * 2) / scale;
|
||||||
|
const dHeight = rect.height - (PADDING * 2) / scale;
|
||||||
|
|
||||||
|
ctx.drawImage(canvas, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
|
||||||
|
|
||||||
|
if (maskColor) {
|
||||||
|
ctx.fillStyle = maskColor;
|
||||||
|
ctx.globalCompositeOperation = 'source-in';
|
||||||
|
ctx.fillRect(0, 0, rect.width, rect.height);
|
||||||
|
}
|
||||||
|
}, [adapter.transformer, adapter.transformer.nodeRect, adapter.transformer.pixelRect, cache, maskColor]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
Loading…
x
Reference in New Issue
Block a user