@@ -12,6 +12,7 @@ import {
1212 BreadcrumbSeparator ,
1313} from "@/components/ui/breadcrumb"
1414import { Aperture , X } from "lucide-react" ;
15+ import exifr from 'exifr'
1516
1617export const metadata : Metadata = {
1718 title : "Photography" ,
@@ -27,12 +28,13 @@ const getBase64 = async (src: ArrayBuffer, size: number) => {
2728 return `data:image/${ info . format } ;base64,${ data . toString ( 'base64' ) } ` ;
2829} ;
2930
30- async function getBlurPreviewDataUrl ( public_id : string ) {
31+ async function getBlurPreviewAndMetadata ( public_id : string ) {
3132 const imageUrl = cloudinary . url ( public_id , { transformation : [ { crop : 'thumb' , width : 30 } ] } )
3233 // fetch image content and convert to data url
3334 const response = await fetch ( imageUrl ) ;
3435 const arrayBuffer = await response . arrayBuffer ( ) ;
35- return getBase64 ( arrayBuffer , 8 )
36+ const metadata = await exifr . parse ( Buffer . from ( arrayBuffer ) )
37+ return { blurDataURL : await getBase64 ( arrayBuffer , 8 ) , metadata }
3638}
3739
3840async function getPhotos ( ) {
@@ -42,12 +44,15 @@ async function getPhotos() {
4244 secure : true ,
4345 } ) ;
4446 const res = await cloudinary . api . resources_by_tag ( 'photography' , { resource_type : 'image' , tags : true } )
45- return Promise . all ( res . resources . map ( async resource => ( {
46- ...resource ,
47- tags : resource . tags . filter ( t => t !== 'photography' ) ,
48- blurDataURL : await getBlurPreviewDataUrl ( resource . secure_url ) ,
49- metadata : ( await cloudinary . api . resource ( resource . public_id , { media_metadata : true } ) ) . media_metadata
50- } ) ) ) ;
47+ return Promise . all ( res . resources . map ( async resource => {
48+ const { blurDataURL, metadata } = await getBlurPreviewAndMetadata ( resource . secure_url )
49+ return {
50+ ...resource ,
51+ tags : resource . tags . filter ( t => t !== 'photography' ) ,
52+ blurDataURL,
53+ metadata
54+ }
55+ } ) ) ;
5156 } catch ( error ) {
5257 console . error ( "Error fetching photos from Cloudinary:" , error ) ;
5358 return [ ] ;
@@ -62,7 +67,7 @@ const getThumbUrl = (public_id: string) => {
6267
6368export default async function PhotographyPage ( ) {
6469 const photos = await cachedGetPhotos ( )
65- console . log ( photos . map ( p => p ) )
70+ console . log ( photos . map ( p => p . metadata ) )
6671 return (
6772 < div className = "container mx-auto px-4 py-8" >
6873 < Breadcrumb className = "pb-8" >
@@ -103,11 +108,11 @@ export default async function PhotographyPage() {
103108 { photo . metadata && (
104109 < div className = "mt-2 text-xs" >
105110 < div className = "mb-1 flex flex-wrap gap-x-4 text-xs text-muted-foreground justify-between" >
106- < span > { photo . metadata . FocalLength } </ span >
111+ < span > { photo . metadata . FocalLength } mm </ span >
107112 < span > f/{ photo . metadata . FNumber } </ span >
108- < span > { photo . metadata . ExposureTime } s</ span >
113+ < span > 1/ { 1 / photo . metadata . ExposureTime } s</ span >
109114 < span > ISO { photo . metadata . ISO } </ span >
110- < span > { Number ( photo . metadata . ExposureCompensation ) === 0 ? "±" : "" } { photo . metadata . ExposureCompensation } EV</ span >
115+ < span > { photo . metadata . ExposureCompensation === 0 ? "±" : "" } { photo . metadata . ExposureCompensation } EV</ span >
111116 </ div >
112117 < div className = "flex gap-2 flex-wrap" >
113118 < span className = "font-semibold" > { photo . metadata . Make } { photo . metadata . Model } </ span >
0 commit comments