import { Center, Flex, Heading, IconButton, Link, Text, Tooltip, } from '@chakra-ui/react'; import { ExternalLinkIcon } from '@chakra-ui/icons'; import { memo } from 'react'; import { IoArrowUndoCircleOutline } from 'react-icons/io5'; import { useAppDispatch } from '../../../app/store'; import * as InvokeAI from '../../../app/invokeai'; import { setCfgScale, setFacetoolStrength, setCodeformerFidelity, setFacetoolType, setHeight, setHiresFix, setImg2imgStrength, setInitialImagePath, setMaskPath, setPrompt, setSampler, setSeamless, setSeed, setSeedWeights, setShouldFitToWidthHeight, setSteps, setUpscalingLevel, setUpscalingStrength, setWidth, } from '../../options/optionsSlice'; import promptToString from '../../../common/util/promptToString'; import { seedWeightsToString } from '../../../common/util/seedWeightPairs'; import { FaCopy } from 'react-icons/fa'; type MetadataItemProps = { isLink?: boolean; label: string; onClick?: () => void; value: number | string | boolean; labelPosition?: string; }; /** * Component to display an individual metadata item or parameter. */ const MetadataItem = ({ label, value, onClick, isLink, labelPosition, }: MetadataItemProps) => { return ( {onClick && ( } size={'xs'} variant={'ghost'} fontSize={20} onClick={onClick} /> )} {label}: {isLink ? ( {value.toString()} ) : ( {value.toString()} )} ); }; type ImageMetadataViewerProps = { image: InvokeAI.Image; styleClass?: string; }; // TODO: I don't know if this is needed. const memoEqualityCheck = ( prev: ImageMetadataViewerProps, next: ImageMetadataViewerProps ) => prev.image.uuid === next.image.uuid; // TODO: Show more interesting information in this component. /** * Image metadata viewer overlays currently selected image and provides * access to any of its metadata for use in processing. */ const ImageMetadataViewer = memo( ({ image, styleClass }: ImageMetadataViewerProps) => { const dispatch = useAppDispatch(); // const jsonBgColor = useColorModeValue('blackAlpha.100', 'whiteAlpha.100'); const metadata = image?.metadata?.image || {}; const { type, postprocessing, sampler, prompt, seed, variations, steps, cfg_scale, seamless, hires_fix, width, height, strength, fit, init_image_path, mask_image_path, orig_path, scale, } = metadata; const metadataJSON = JSON.stringify(metadata, null, 2); return (
File: {image.url} {Object.keys(metadata).length > 0 ? ( <> {type && } {['esrgan', 'gfpgan'].includes(type) && ( )} {type === 'gfpgan' && strength !== undefined && ( dispatch(setFacetoolStrength(strength))} /> )} {type === 'esrgan' && scale !== undefined && ( dispatch(setUpscalingLevel(scale))} /> )} {type === 'esrgan' && strength !== undefined && ( dispatch(setUpscalingStrength(strength))} /> )} {prompt && ( dispatch(setPrompt(prompt))} /> )} {seed !== undefined && ( dispatch(setSeed(seed))} /> )} {sampler && ( dispatch(setSampler(sampler))} /> )} {steps && ( dispatch(setSteps(steps))} /> )} {cfg_scale !== undefined && ( dispatch(setCfgScale(cfg_scale))} /> )} {variations && variations.length > 0 && ( dispatch(setSeedWeights(seedWeightsToString(variations))) } /> )} {seamless && ( dispatch(setSeamless(seamless))} /> )} {hires_fix && ( dispatch(setHiresFix(hires_fix))} /> )} {width && ( dispatch(setWidth(width))} /> )} {height && ( dispatch(setHeight(height))} /> )} {init_image_path && ( dispatch(setInitialImagePath(init_image_path))} /> )} {mask_image_path && ( dispatch(setMaskPath(mask_image_path))} /> )} {type === 'img2img' && strength && ( dispatch(setImg2imgStrength(strength))} /> )} {fit && ( dispatch(setShouldFitToWidthHeight(fit))} /> )} {postprocessing && postprocessing.length > 0 && ( <> Postprocessing {postprocessing.map( ( postprocess: InvokeAI.PostProcessedImageMetadata, i: number ) => { if (postprocess.type === 'esrgan') { const { scale, strength } = postprocess; return ( {`${ i + 1 }: Upscale (ESRGAN)`} dispatch(setUpscalingLevel(scale))} /> dispatch(setUpscalingStrength(strength)) } /> ); } else if (postprocess.type === 'gfpgan') { const { strength } = postprocess; return ( {`${ i + 1 }: Face restoration (GFPGAN)`} { dispatch(setFacetoolStrength(strength)); dispatch(setFacetoolType('gfpgan')); }} /> ); } else if (postprocess.type === 'codeformer') { const { strength, fidelity } = postprocess; return ( {`${ i + 1 }: Face restoration (Codeformer)`} { dispatch(setFacetoolStrength(strength)); dispatch(setFacetoolType('codeformer')); }} /> {fidelity && ( { dispatch(setCodeformerFidelity(fidelity)); dispatch(setFacetoolType('codeformer')); }} /> )} ); } } )} )} } size={'xs'} variant={'ghost'} fontSize={14} onClick={() => navigator.clipboard.writeText(metadataJSON) } /> Metadata JSON:
{metadataJSON}
) : (
No metadata available
)}
); }, memoEqualityCheck ); export default ImageMetadataViewer;