yihong0618 和朋友们的频道 头像

消息来源频道

yihong0618 和朋友们的频道

@hyi0618

频道8,612 位成员公开可见0 人在线

yihong0618 和朋友们的频道

成员规模8,612 位成员
在线情况0 人在线
消息总数10,129 条消息
浏览量总数3,276,841 次浏览

在这个频道里搜索消息……

t.me/hyi0618

TIL:
Link: https://github.com/simonw/til/blob/main/exif/orientation-and-location.md
📌 Interpreting photo orientation and locations in EXIF data
I upgraded my Niche Museums site to use PhotoSwipe for its photo galleries today. Here's my issue.
This lead me down a bit of a rabbit hole of photo EXIF data.
The two problems I ended up solving:
⦁ Given photo EXIF data, what is the width and height of the image (taking photo orientation into account)?
⦁ Also given EXIF data, how can I determine the latitude and longitude of the photo?
✏️ Figuring out the width and height
The PhotoSwipe gallery code needs to have the width and heights of the images embedded in custom data- attributes like this:
<a
data-pswp-height="3024"
data-pswp-width="4032"
href="https://niche-museums.imgix.net/pioneer-history-19.jpeg?w=1200&auto=compress"
class="gallery-photo">
<img
src="https://niche-museums.imgix.net/pioneer-history-19.jpeg?w=400&blur=200&px=16&auto=format">
</a>
My database was only storing the URL to those images, not their widths and heights. In order to generate the correct HTML I needed that extra information.
Niche Museums hosts photos in an S3 bucket behind Imgix, which means I can resize the photos on demand using the ?w= and ?h= query parameters.
It also means I can get back JSON for the EXIF data of the images by appending ?fm=json.
https://niche-museums.imgix.net/pioneer-history-18.jpeg?fm=json
There's a lot of information in there, but the most important bits for solving this problem are:
{
"Orientation": 3,
"PixelWidth": 4032,
"PixelHeight": 3024
}
For my first attempt, I assumed that PixelWidth and PixelHeight represented the width and height of the image, respectively.
This almost worked... except for some photos which were displayed in portrait mode, for which the two values appeared to be swapped.
The answer turned out to be in the Orientation parameter. GPT-4 helped me understand the following:
The values you mentioned (1, 3, 6, and 8) represent the most common orientations:

⦁ 1: Normal (0° rotation)
⦁ 3: Upside-down (180° rotation)
⦁ 6: Rotated 90° counterclockwise (270° clockwise)
⦁ 8: Rotated 90° clockwise (270° counterclockwise)
So I need to flip the width and height values if the orientation is 6 or 8.
I ended up doing that using this SQL query:
select
'https://niche-museums.imgix.net/' || filename as url,
case
when Orientation in (6, 8) then PixelHeight
else PixelWidth
end as width,
case
when Orientation in (6, 8) then PixelWidth
else PixelHeight
end as height
from raw_photos;
✏️ That raw_photos table
I skipped a step here: how did I load the data into that raw_photos table in the first place?
First I wrote a Python script to retrieve the JSON metadata for every photo. This dumped them into a photos-metadata/, each one with a name like IMG_0859.jpeg.json.
That script now runs in GitHub to catch metadata for newly added photos - a form of Git scraping.
Next, I wrote a sqlite-utils to load all of those JSON files into my SQLite database. That script also creates a photos view that implements the above case SQL logic.
I initially wrote this as a shell script, but it was a LOT slower than doing it in Python:
for json_file in photos-metadata/*.json; do
sqlite-utils insert browse.db raw_photos \
--pk=filename \
--replace \
--alter \
--