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:
>
) : (
No metadata available
)}
);
},
memoEqualityCheck
);
export default ImageMetadataViewer;