Auto-generate blur data when editing photos

This commit is contained in:
Sam Becker 2024-05-06 21:34:04 -05:00
parent afd0e23a67
commit af0b004a79
5 changed files with 35 additions and 20 deletions

View File

@ -1,24 +1,17 @@
import Link from 'next/link';
import PathLoaderButton from '@/components/PathLoaderButton';
import { FaRegEdit } from 'react-icons/fa';
export default function EditButton ({
href,
label = 'Edit',
}: {
href: string,
label?: string,
}) {
return (
<Link
title={label}
href={href}
className="button"
prefetch={false}
<PathLoaderButton
path={href}
icon={<FaRegEdit size={15} className="translate-y-[0.5px]" />}
>
<FaRegEdit className="translate-y-[-0.5px]" />
<span className="hidden sm:inline-block">
{label}
</span>
</Link>
Edit
</PathLoaderButton>
);
}

View File

@ -3,8 +3,8 @@ import { getPhotoNoStore, getUniqueTagsCached } from '@/photo/cache';
import { PATH_ADMIN } from '@/site/paths';
import PhotoEditPageClient from '@/photo/PhotoEditPageClient';
import { AI_TEXT_GENERATION_ENABLED } from '@/site/config';
import { resizeImageFromUrl } from '@/photo/server';
import { getNextImageUrlForRequest } from '@/services/next-image';
import { blurImageFromUrl, resizeImageFromUrl } from '@/photo/server';
import { getNextImageUrlForManipulation } from '@/services/next-image';
export default async function PhotoEditPage({
params: { photoId },
@ -21,15 +21,20 @@ export default async function PhotoEditPage({
// Only generate image thumbnails when AI generation is enabled
const imageThumbnailBase64 = AI_TEXT_GENERATION_ENABLED
? await resizeImageFromUrl(getNextImageUrlForRequest(photo.url, 640))
? await resizeImageFromUrl(getNextImageUrlForManipulation(photo.url))
: '';
const blurData = await blurImageFromUrl(
getNextImageUrlForManipulation(photo.url)
);
return (
<PhotoEditPageClient {...{
photo,
uniqueTags,
hasAiTextGeneration,
imageThumbnailBase64,
blurData,
}} />
);
};

View File

@ -22,11 +22,13 @@ export default function PhotoEditPageClient({
uniqueTags,
hasAiTextGeneration,
imageThumbnailBase64,
blurData,
}: {
photo: Photo
uniqueTags: TagsWithMeta
hasAiTextGeneration: boolean
imageThumbnailBase64: string
blurData: string
}) {
const seedExifData = { url: photo.url };
@ -86,6 +88,7 @@ export default function PhotoEditPageClient({
updatedExifData={hasExifDataBeenFound
? updatedExifData
: undefined}
updatedBlurData={blurData}
uniqueTags={uniqueTags}
aiContent={hasAiTextGeneration ? aiContent : undefined}
onTitleChange={setUpdatedTitle}

View File

@ -27,22 +27,25 @@ import Spinner from '@/components/Spinner';
import usePreventNavigation from '@/utility/usePreventNavigation';
import { useAppState } from '@/state/AppState';
import UpdateBlurDataButton from '../UpdateBlurDataButton';
import { getNextImageUrlForManipulation } from '@/services/next-image';
const THUMBNAIL_SIZE = 300;
export default function PhotoForm({
type = 'create',
initialPhotoForm,
updatedExifData,
type = 'create',
updatedBlurData,
uniqueTags,
aiContent,
onTitleChange,
onTextContentChange,
onFormStatusChange,
}: {
type?: 'create' | 'edit'
initialPhotoForm: Partial<PhotoFormData>
updatedExifData?: Partial<PhotoFormData>
type?: 'create' | 'edit'
updatedBlurData?: string
uniqueTags?: TagsWithMeta
aiContent?: AiContent
onTitleChange?: (updatedTitle: string) => void
@ -110,6 +113,12 @@ export default function PhotoForm({
const url = formData.url ?? '';
useEffect(() =>
setFormData(data => updatedBlurData
? { ...data, blurData: updatedBlurData }
: data)
, [updatedBlurData]);
useEffect(() =>
setFormData(data => aiContent?.title
? { ...data, title: aiContent?.title }
@ -184,9 +193,9 @@ export default function PhotoForm({
shouldConfirm={Boolean(formData.semanticDescription)}
/>;
case 'blurData':
return type === 'edit'
return shouldDebugBlur && type === 'edit' && formData.url
? <UpdateBlurDataButton
photoUrl={formData.url}
photoUrl={getNextImageUrlForManipulation(formData.url)}
onUpdatedBlurData={blurData =>
setFormData(data => ({ ...data, blurData }))}
/>

View File

@ -23,3 +23,8 @@ export const getNextImageUrlForRequest = (
return url.toString();
};
// Generate small, low-bandwidth images for quick manipulations such as
// generating blur data or image thumbnails for AI text generation
export const getNextImageUrlForManipulation = (imageUrl: string) =>
getNextImageUrlForRequest(imageUrl, 640, 90);