diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json
index c476411d3f..6fd46aafcf 100644
--- a/invokeai/frontend/web/public/locales/en.json
+++ b/invokeai/frontend/web/public/locales/en.json
@@ -384,7 +384,9 @@
"selectAnImageToCompare": "Select an Image to Compare",
"slider": "Slider",
"sideBySide": "Side-by-Side",
- "swapImages": "Swap"
+ "swapImages": "Swap Images",
+ "compareOptions": "Comparison Options",
+ "sliderFitLabel": "Stretch second image to fit"
},
"hotkeys": {
"searchHotkeys": "Search Hotkeys",
diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageViewer/ImageComparisonSlider.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageViewer/ImageComparisonSlider.tsx
index c7a411c07c..43c97a69b5 100644
--- a/invokeai/frontend/web/src/features/gallery/components/ImageViewer/ImageComparisonSlider.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/ImageViewer/ImageComparisonSlider.tsx
@@ -1,5 +1,6 @@
import { Box, Flex, Icon, Image, Text } from '@invoke-ai/ui-library';
import { useMeasure } from '@reactuses/core';
+import { useAppSelector } from 'app/store/storeHooks';
import type { Dimensions } from 'features/canvas/store/canvasTypes';
import { STAGE_BG_DATAURL } from 'features/controlLayers/util/renderers';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
@@ -29,6 +30,7 @@ type Props = {
export const ImageComparisonSlider = memo(({ firstImage, secondImage }: Props) => {
const { t } = useTranslation();
+ const sliderFit = useAppSelector((s) => s.gallery.sliderFit);
// How far the handle is from the left - this will be a CSS calculation that takes into account the handle width
const [left, setLeft] = useState(HANDLE_LEFT_INITIAL_PX);
// How wide the first image is
@@ -165,11 +167,11 @@ export const ImageComparisonSlider = memo(({ firstImage, secondImage }: Props) =
{
const { t } = useTranslation();
const dispatch = useAppDispatch();
const comparisonMode = useAppSelector((s) => s.gallery.comparisonMode);
+ const sliderFit = useAppSelector((s) => s.gallery.sliderFit);
const setComparisonModeSlider = useCallback(() => {
dispatch(comparisonModeChanged('slider'));
}, [dispatch]);
@@ -17,6 +32,12 @@ export const ImageComparisonToolbarButtons = memo(() => {
const swapImages = useCallback(() => {
dispatch(comparedImagesSwapped());
}, [dispatch]);
+ const onSliderFitChanged = useCallback(
+ (e: ChangeEvent) => {
+ dispatch(sliderFitChanged(e.target.checked ? 'fill' : 'contain'));
+ },
+ [dispatch]
+ );
return (
<>
@@ -31,6 +52,30 @@ export const ImageComparisonToolbarButtons = memo(() => {
{t('gallery.sideBySide')}
+
+
+ }
+ />
+
+
+
+
+
+ {t('gallery.sliderFitLabel')}
+
+
+
+
+
+
+
>
);
diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts
index d8618ea200..4a49acafc5 100644
--- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts
+++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts
@@ -24,6 +24,7 @@ const initialGalleryState: GalleryState = {
viewerMode: 'view',
imageToCompare: null,
comparisonMode: 'slider',
+ sliderFit: 'fill',
};
export const gallerySlice = createSlice({
@@ -97,6 +98,9 @@ export const gallerySlice = createSlice({
state.imageToCompare = oldSelection[0] ?? null;
}
},
+ sliderFitChanged: (state, action: PayloadAction<'contain' | 'fill'>) => {
+ state.sliderFit = action.payload;
+ },
},
extraReducers: (builder) => {
builder.addMatcher(isAnyBoardDeleted, (state, action) => {
@@ -138,6 +142,7 @@ export const {
imageToCompareChanged,
comparisonModeChanged,
comparedImagesSwapped,
+ sliderFitChanged,
} = gallerySlice.actions;
const isAnyBoardDeleted = isAnyOf(
diff --git a/invokeai/frontend/web/src/features/gallery/store/types.ts b/invokeai/frontend/web/src/features/gallery/store/types.ts
index f406c37303..1388c792c3 100644
--- a/invokeai/frontend/web/src/features/gallery/store/types.ts
+++ b/invokeai/frontend/web/src/features/gallery/store/types.ts
@@ -24,5 +24,6 @@ export type GalleryState = {
alwaysShowImageSizeBadge: boolean;
imageToCompare: ImageDTO | null;
comparisonMode: ComparisonMode;
+ sliderFit: 'contain' | 'fill';
viewerMode: ViewerMode;
};