약속이 아닌, 측정

성능

이 페이지의 모든 수치는 평범한 노트북(Apple M3, 16 GB)에서 실제 사진으로 측정했고, 그 수치를 낸 스크립트가 저장소에 있어 누구나 다시 실행할 수 있습니다. 각 차트 아래에는 프린트에 어떤 의미인지를, 마지막에는 수치 뒤의 용어 설명을 실었습니다.

Fotollection이 빠른 이유

마법은 없습니다. 첫 코드를 쓰기 전에 정한 몇 가지 결정, 그리고 그 모든 측정.

  1. 모든 코어에서 네이티브 코드

    Fotollection의 작업은 Rust로 실행되며, 내 프로세서에 맞게 컴파일되어 모든 코어에 나뉘고, 프로세서가 픽셀 처리를 위해 제공하는 벡터 명령어(SIMD)를 씁니다.1,2,3

    23.5 / 초16 MP 사진 내보내기

  2. 필요한 것만

    폴더를 열 때는 각 파일의 EXIF와 작은 내장 썸네일만 읽고, 사진 전체는 읽지 않습니다. 썸네일은 디스크 캐시에 저장됩니다.4

    0.12초사진 1,000장 열기

  3. 화면보다 많은 픽셀은 다루지 않기

    미리 보기는 최대 1600 px로, 메모리에 둔 2048 px 사본에서 만듭니다. 원본 사진은 확대할 때만 부분별로 읽습니다.

    17 ms미리 보기 다시 그리기

  4. 클릭하기 전에 준비 완료

    썸네일이 다 되면 모든 사진의 미리 보기를 백그라운드에서 만들어 디스크에 두고, 메모리의 4분의 1로 화면 속 사진의 앞뒤 사진을 들고 있습니다.

    27 ms어떤 사진이든 열기

  5. 같은 일은 두 번 하지 않기

    색 슬라이더는 색만 바꾸고 크기는 바꾸지 않습니다. 모든 색 슬라이더는 33 × 33 × 33색의 테이블 하나로 합쳐지므로, 슬라이더 10개도 1개와 같은 비용입니다.

    2 ms미리 보기에서 색 슬라이더 10개

  6. 예산 안의 메모리

    Fotollection이 동시에 다루는 원본 크기 사진은 메모리 예산이 허락하는 만큼뿐이며, 그 예산은 내보내기에서 가장 큰 사진으로 정해집니다.

    1.45 GB사진 5,035장의 메모리 최대치

  7. 측정으로 조정한 인코더

    프린트용 파일에서는 크기를 1 % 도 줄이지 못하면서 인코딩 시간의 3분의 1을 쓰던 테이블 최적화를 건너뜁니다.

    −33 %프린트용 파일의 인코딩 시간

  8. 편집하는 동안은 그래픽 카드

    색 슬라이더를 움직이는 동안에는 코어가 만든 테이블로 그래픽 카드가 그립니다. 내보내기는 프로세서에서 하므로, 프린트는 어느 컴퓨터에서나 똑같습니다.

    1–2 ms슬라이더 한 단계(26 ms에서)

작업이 일어나는 곳: 내 컴퓨터의 Fotollection과 일반적인 웹 편집기
작업이 일어나는 곳: 내 컴퓨터의 Fotollection과 일반적인 웹 편집기

최대 20배 빠르게. 메모리를 쓰는 새로운 방법.

v0.11.0은 Fotollection이 사진을 다루는 방식을 새로 생각했습니다. 썸네일이 다 되면 모든 사진의 미리 보기를 백그라운드에서 만들어 디스크에 두고, 컴퓨터 메모리의 4분의 1로 보고 있는 사진의 앞뒤를 들고 있으며, 화면 속 사진이 언제나 먼저입니다. 그 결과 가까이 있든 멀리 있든, JPEG든 RAW든 어떤 사진이든 27밀리초에 열립니다. 같은 여행의 사진 422장으로 측정해, RAW 열기는 v0.9.0보다 최대 20배, JPEG는 10배 빠릅니다.5,6

20×v0.9.0보다 빠른 RAW 사진 열기(531 → 27 ms)
10×v0.9.0보다 빠른 JPEG 열기(274 → 27 ms)
27 ms가깝든 멀든 어떤 사진이든 열기(예산 100 ms)
사진 열기: v0.9.0과 v0.10.0을 v0.11.0과 비교, 한 여행의 사진 422장으로
사진 열기: v0.9.0과 v0.10.0을 v0.11.0과 비교, 한 여행의 사진 422장으로7
사진 미리 보기의 출처: 메모리, 다음은 디스크, 다음은 파일
사진 미리 보기의 출처: 메모리, 다음은 디스크, 다음은 파일

이전: 클릭할 때마다 사진을 디코딩

v0.10.0까지는 미리보기를 요청받은 시점에 만들었습니다. 파일을 읽고, 사진을 디코딩(RAW라면 현상)하고, 방향을 바로잡고, 2048 px로 크기를 줄여 sRGB로 변환한 다음, 자르기, 색 입히기, 날짜 넣기, 화면용 인코딩을 했습니다. Lumix GX9의 20 MP 사진에서 최근 8장에 들어 있지 않은 사진을 열 때마다 JPEG는 274~278 ms, RAW는 440~531 ms가 걸렸습니다. 한 장이라면 충분히 빠르지만, 여행 사진을 연달아 넘겨 보기에는 부족합니다.

Lightroom과 같은 표준 미리보기

v0.11.0부터는 사용자가 기다리는 작업을 요청받기 전에 끝내 둡니다. 폴더의 썸네일이 갖춰지면 곧바로 Fotollection이 백그라운드에서 모든 사진의 2048 px 사본을 스레드마다 한 장씩 만들어, 썸네일 옆 디스크에 약 0.66 MB의 JPEG로 저장합니다(여행 전체로 약 280 MB). 가까운 사진이든 먼 사진이든, 이번 세션이든 다음 세션이든, 어떤 사진을 클릭해도 이 사본에서 시작합니다. JPEG든 RAW든 27 ms입니다. 남는 것은 미리보기 자체의 처리(자르기, 크기 조정, 색, 날짜, 인코딩)로, 메모리에서 열 때와 같은 27 ms입니다. 디스크의 사본으로 만든 미리보기는 새로 만든 것과 평균 1.35레벨(255단계 중)밖에 차이 나지 않아 눈으로 구분할 수 없습니다.8

메모리는 최소가 아니라 잘 쓰기

16 GB 노트북에서 8장만 메모리에 두는 사진 뷰어는 그 노트북을 낭비하는 셈입니다. Fotollection은 이제 컴퓨터 메모리의 4분의 1을 미리보기에 씁니다(16 GB Mac이라면 2048 px로 약 190장, 슬라이더용 RAW 현상 20장 분량, 확대용 600 MB). 바이트 단위로 세고 가장 오래된 것부터 비웁니다. 사진이 화면에 뜨면 진행 방향의 다음 2장과 뒤의 1장도 읽어 오므로, 화살표 키로 넘길 때 기다릴 일이 없습니다. 내보내기에는 여전히 2 GB 상한이 적용됩니다.

화면의 사진이 최우선

RAW 현상은 한 번에 하나만 실행해 RAW 묶음이 메모리에 들어가도록 합니다. 이전에는 순서가 운에 맡겨져, 만드는 중인 미리보기, 내보내기 크기 예상, 내보내기가 클릭한 사진을 기다리게 하는 일이 있었습니다. 이제 모든 현상은 누가 기다리고 있는지 알리고, 화면의 사진이 현상을 필요로 할 때마다 백그라운드 작업이 길을 비켜 줍니다. 이 작업 중에 드물게 일어나던 멈춤 두 가지도 찾아내 지금은 해결했습니다. 하나는 실행할 스레드가 남지 않은 현상을 모든 스레드가 기다리던 것, 다른 하나는 화면이 한 번도 요청하지 않은 이미지를 기다리던 것입니다.

버전 JPEG p50 / p95 RAW p50 / p95 방식
v0.9.0 274 / 286 ms 531 / 550 ms 클릭할 때 디코딩. RAW는 macOS를 거침
v0.10.0 278 / 293 ms 440 / 471 ms 클릭할 때 디코딩. RAW는 자체 현상
v0.11.0 27 / 32 ms 27 / 30 ms 디스크의 표준 미리보기 또는 메모리에서

제작자의 프라하 여행(JPEG 396장과 RAW 26장, 20 MP)으로 Apple M3에서 measure_browse를 사용해 측정했습니다. v0.9.0은 해당 태그에서 빌드했고, v0.10.0은 이 변경 바로 전의 코드로 측정했습니다.

속도: 사진 1,000장을 눈 깜짝할 사이에

폴더를 열 때는 각 사진의 EXIF와 작은 내장 썸네일만 읽고, 이미지 전체는 읽지 않으며, 설정을 바꾸면 미리 보기만 다시 그립니다. 네이티브 Rust는 같은 작업을 하는 웹 브라우저보다도 낫습니다. 내보내기 속도는 같고, 미리 보기는 더 빠르며, 메모리는 4분의 1 적게 씁니다.9

0.12초사진 1,000장 폴더 읽기, 예산의 8분의 1
17 ms변경 후 미리 보기 다시 그리기
23.5초당 내보내는 16 MP 사진
속도와 메모리, 코드를 쓰기 전에 정한 예산과 비교
속도와 메모리, 코드를 쓰기 전에 정한 예산과 비교7
같은 작업을 Fotollection과 웹 브라우저에서
같은 작업을 Fotollection과 웹 브라우저에서7

폴더를 열 때 일어나는 일

Fotollection은 사진 폴더를 통째로 읽지 않습니다. 각 파일에서 읽는 것은 EXIF(날짜, 카메라, 촬영 장소)와 모든 카메라가 파일에 저장해 두는 작은 썸네일뿐입니다. 1000장에 0.12초로, 코드를 쓰기 전에 정한 1초 목표보다 훨씬 빠릅니다. 그다음 백그라운드에서, Fotollection이 가볍게 반응하도록 스레드 두 개로 더 선명한 400 px 썸네일을 만들어 디스크 캐시에 넣으므로, 다시 연 폴더는 바로 표시됩니다. 5035장에서는 읽기에 383 ms, 내장 썸네일에 236 ms가 걸렸습니다.

미리보기 17 ms의 내역

설정을 바꾸면 미리보기는 메모리에 있는 사진의 2048 px 사본으로 다시 그려지며, 원본 크기 파일에서 그리는 일은 결코 없습니다. 걸리는 시간 16.7 ms 중 자르기와 Lanczos 필터 크기 조정이 9.7 ms, 날짜가 0.1 ms 미만, 화면용 미리보기 JPEG 인코딩이 7.0 ms입니다. 이 인코더는 측정하면서 조정했습니다. 내보내기와 같은 설정(전체 색 해상도와 최적화한 테이블)으로는 16.2 ms가 걸렸습니다. 화면에는 그런 것이 필요 없으므로 미리보기는 색 정보를 절반으로 하고 표준 테이블을 쓰며, 내보내기는 풀 컬러(4:4:4)로 만듭니다. 더 가벼운 크기 조정 필터도 시험했지만 이 프로세서에서는 오히려 느려서(12.5 ms) Lanczos를 유지했습니다.

네이티브 코드와 브라우저

같은 처리(디코딩, 2:3으로 자르기, 날짜, 품질 95 JPEG)를 같은 사진 95장으로 Fotollection과 Chromium(코어마다 워커 하나)에서 실행했습니다. 내보내기 속도는 같아서 초당 18.0장 대 17.9장. 브라우저가 느리다는 처음의 가설은 틀렸습니다. 네이티브 코드의 강점은 다른 곳에 있습니다. 브라우저의 인코더가 색 정보를 절반으로 줄이는 반면, Fotollection은 전체 색 해상도 4:4:4로 파일을 쓰고, 각 사진의 색 프로필을 지키며, 파일을 디스크에 직접 쓰고, 메모리 사용량도 4분의 1 적었습니다(1.35 GB 대 1.78 GB). 그 뒤 인화용 인코더는 더 빨라져 16 MP에서 초당 23.5장입니다.

편집에는 그래픽 카드, 내보내기에는 모든 코어

색 슬라이더를 드래그하는 동안에는 Fotollection의 코어가 만드는 것과 같은 테이블로 그래픽 카드가 룩을 그리고, 손을 떼면 정확한 렌더링으로 바뀝니다. 내보내기는 프로세서에서 하므로, 프린트는 어느 컴퓨터에서나 똑같이 나옵니다.

1–2 ms그래픽 카드에서 슬라이더 한 단계(약 26 ms에서)
0.13카드의 룩과 정확한 렌더링 사이의 ΔE2000
10.8초당 내보내는 26 MP 사진, 6장 동시
색 슬라이더 한 단계: 프로세서와 그래픽 카드
색 슬라이더 한 단계: 프로세서와 그래픽 카드7
동시에 처리하는 사진 수에 따른 내보내기 속도
동시에 처리하는 사진 수에 따른 내보내기 속도7
편집은 그래픽 카드에서, 내보내기는 모든 프로세서 코어에서
편집은 그래픽 카드에서, 내보내기는 모든 프로세서 코어에서

슬라이더 10개를 1개 비용으로

모든 색 슬라이더(밝기, 대비, 색온도, 채도, 페이드, 섀도와 하이라이트 색 입히기, 흑백)는 33 × 33 × 33색의 테이블 하나로 합쳐집니다. 각 색이 어디로 가는지 나타내는 35,937개의 점입니다. 이를 사진에 적용할 때는 픽셀마다 테이블 안의 칸을 찾고, 칸의 꼭짓점 4개 사이에서 보간합니다(사면체 보간). 그래서 슬라이더 10개의 비용이 1개와 다르지 않습니다. 모든 슬라이더를 움직인 상태에서 테이블을 만드는 데 약 2.6 ms, 1600 px 미리보기에 적용하는 데 2.2 ms 미만, 24 MP 내보내기에서는 약 24 ms가 걸립니다.

그래도 드래그가 느리게 느껴졌던 이유와 그래픽카드가 바꾼 것

단계별로 재 보니 슬라이더를 한 번 움직이는 데 약 26 ms가 걸렸고, 그중 색 자체는 2 ms뿐이었습니다. 나머지는 미리보기의 JPEG 인코딩(7~11 ms)과 창에서의 재디코딩(9~15 ms)입니다. 그래픽카드는 이 둘을 모두 없앱니다. 드래그가 시작되면 색을 입히기 전의 미리보기와, 사진이 어디에 있는지(날짜, 프레임, 여백이 아닌 부분)를 나타내는 마스크를 한 번만 그래픽카드로 보냅니다. 이후 단계에서 보내는 것은 새 테이블뿐이며, 작은 WebGL2 프로그램이 코어와 똑같은 방식으로 보간합니다. 한 단계에 macOS의 WebKit에서 1 ms, Chromium에서 2 ms입니다. 손을 떼면 코어의 정확한 렌더링으로 바뀝니다. 모든 슬라이더를 움직인 강한 룩으로 둘을 비교하면 ΔE2000 차이는 평균 0.13, 99번째 백분위수에서 0.77로, 나란히 놓고 볼 때 눈이 알아차리는 1보다 훨씬 낮습니다.

스위치는 필요 없습니다. 첫 드래그에서 Fotollection이 스스로 확인하고, WebGL2가 없거나, 렌더러가 소프트웨어이거나, 시험 삼아 한 단계에 8 ms 이상 걸리면 세션이 끝날 때까지 프로세서 경로를 씁니다. 테스트에서 소프트웨어 렌더러는 한 단계에 16.5 ms가 걸렸으므로, 그 경우에는 프로세서에 머무는 것이 정답입니다.

모든 코어로 내보내기

사진 한 장의 디코딩과 인코딩은 각각 코어 하나에서 실행되므로, 내보내기는 여러 사진을 동시에 처리해야 빨라집니다. 몇 장을 동시에 할지는 메모리에 달려 있습니다. 24~26 MP 사진에서 동시 2장이면 초당 4.9장, 4장이면 9.4장, 6장이면 11.5장, 8장이면 12.5장이었고, 메모리는 0.49 GB에서 1.21 GB로 늘었습니다. Fotollection은 1.6 GB의 메모리 예산과 가장 큰 사진의 크기로 장수를 정하며, 6장에서 멈춥니다. 실제 여행 사진에서 동시 8장은 빨라지지 않고 메모리만 0.2 GB 더 썼기 때문입니다. 내보내기에는 그래픽카드를 쓰지 않습니다. 인화물은 어느 컴퓨터에서나 같아야 하며, 내보내기를 바이트 단위로 비교하는 테스트도 이를 전제로 합니다.

실제 여행: 프라하의 파일 422개

테스트용 세트는 실제보다 좋게 보일 수 있습니다. 그래서 프라하에서 주말을 보낸 뒤 Lumix GX9에서 옮긴 그대로의 폴더를 썼습니다. 한 장에 약 11 MB인 20 MP JPEG 396장과 RAW 파일 26개, 모두 4.7 GB입니다. 열면 0.23초에 모든 파일의 EXIF를 읽습니다. 미리 보기는 19 ms에 다시 그리고, RAW는 0.35초에 현상하며, 엽서 10장은 21 ms에 다시 그립니다. 2026년 11월 3일, 이 큰 파일들에서 두 수치가 예산을 넘었습니다. 내보내기는 초당 7.6장, 메모리 최대치는 2.14 GB였습니다. 원인을 찾아 v0.9.7에서 고쳤고, 이제 JPEG는 초당 10.1장씩 내보내며 전체 실행이 1.31 GB 이하로 유지됩니다.10,11

0.23초파일 422개를 EXIF까지 모두 열기
19 ms미리 보기 다시 그리기, p95(예산 50 ms)
0.35초20 MP RAW 한 장 현상(중앙값)
21 ms엽서 10장 다시 그리기(예산 100 ms)
10.1 / 초JPEG 내보내기(예산 8 / 초)
1.31 GB메모리 최대치, JPEG와 RAW(상한 2 GB)

이루지 못한 두 목표와 그로써 찾은 것

이 20 MP 파일에서는 첫 실행에서 두 목표를 이루지 못했습니다. 내보내기는 초당 7.6장, 메모리 최대치는 2.14 GB로 2 GB 상한을 넘었습니다. 사진 한 장의 단계별 시간을 재 보니 시간이 어디로 가는지 드러났습니다. 디코딩 약 100 ms, 자르기 2 ms, 인화용 인코딩 203 ms. 인화용 인코더는 두 번째 패스에서 테이블을 최적화하고 있었고, 그 때문에 이미지의 모든 계수를 메모리에 담아 두었습니다. 한 장당 약 160 MB, 동시 6장이면 약 1.5 GB인데, 그래서 파일이 작아지는 것은 고작 0.9%입니다. 표준 테이블이라면 파일을 띠 단위로 쓸 수 있습니다. 138 ms, 렌더링 이미지에 대한 오차는 같고 늘어나는 것은 몇 킬로바이트뿐입니다.

메모리의 일부는 애초에 Fotollection의 것이 아니었습니다. 벤치마크는 썸네일을 모든 코어로 만들었지만, Fotollection은 백그라운드 스레드 두 개를 씁니다. 게다가 자체 미리보기 측정값을 내보내기 중에도 붙들고 있었습니다. Fotollection과 같은 방식으로 재면 내보내기 시작 전에는 0.35~0.39 GB입니다. v0.9.7부터는 동시에 처리하는 장수를 내보내는 사진 중 가장 큰 사진에도 맞추므로(아주 큰 사진이면 줄임), 어떤 크기에서도 최대치가 상한 아래에 머뭅니다. 이 폴더에서는 초당 10.1장, 1.31 GB입니다.

메모리: 사진 5,035장에도 평평하게

Fotollection은 사진 한 장당 몇 바이트만 메모리에 두고, 썸네일은 디스크 캐시에 쓰며, 동시에 다루는 원본 크기 이미지는 메모리 예산에 맞는 만큼뿐입니다. 그래서 여행 사진이 수천 장으로 늘어도 메모리는 평평하게 유지됩니다.

1.45 GB사진 5,035장의 메모리 최대치
1.35 GB사진 95장의 메모리 최대치
53×0.1 GB 더 써서 늘어나는 사진 수
한 번에 처리하는 사진이 5,035장까지 늘어날 때의 메모리 최대치
한 번에 처리하는 사진이 5,035장까지 늘어날 때의 메모리 최대치7

폴더가 커져도 메모리가 늘지 않는 이유

Fotollection이 라이브러리에 담아 두는 것은 사진 한 장당 몇 바이트(5035장에 13 MB)입니다. 썸네일은 메모리에 두지 않고 디스크 캐시에 쓰며, 메모리 속 미리보기는 개수를 제한하고, 원본 크기 사진은 예산에 맞는 장수만 동시에 처리합니다. 화면의 그리드는 가상화되어 있어 보이는 타일만 존재합니다. 테스트에서는 같은 사진 95장을 53번 링크해 5035개 파일의 폴더를 만들었습니다:

95장 5035장
읽기와 EXIF 5 ms, 7 MB 383 ms, 13 MB
400 px 썸네일을 디스크 캐시로 47.8장/초 46.4장/초
내보내기, 동시 6장 18.0장/초 15.4장/초, 실패 0
전체 메모리 최대치 1.35 GB 1.45 GB

사진이 53배가 되어도 메모리는 0.1 GB 늘었을 뿐입니다. 긴 내보내기에서 한 장당 조금 느린 것은 5분 넘게 계속 실행되면서 노트북 프로세서가 지속 부하로 속도를 낮추기 때문입니다.

프린트 품질: 프린트는, 사진 그대로

웹 편집기로 만든 프린트는 흔히 밋밋해 보입니다. 편집기가 색 프로필을 버리고, 사진을 2000 px로 줄이고, 품질 80에 색을 절반으로 저장하기 때문입니다. Fotollection은 프로필을 유지하고 최대 해상도의 4:4:4로 내보냅니다.

0.19색 오차. 눈이 알아채기 시작하는 것은 1부터
4:4:4색 해상도 그대로. 웹 편집기는 절반으로
87 %웹 편집기의 2000 px에서 사라지는 세밀한 디테일
내보내기가 원본에서 무엇을 남기는지, 일반적인 웹 편집기와 비교
내보내기가 원본에서 무엇을 남기는지, 일반적인 웹 편집기와 비교7

웹 편집 도구에서 뽑은 인화물이 밋밋해 보이는 이유

테스트에서는 카메라 사진 20장과 그 Display P3 버전(최근 스마트폰과 Mac의 넓은 색 공간) 5장을 Fotollection의 실제 내보내기로 내보내고, 두 파일을 독립된 디코더로 읽습니다. 색 프로필을 거쳐 CIELAB으로 변환하고 원본 사진과 픽셀 단위로 비교합니다. 일반적인 웹 편집 도구의 내보내기에도 같은 비교를 합니다. 프로필을 지우고, 2000 px로 줄였다가 인화용으로 다시 키우고, 품질 80, 색 정보를 절반(4:2:0)으로 저장한 것입니다.

중앙값 Fotollection, sRGB 웹 편집 도구 Fotollection, Display P3 웹 편집 도구
ΔE2000(색 오차, 1 미만은 보이지 않음) 0.19 1.39 0.31 2.15
PSNR 52.6 dB 37.9 dB 50.8 dB 37.0 dB
남은 채도 100% 99.9% 99.9% 86.8%
남은 디테일 99.8% 13% 100% 18%

밋밋해 보이는 원인은 두 가지입니다. 2000 px로 줄였다가 현상소에서 다시 키우는 과정에서 인화물을 선명하게 보이게 하는 디테일의 87%가 버려집니다. 그리고 색 프로필을 지우면 Display P3 사진을 sRGB로 읽게 되어 채도의 13%를 잃습니다. Fotollection은 프로필을 유지하고(25개 파일 중 25개), 사진의 전체 해상도, 풀 컬러(4:4:4), 품질 95로 내보냅니다(측정 당시의 값. v0.13.0부터 기본값은 90이며, 그래도 눈에 보이는 차이 아래입니다). 조금 큰 오차는 모든 JPEG가 가장 힘들어하는 선명한 경계에서만 나타납니다. 앞으로의 과제: 실제 iPhone의 HEIC 파일과 분광 측색계로 잰 인화물.

Facebook과 Instagram용 사진: 가볍게, 그래도 사진 그대로

Facebook은 모든 사진을 2048 px로 줄이고, 다시 압축하며, 색 프로필을 무시합니다. Share 내보내기는 그 작업을 먼저 제대로 해 두기 때문에, Facebook을 거친 뒤에도 보통 방식보다 원본에 더 가깝게 남습니다.

99.6 %Facebook을 거친 뒤에도 남는 Display P3 사진의 색(보통은 86 %)
2048 pxFacebook이 손대지 않는 크기
½Original size의 절반 크기 파일, 모든 픽셀 유지
Facebook용 사진: Facebook이 다시 압축한 뒤 보는 사람이 보게 되는 것
Facebook용 사진: Facebook이 다시 압축한 뒤 보는 사람이 보게 되는 것7

Facebook이 사진에 하는 일과 그 전에 우리가 하는 일

Facebook은 모든 사진을 최대 2048 px로 줄이고, 품질 약 71, 색 정보를 절반으로 다시 압축하며, 색 프로필을 무시합니다. Share 내보내기는 업로드 전에 이 작업을 제대로 끝내 두므로 Facebook이 줄일 여지가 남지 않습니다. 사진은 프로필을 거쳐 sRGB로 변환되고, 선형 광에서 Lanczos 필터로 크기가 조정되고, 가볍게 샤프닝된 뒤 품질 88로 저장됩니다. 모든 설정은 측정으로 골랐습니다. 더 강한 샤프닝(0.2가 아닌 0.35)은 점수가 떨어졌고, 품질 84나 80은 아낀 것보다 더 많이 잃었습니다.

중앙값 원본 크기 Facebook, 2048 px Instagram, 1080 px
파일 크기(3.08 MB 카메라 JPEG) 1.42 MB 0.51 MB 0.24 MB
이상적인 크기 조정과의 SSIM(1이면 동일) 0.981 0.979 0.982
ΔE2000 0.96 1.27 1.58

Facebook 자체의 재압축을 거친 뒤에도 결과는 일반적인 방법보다 사진에 더 가깝습니다(SSIM 0.965 대 0.961). Display P3 사진은 프로필을 버리지 않고 진짜 sRGB 색으로 변환했기 때문에 86%가 아니라 99.6%의 색을 지킵니다. 크기를 줄인 프리셋이 ΔE 1을 넘는 것은 어느 플랫폼이든 결국 하는 색 정보 절반 줄이기 때문입니다. Original size는 모든 픽셀을 지키면서 파일은 약 절반, ΔE는 1 미만입니다.

카메라 RAW: 있는 그대로 열기

Fotollection은 흔히 쓰는 9개 카메라의 RAW 파일을 변환 없이 그대로 열며, Windows와 Linux에서는 설치할 것도 없습니다. v0.10.0부터는 베이어 센서를 쓰는 모든 카메라에서 원본 크기 이미지를 자체 현상하며, RAW 편집기처럼 카메라 자체의 데이터로 만듭니다. 반면 Adobe DNG Converter는 RAW 파일 하나를 다른 RAW 파일로 바꿀 뿐입니다.12,13,14,15

9–32 msRAW 썸네일, 파일 안의 미리 보기에서
0.3–0.7초Fotollection 자체 현상으로 원본 크기 사진
1.2–1.8초Adobe DNG Converter, 파일 하나를 변환만 하는 데
카메라 RAW: 파일에서 화면까지, 카메라별로 Adobe DNG Converter와 비교
카메라 RAW: 파일에서 화면까지, 카메라별로 Adobe DNG Converter와 비교7
RAW 사진 한 장, 파일에서 프린트까지
RAW 사진 한 장, 파일에서 프린트까지
현상 게이트: 화면 속 사진이 먼저, 백그라운드 작업은 대기
현상 게이트: 화면 속 사진이 먼저, 백그라운드 작업은 대기

센서가 실제로 기록하는 것

카메라 센서는 포토사이트(photosite)라고 불리는 작은 우물 수백만 개가 늘어선 격자입니다. 셔터가 열려 있는 동안 각 포토사이트가 받은 빛을 모아 전하로 바꾸고, 셔터가 닫히면 변환기가 각 전하를 숫자로 바꿉니다. 이 관계는 선형이어서 빛이 두 배면 숫자도 두 배입니다. 사람의 눈은 전혀 선형이 아니며 밝기를 비율로 판단합니다. 그래서 RAW 파일은 현상하기 전까지 어둡고 밋밋해 보입니다.

이 격자를 읽어 내는 센서에는 두 종류가 있습니다:

  • CCD(charge-coupled device, 전하 결합 소자)는 각 포토사이트의 전하를 한 줄씩 칩 가장자리의 증폭기 하나로 보냅니다. 초기 디지털카메라와 많은 초기 중형 디지털 백의 센서로, 이미지는 깨끗하지만 읽기가 느리고 전력 소모가 컸습니다.
  • CMOS는 포토사이트마다 증폭기를 두고 여러 개를 동시에 읽습니다. 더 빠르고, 전력을 적게 쓰고, 싸게 만들 수 있어 이제 거의 모든 카메라와 스마트폰에 쓰입니다. 많은 CMOS 센서가 줄을 차례로 읽기 때문에 전자 셔터로 찍은 빠른 피사체가 비스듬히 휘어질 수 있으며(이것이 롤링 셔터), 훨씬 빠르게 읽는 적층형(stacked) 센서에서는 왜곡이 적습니다.

이 숫자는 JPEG보다 훨씬 많은 단계를 가집니다. 카메라는 포토사이트마다 12 또는 14비트, 즉 4096 또는 16,384단계를 기록하고, JPEG가 지키는 것은 8비트, 256단계입니다. 이 여분의 단계 덕분에 섀도를 끌어올리거나 밝은 하늘을 눌러도 톤이 끊기지 않습니다. 그리고 빛이 없다고 0인 것도 아닙니다. 모든 센서는 검정 근처의 노이즈가 잘려 나가지 않도록 작은 오프셋, 즉 블랙 레벨을 더합니다. Nikon D750 샘플에서는 검정이 600, 센서가 기록할 수 있는 최댓값인 화이트 레벨이 15,520입니다. 모든 RAW 현상의 첫 작업은 이 두 숫자를 0과 1에 맞추는 것이며, 카메라에 따라 컬러 필터 위치마다 블랙 레벨이 다르기 때문에 위치마다 따로 합니다.

색은 각 포토사이트 위의 필터에서 나온다

포토사이트가 재는 것은 도달한 빛의 양뿐이며 색은 재지 않습니다. 색을 보기 위해 센서는 컬러 필터 배열로 덮여 있습니다. 포토사이트마다 위에 작은 빨강, 초록, 파랑 필터가 있어, 각각 스펙트럼의 일부만 셉니다.

  • Bayer 배열은 1976년 Kodak의 Bryce Bayer가 특허를 낸 것으로, 2 × 2 정사각형을 반복합니다. 빨강 1, 초록 2, 파랑 1입니다. 포토사이트의 절반이 초록인 것은 사람의 눈이 디테일 대부분을 스펙트럼의 가운데에서 느끼기 때문이며, 초록이 선명도의 대부분을 맡습니다. 거의 모든 카메라가 이 배열을 네 방향(RGGB, BGGR, GRBG, GBRG) 중 하나로 쓰며, 그 방향은 파일에 적혀 있어야 합니다.
  • X-Trans는 Fujifilm이 2012년부터 쓰는 배열로, 6 × 6 정사각형을 반복하며 모든 행과 열에 빨강, 초록, 파랑이 있습니다. 불규칙한 배치 덕분에 촘촘한 반복 무늬에 색 모아레가 덜 생기고, Fujifilm은 많은 센서에 있는 로우패스 필터를 뺄 수 있습니다. 그 대신 재구성은 더 어려워집니다.
  • 그 밖의 방식: 흑백 센서에는 필터가 전혀 없어 모든 포토사이트가 디테일을 전부 담습니다(Leica의 Monochrom). Sigma의 Foveon은 실리콘의 깊이마다 색을 흡수하는 층 세 개를 겹칩니다. 많은 스마트폰은 같은 색 포토사이트 네 개를 묶어(Quad Bayer) 어두운 곳에서는 하나로 읽습니다.

즉 24 MP Bayer 센서는 2400만 개의 숫자를 기록하고, 각각은 한 가지 색뿐입니다. 모든 픽셀에서 세 가지 색 중 두 가지가 빠져 있습니다. 이 모자이크에서 이미지를 만드는 것이 디모자이크의 일이며, 아래에서 설명합니다.

RAW 파일 안에 든 것

JPEG는 완성된 이미지로, 카메라가 이미 모든 판단을 내렸습니다. RAW 파일은 그 판단 이전의 센서 숫자를, 나중에 판단하는 데 필요한 것들과 함께 저장합니다:

  • 샘플 자체(포토사이트마다 하나)와, 각각이 어떤 컬러 필터 아래에 있었는지
  • 블랙 레벨과 화이트 레벨
  • 유효 영역(빛을 받은 포토사이트. 둘레의 몇 행과 몇 열은 검정을 재기 위해 일부러 가려져 있습니다)과 카메라의 기본 자르기
  • 촬영할 때 카메라가 고른 화이트 밸런스
  • 이 센서 고유의 빨강, 초록, 파랑이 사람이 보는 색과 어떻게 대응하는지 나타내는 컬러 매트릭스
  • 카메라가 자기 색과 톤으로 만든 JPEG 미리보기와 EXIF 데이터

제조사마다 고유한 형식이 있으며, 대부분 TIFF 기반이고 일부는 공개되지 않았습니다. CR2와 CR3(Canon), NEF(Nikon), ARW(Sony), RW2(Panasonic), ORF(Olympus), RAF(Fujifilm). DNG는 Adobe가 공개한 형식(버전 1.7)으로, Ricoh, Leica, Pentax와 많은 스마트폰이 씁니다. 이 페이지는 그 규칙을 따릅니다.

Fotollection은 DNG를 사양을 보고 직접 작성한 리더로 읽고, 다른 형식은 Fotollection에 내장한 LGPL 라이브러리 rawler로 풉니다. 그리드의 썸네일은 센서 데이터를 전혀 건드리지 않고 파일 안의 미리보기에서 9~32 ms에 만들어집니다. 그래서 RAW 폴더도 JPEG 폴더와 같은 속도로 열립니다.

디모자이크: 빠진 두 색 계산하기

각 픽셀에서 빠진 두 색을 주변에서 재구성하는 것을 디모자이크라고 하며, RAW 사진의 선명함과 깨끗함을 다른 어떤 단계보다 크게 좌우합니다. 모든 방법이 같은 딜레마를 안고 있습니다. 주변을 평균하면 평평한 부분에서는 안전하지만, 경계를 넘으면 서로 다른 두 면이 섞입니다. 어느 이웃끼리 같은 대상에 속하는지 가려내는 것이 실력입니다.

  • 바이리니어는 각 색의 가장 가까운 포토사이트를 단순히 평균합니다. 모든 방법의 비교 기준이며, 부드럽고, 빨강, 초록, 파랑을 조금씩 다른 위치에서 평균하기 때문에 선명한 경계를 따라 색 번짐이 생깁니다.
  • Malvar–He–Cutler(2004년)는 이 평균에서 출발해, 고정된 5 × 5 필터로 그 포토사이트가 본 색의 디테일을 이용해 보정합니다. 더 선명하면서도 매우 빠릅니다. Fotollection은 v0.10.0까지 이 방법으로 현상했습니다.
  • PPG(patterned pixel grouping)는 먼저 이미지 변화가 가장 적은 방향을 판단하고 그 방향으로만 보간합니다. rawler가 쓰는 방법으로, v0.10.0까지는 Windows판과 Linux판 Fotollection에서도 대부분의 형식에 썼습니다.
  • RCD(ratio corrected demosaicing, Luis Sanz Rodríguez)는 색의 차이가 아니라 비율로 처리해 밝은 부분에서도 어두운 부분에서도 잘 무너지지 않고, 디테일에서 오류가 적은 것으로 알려져 있습니다. darktable과 RawTherapee도 갖추고 있습니다.
  • Markesteijn은 Frank Markesteijn의 이름을 딴 X-Trans용 방법으로, 1패스 또는 더 느리지만 깨끗한 3패스로 동작합니다.
  • v0.10.0 이후 Fotollection의 디모자이크는 방향 판단을 RCD에서 가져오고, 초록을 양쪽에서 추정해 그 점 자신의 색으로 보정하며(Hamilton과 Adams의 방법), 각 쪽의 변화 크기로 가중치를 줍니다. 처음에는 RCD 자체의 비율 단계를 구현했지만 테스트 차트에서 성적이 나빠서, 이긴 쪽을 자체 이름으로 출시하고 있습니다.

방법이 추측을 잘못하면 전형적인 네 가지 형태로 나타납니다:

  • 지퍼: 선명한 경계를 따라 밝고 어두운 픽셀이 번갈아 늘어섬. 방법이 경계 양쪽에서 이웃을 가져왔을 때
  • 미로: 평평한 부분에 나타나는 자잘한 벌레 먹은 듯한 무늬. Bayer 정사각형의 두 초록이 완전히 같은 값을 읽지 않을 때(색이 다른 인접한 행에 있어 많은 센서에서 1~2% 어긋납니다)
  • 위색: 실제로는 회색인 디테일, 예를 들어 천, 머리카락, 벽돌 벽, 먼 울타리에 나타나는 색 점이나 번짐
  • 모아레: 컬러 필터가 표본화할 수 있는 것보다 촘촘한, 아주 미세한 반복 무늬에 나타나는 색 물결

평가 방법. 사람의 눈은 선명해 보이는 결과에 속기 쉬우므로, 모든 방법을 정답이 정확히 알려진 이미지로 채점합니다. 컴퓨터가 768 px 테스트 차트 다섯 장을 그립니다. 존 플레이트(바깥으로 갈수록 촘촘해져 초록 포토사이트가 지킬 수 있는 가장 미세한 디테일에 이르는 동심원), 스포크 72개의 지멘스 스타, 회색 위에 세 방향으로 놓은 채도 높은 띠, 매끄러운 그라데이션, 그리고 두 초록이 2% 어긋난 평평한 회색입니다. 각각을 Bayer 센서가 기록할 형태로 바꾸고, 디모자이크한 뒤 원본 이미지와 비교합니다. PSNR은 전체 오차를 데시벨로 잽니다(클수록 좋고, 6 dB마다 오차가 절반). 위색은 회색 차트에 나타나는 색의 평균, 경계 오차는 경계에서 2 px 이내의 평균 오차입니다.

차트(768 px) 바이리니어 Malvar(v0.10.0까지의 방식) v0.10.0 이후의 방식
존 플레이트: PSNR, 클수록 좋음 13.0 dB 17.3 dB 16.5 dB
존 플레이트: 위색, 작을수록 좋음 65.9 43.0 18.7
지멘스 스타: PSNR 21.3 dB 25.2 dB 37.9 dB
지멘스 스타: 위색 9.4 8.4 0.16
채도 높은 띠: 경계를 따른 오차, 작을수록 좋음 11.6 21.6 10.5
매끄러운 그라데이션: PSNR 78.9 dB 77.5 dB 78.4 dB
초록이 어긋난 평평한 회색: 미로, 작을수록 좋음 0.38 0.38 0
고착 픽셀이 있는 텍스처: 10,000개당 남은 수, 작을수록 좋음 35.8 66.5 0

Malvar는 논문대로 미세한 회색 디테일에서 바이리니어보다 약 4 dB 낫지만, 강한 색끼리의 경계에서는 뒤집니다. 보정이 한 색의 디테일을 다른 색에서 빌려 오고 색이 함께 변한다고 가정하기 때문인데, 회색 벽의 빨간 간판은 그렇지 않습니다. 둘 다 미로를 없애지 못합니다. 미로는 디모자이크의 문제가 아니라 두 초록의 차이여서 그 전에 맞춰 두어야 하기 때문입니다. v0.10.0부터의 처리 흐름은 이런 구멍을 막습니다. 각 점이 아직 측정한 값만 가지고 있을 때 고착 픽셀과 초록의 어긋남을 고치고, 방향에 따른 디모자이크로 색을 재구성하고, 색 차이에 작은 미디언을 걸어 남은 위색을 없앱니다. 테스트 차트에서 모든 항목을 이겼고, 예외는 존 플레이트 전체의 PSNR뿐으로, 모든 방법이 앨리어싱이 생기는 가장 미세한 디테일 근처에서 Malvar보다 0.8 dB 낮습니다. 그래도 위색은 그곳에서도 절반이 됩니다. 실제 파일 9개에서는 모든 Bayer 카메라의 현상이 카메라 자체 JPEG에 같거나 더 가까워졌고, 24 MP에 약 180 ms가 걸립니다. Malvar의 40 ms에 비해 한 장당 몇십 분의 1초 더 걸리지만, 그만큼 디테일이 깨끗한 인화물이 됩니다.

카메라의 색에서 내 색으로

카메라의 빨강, 초록, 파랑은 화면의 색과 같지 않습니다. 센서마다 필터 색소가 다르고, 사람 눈의 원뿔세포와는 다른 방식으로 겹칩니다. 파일 안의 컬러 매트릭스가 카메라의 색을 CIE XYZ(1931년에 정한 사람 색각의 표준 모델)로 바꾸고, 거기서 많은 화면과 현상소의 색 공간인 sRGB로 바꿉니다.

  • 처음은 화이트 밸런스입니다. 빨강과 파랑에 게인을 걸어 장면에서 흰 것이 중립으로 보이게 합니다. 카메라는 고른 게인을 기록해 두며, Fotollection은 이를 디모자이크 전에 적용하므로 위의 방법이 쓰는 색 차이가 작게 유지됩니다.
  • DNG에는 보통 매트릭스가 두 개 있습니다. 하나는 따뜻한 백열등, 다른 하나는 주광에서 잰 것입니다. 사진에 맞는 것은 그 사이이며, 현상은 화이트 밸런스에서 촬영 당시의 빛을 색온도로 계산해 둘을 섞습니다. Fotollection은 다른 형식에서도 rawler가 카메라 모델마다 알고 있는 매트릭스로 같은 일을 합니다.
  • 이 모든 것은 어떤 커브보다도 앞서, 센서 자체의 스케일, 즉 선형 광에서 합니다. 색 혼합, 스케일링, 크기 조정은 선형 광에서 하면 물리적으로 맞는 결과가 되고, 커브 뒤에서 하면 경계가 어두워지고 색이 어긋납니다.

카메라 본래의 룩. 카메라 자체의 JPEG는 중립이 아닙니다. 모든 제조사가 고유한 대비, 색, 피부 톤을 더하며, 그 룩은 사람들이 브랜드를 고르는 이유의 하나입니다. v0.10.0부터 RAW 사진은 중립 표시로 열립니다. 센서의 매트릭스에 충실하고, 렌즈의 주변부 광량 저하와 카메라가 고른 노출을 반영한 것입니다. Like the camera’s JPEG는 RAW 사진의 RAW colour 카드에 있으며, 클릭 한 번으로 한 장에도, 모든 RAW에 한꺼번에도 적용할 수 있습니다. (v0.10.0까지는 모든 RAW를 카메라의 JPEG에 맞췄습니다. 그때 저장한 프로젝트는 그 룩을 유지합니다.) 이 옵션은 커브와 매트릭스, 또는 채널별 커브라는 두 가지 방식으로 카메라의 JPEG에 맞추고, 그 파일에서 더 가까워진 쪽을 남깁니다. Nikon D750에서는 차이가 절반이 되어 ΔE2000이 2.26에서 1.16이 되었습니다. 그리드의 썸네일은 Lightroom과 마찬가지로 카메라 자체의 미리보기를 씁니다.

톤: 선형 숫자에서 이미지로

선형 숫자는 화면에서 어둡고 색이 바래 보입니다. 빛이 두 배가 되면 센서는 두 배의 숫자로 기록하지만, 우리 눈에는 한 단계 밝아진 것으로만 보이기 때문입니다. 톤 커브가 센서의 스케일을 이미지로 바꿉니다. 중간 회색의 위치를 정하고, 섀도를 끌어올리고, 하이라이트를 단번에 자르지 않고 부드럽게 굴리며, 이미지의 대비를 정합니다. 그 뒤 이미지는 sRGB 커브(흔히 말하는 “감마”)로 저장되어, JPEG의 256단계 중 많은 부분을 눈이 단계 차이에 가장 민감한 섀도에 배정합니다.

카메라가 JPEG에서 하는 보정 가운데 두 가지는 RAW 데이터에 들어 있지 않으며, 둘 다 인화물에 영향을 줍니다:

  • 주변부 광량 저하: 모든 렌즈는 모서리로 갈수록 어두워집니다. Fotollection은 카메라가 모서리를 얼마나 밝혔는지를 카메라 자체의 미리보기에서 방사 방향 게인으로 잽니다. 처음 DNG 현상을 카메라의 JPEG와 비교했을 때 가운데는 약 4 L* 너무 밝고, 모서리는 1.5 너무 어두웠습니다. 방사 방향 게인으로 차이는 ΔE 3.8에서 2.67로 줄었고, 사진의 모든 부분이 ±0.5 L* 안에 들어왔습니다.
  • 왜곡: 렌즈의 약한 술통형 또는 실패형 왜곡입니다. 마이크로 포서드 카메라(Panasonic, Olympus)는 카메라에서 보정하는 것을 전제로 설계되어, 파일에 그 방법이 기록되어 있습니다. Mac에서는 이 파일들을 보정을 적용하는 macOS가 현상하며, 자체 현상에서의 보정은 계획 중입니다(FR-085).

Fotollection의 RAW 현상, 단계별로

인화 미리보기, 확대, 내보내기 뒤에 있는 전체 현상에서는:

  1. 판별: 형식은 파일 이름이 아니라 앞부분의 바이트로 판별하므로, 이름을 바꾼 파일이나 평범한 TIFF처럼 보이는 RAW도 제대로 읽습니다.
  2. 읽기: 센서의 숫자. DNG는 자체 리더로, 다른 형식은 rawler로 풉니다. 너무 크거나 손상된 파일은 픽셀 하나도 디코딩하기 전에 오류 코드와 함께 거부합니다.
  3. 레벨: 검정을 0, 흰색을 1로. 컬러 필터 위치마다, 유효 영역의 모서리부터 세어서.
  4. 화이트 밸런스, 이어서 디모자이크: 먼저 고착 픽셀과 초록의 어긋남, 다음으로 방향에 따른 디모자이크, 마지막으로 위색 미디언(X-Trans용 Markesteijn은 v0.15.0에 나올 예정).
  5. 색: 카메라의 매트릭스를 촬영 당시의 빛에 맞춰 섞어, 선형 광에서.
  6. 톤과 룩: 카메라의 미리보기에 맞추며, 주변부 광량 저하도 포함해서.
  7. 여기부터는 RAW 사진도 다른 사진과 같습니다. 자르기, 날짜, 프레임, 인화 크기, 색 프로필. 전체 해상도, 4:4:4, 품질 95로 내보냅니다.

몇 가지 규칙은 처음부터 끝까지 지켜집니다. 현상은 한 번에 하나만, 모든 프로세서 코어에 나눠 실행하고, 창 자체의 스레드에서는 절대 실행하지 않으므로, 30 MP 사진을 현상하는 중에도 Fotollection은 반응합니다. 내보내기는 항상 프로세서에서 하므로 인화물은 어느 컴퓨터에서나 같습니다. 그래픽카드가 빠르게 하는 것은 편집 중에 보이는 것뿐입니다. 그리고 코드는 우리 자신의 것으로, 다른 프로젝트에서 복사하지 않고 공개된 사양과 논문을 보고 작성해 검증합니다. 위의 합성 차트, 9개 기종의 RAW 파일 9개(CC0, raw.pixls.us 제공), 그리고 파일을 일부러 잘라 내거나 망가뜨려, 손상된 파일이 충돌이 아니라 오류가 되는지 확인합니다.

v0.10.0부터: 모든 Bayer 카메라에 자체 현상. rawler는 파일을 풀기만 하고, 나머지는 Fotollection이 합니다. 샘플 파일 9개의 전체 현상, 3회의 중앙값, 같은 노트북에서. 더 깨끗한 디모자이크를 갖춘 우리 현상과 rawler의 더 단순한 방식, 그리고 macOS의 비교입니다:

카메라(형식) Fotollection 자체 rawler macOS
Panasonic GX9 (RW2, 20 MP) 280 ms 216 ms 436 ms
Panasonic S5 (RW2, 24 MP) 442 ms 301 ms 1044 ms
Olympus E-M10 III (ORF, 16 MP) 308 ms 364 ms 1164 ms
Sony A7 III (ARW, 24 MP) 372 ms 241 ms 488 ms
Canon R10 (CR3, 24 MP) 494 ms 360 ms 1647 ms
Ricoh GR III (DNG, 24 MP) 523 ms 650 ms —
Nikon D750 (NEF, 24 MP) 502 ms 402 ms 412 ms
Canon 5D Mark IV (CR2, 31 MP) 691 ms 565 ms 418 ms
Fujifilm X-T3 (RAF, 26 MP, X-Trans) 지원 예정 524 ms 1339 ms

우리 현상은 더 깨끗한 디모자이크와 맞춘 색 때문에 rawler보다 0.1~0.25초 더 걸리지만, 대부분의 카메라에서 macOS보다 빠릅니다. 현상은 한 장에 한 번뿐이고, 그 뒤로는 슬라이더가 보관해 둔 사본을 4~11 ms에 다시 처리합니다. Mac에서는 Panasonic과 Olympus 파일이, 자체 현상이 왜곡을 보정할 수 있게 될 때까지 렌즈 보정 때문에 macOS에 남습니다. S5의 회색 패치는 rawler를 거칠 때보다 더 중립이 됩니다(색 어긋남 1.42 대 2.43, 0이 완전한 회색). 다음은 Markesteijn을 쓰는 Fujifilm X-Trans, 그다음은 프로세서의 결과를 기준으로 삼는 그래픽카드 미리보기 현상입니다.

베스트 샷 추천: 사람의 선택과 비교

실제 사진 95장을 손으로 22개 장면으로 나누고, 뚜렷한 베스트가 있는 장면에서는 그 사진을 골랐습니다. 그런 다음 Fotollection의 그룹과 추천을 이 선택과 비교했습니다.

6 / 6뚜렷한 베스트가 있는 장면에서 납득할 만한 추천
15 / 22찾아낸 장면. 두 장면을 섞은 적은 없음
17 ms사진 한 장 분석, 얼굴이 있으면 28 ms
베스트 샷 추천, 사람이 직접 고른 사진과 비교
베스트 샷 추천, 사람이 직접 고른 사진과 비교7

제안이 만들어지는 방식과 그 평가 방법

Fotollection은 먼저 "순간"을 찾습니다. 사진을 촬영 시각 순으로 1초 미만의 정밀도로 정렬하고, 간격이 2초 또는 평소 간격의 4배를 넘을 때, 카메라나 렌즈가 바뀔 때, 촬영 장소가 30 m 이상 떨어질 때 새 순간을 시작합니다. 또한 사진마다 작은 시각적 지문(명암의 배치와 색의 섞임)을 만들고, 바로 앞 사진과 아직 비슷할 때만 그 순간에 더합니다. 옆으로 한 걸음 옮기거나 초점 거리로 설명되는 줌은 허용합니다.

다음으로 한 순간 안에서 축소본으로 각 사진을 측정합니다. 피사체의 선명도, 손떨림, 노출(하이라이트 날림, 섀도 뭉개짐, 밝기), 노이즈, 그리고 얼굴이 있다면 눈을 뜨고 있는지, 얼굴이 카메라를 향하는지. 모든 지표는 같은 순간의 다른 사진과만 비교하며 가중치를 둡니다(피사체 선명도 35%, 뜬 눈 20%, 손떨림 15%, 노출 15%, 하이라이트 날림 10%, 나머지는 그 이하). 최소 차이도 두기 때문에 인화물에서 보이지 않는 차이가 결정을 좌우하는 일은 없습니다. 제안에는 이유가 함께 표시되고, 아무것도 삭제되지 않으며, 모든 처리가 내 컴퓨터에서 한 장에 17 ms 미만, 얼굴이 있으면 28 ms 미만으로 실행됩니다.

정직하게 평가하기 위해 실제 사진 95장을 손으로 22개 순간으로 나누고, 분명한 베스트가 있는 6개 순간에서는 남겨야 할 사진을 정했습니다. 모든 개선은 이것과 비교해 측정합니다:

단계 찾은 순간(22개 중) 잘못된 병합 타당한 선택
이미지 지문만 3 0 2개 중 2
+ 배치와 색 13 0 4개 중 3
+ 초점 거리로 본 줌 15 0 6개 중 5
+ 공정한 선명도와 가려진 얼굴 15 0 6개 중 6

서로 다른 두 순간이 같은 그룹이 되는 일은 없습니다. 남는 두 그룹은 손으로 "판단하기 어려움"이라고 표시한 쌍입니다. 아직 놓치는 순간은 포즈나 구도가 크게 바뀌는 경우로, 예를 들어 음식을 반대편에서도 찍은 경우입니다.

수치 뒤의 용어

사진과 프린트의 전문 용어를, 친구에게 설명하듯이.

ΔE(델타 E)란?16

ΔE는 두 색이 사람의 눈에 얼마나 다르게 보이는지를, 우리가 보는 방식에 맞춘 색 공간(CIELAB, 2000년 공식)에서 계산한 값입니다. 0은 똑같다는 뜻입니다. 약 1은 훈련된 눈이 나란히 놓고 알아챌 수 있는 가장 작은 차이이고, 2–3은 대부분의 사람에게 보이며, 5를 넘으면 다른 색으로 보입니다. Fotollection의 프린트용 내보내기는 평균 0.19입니다.

SSIM이란?17

SSIM(구조적 유사도 지수)은 픽셀 하나하나가 아니라 두 이미지의 형태와 질감을 비교합니다. 흐림이나 블록 모양의 압축 흔적을 우리가 알아채는 방식에 더 가깝습니다. 1은 똑같다는 뜻이고, 약 0.98을 넘으면 대부분의 사람은 확대하지 않고는 둘을 구별하지 못합니다.

JPEG는 몇 가지 색을 담을 수 있나요?6,18

JPEG는 빨강, 초록, 파랑에 각각 8비트, 즉 256단계씩, 약 1670만 색을 담습니다. 사진관도 이것으로 프린트합니다. 카메라 RAW 파일은 12–14비트를 담고 최근 iPhone은 10비트 HEIC로도 저장할 수 있어 편집할 때 도움이 됩니다. 완성된 프린트라면, 잘 만든 8비트 JPEG에서 톤 사이에 계단이 보이지 않습니다.

JPG와 JPEG의 차이는? PNG를 써야 하나요?

JPG와 JPEG는 같은 형식입니다. 옛 Windows가 세 글자 확장자만 허용했을 뿐입니다. PNG는 무손실이라 아무것도 버려지지 않지만, PNG로 저장한 사진은 흔히 3–5배 커지고, 대부분의 키오스크와 사진관은 JPEG를 받습니다. Fotollection이 프린트용으로 내보내는, 품질 90 이상에 색 해상도가 그대로인(4:4:4) JPEG라면 종이 위에서는 원본과 구별되지 않습니다.

4:4:4와 4:2:0이란?

우리 눈은 디테일을 주로 밝기로 보고 색으로는 덜 봅니다. 그래서 JPEG는 색을 낮은 해상도로 저장할 수 있습니다. 4:4:4는 색 해상도를 모두 유지하고, 4:2:0은 4분의 1만 유지합니다. 파일은 작아지지만 빨간 글씨나 나뭇잎 너머의 파란 하늘 같은 색의 경계가 번집니다. 프린트에는 4:4:4가 어울리고, SNS는 어차피 모든 것을 4:2:0으로 다시 압축합니다.

sRGB, Display P3, Adobe RGB와 색 프로필19,20,21

색 프로필은 파일 속 숫자가 무엇을 뜻하는지 소프트웨어에 알려 줍니다. sRGB는 웹에서 쓰는 전형적인 색 범위입니다. iPhone과 최근 카메라가 쓰는 Display P3는 특히 빨강과 초록에서 약 25 % 더 많은 색을 표현합니다. P3 사진이 프로필을 잃으면 그 숫자가 sRGB로 읽혀 색이 바래 보입니다. 우리가 측정한 13 % 의 채도 손실이 바로 이것입니다. 일부 카메라가 프린트용으로 제공하는 Adobe RGB도 sRGB보다 넓으며, 주로 초록과 청록에서 차이가 납니다. Fotollection은 프린트용으로는 사진의 프로필을 무엇이든 그대로 유지하고, SNS용으로는 sRGB로 제대로 변환합니다.

프린트에는 몇 DPI가 필요한가요?

DPI는 용지 1인치에 놓이는 픽셀 수입니다. 300 DPI면 가까이서 봐도 선명하고, 팔을 뻗은 거리라면 150–200 DPI로 충분합니다. 10 × 15 cm 프린트는 300 DPI에서 1800 × 1200 픽셀이 필요하므로, 스마트폰이나 카메라 사진이면 어떤 것이든 충분합니다. 앱의 크기 안내가 사진마다 얼마나 크게 프린트할 수 있는지 알려 줍니다.

Facebook에서 사진이 덜 예뻐 보이는 이유는?

Facebook은 모든 사진을 최대 2048 px로 줄이고, 더 낮은 품질과 절반의 색 해상도로 다시 압축하며, 색 프로필을 버립니다. 너무 크게 올린 사진은 나와 Facebook이 한 번씩, 두 번 크기가 바뀝니다. 처음부터 2048 px, sRGB, 가볍게 샤프닝해서 보내면 Facebook은 한 번만 다시 압축하고, 색도 처음부터 올바릅니다.

측정을 직접 다시 실행하기

모든 것을 내 사진으로 재현할 수 있습니다. 스크립트는 사진을 업로드하거나 복사하지 않고, 남는 것은 수치뿐입니다. 모든 실행을 담은 전체 표는 RESULT.md에 있습니다.

bench/run.sh ~/Pictures/some-folder 3
uv run bench/quality/audit.py ~/Pictures/some-folder /tmp/out
uv run bench/quality/share_audit.py ~/Pictures/some-folder /tmp/share

GitHub에서 RESULT.md 읽기 홈페이지로 돌아가기

  1. 1. SIMD(single instruction, multiple data)는 프로세서가 많은 값을 한 번에 처리하는 방식입니다. 명령어 하나가 넓은 벡터 레지스터에 나란히 놓인 여러 수, 예를 들어 많은 픽셀의 빨강·초록·파랑에 동시에 작용합니다. Intel과 AMD 프로세서에서는 SSE와 AVX로, Apple 실리콘 등 Arm 프로세서에서는 NEON으로 제공됩니다. Intel, AMD, Arm은 각 소유자의 상표입니다.
  2. 2. 단위: px는 픽셀로, 이미지를 이루는 점 하나입니다. MP(메가픽셀)는 100만 픽셀로, 20 MP 사진은 약 5472 × 3648 px입니다. ms는 밀리초로, 1초의 1000분의 1입니다. MB와 GB는 메가바이트와 기가바이트입니다. RAM(랜덤 액세스 메모리)은 컴퓨터의 작업용 메모리입니다.
  3. 3. Rust 및 Rust 로고는 Rust Foundation의 상표입니다. Fotollection의 코어는 Rust로 작성되어 컴퓨터에서 직접 실행됩니다.
  4. 4. EXIF(Exchangeable Image File Format)는 일본의 JEITA와 CIPA가 관리하는 표준으로, 카메라가 사진마다 기록하는 정보를 정합니다. 카메라와 렌즈, 날짜와 시간, 노출, 흔히 GPS 위치, 그리고 작은 내장 썸네일입니다.
  5. 5. RAW 파일에는 카메라가 이미지로 바꾸기 전에 센서가 기록한 것이 담겨 있어서, 색, 밝기, 디테일을 필름을 현상하듯 나중에 정할 수 있습니다. 제조사마다 고유한 형식이 있으며(Canon은 CR3, Nikon은 NEF, Sony는 ARW, Panasonic은 RW2 등), DNG(Digital Negative)는 Adobe가 공개한 개방형 RAW 형식입니다.
  6. 6. JPEG는 Joint Photographic Experts Group의 이미지 형식으로, ISO/IEC 10918-1 및 ITU-T T.81로 표준화되었습니다.
  7. 7. 모든 차트: 수치는 참고용으로, 평범한 노트북(Apple M3, 16 GB)에서 측정했습니다. 실제 값은 사용하는 컴퓨터에 따라 다릅니다.
  8. 8. Adobe, Lightroom, Lightroom Classic은 미국 및 기타 국가에서 Adobe Inc.의 상표입니다. Fotollection은 Adobe와 제휴하거나 Adobe의 승인을 받지 않았으며, Lightroom 사용자가 이미 아는 단축키와 레이아웃을 따릅니다. Lightroom 로고는 문자 로고로서 퍼블릭 도메인인 Wikimedia Commons의 것을 사용했습니다.
  9. 9. 앱의 창은 Tauri로 만들었고, 운영체제 자체의 웹 뷰가 그립니다. macOS에서는 WebKit(WKWebView), Windows에서는 Microsoft Edge WebView2, Linux에서는 WebKit의 GTK 포트인 WebKitGTK입니다. Tauri는 Commons Conservancy 내 Tauri Programme의 프로젝트이고, WebKit은 Apple Inc.의 상표, GTK는 GNOME Foundation의 프로젝트, Microsoft Edge와 WebView2는 Microsoft Corporation의 상표입니다. 브라우저 비교는 같은 작업을 Google Chrome의 바탕인 오픈 소스 프로젝트 헤드리스 Chromium 156에서, 프로세서 코어마다 Web Worker 하나를 써서 실행했습니다.
  10. 10. 프라하 폴더는 만든 사람의 것으로 공개하지 않습니다(© @hoangphi01, 무단 전재 금지). bench/trip.sh와 그 JPEG에 대한 measure_folder를 각각 3회 실행한 중앙값으로, Apple M3·16 GB에서 다른 앱을 연 상태로, 2026년 11월 4일, v0.9.7의 내보내기로 측정했습니다. 비교하려면 내 폴더로 실행해 보세요.
  11. 11. p50과 p95는 백분위수입니다. p50(중앙값)은 실행의 절반이 그 안에 끝난 시간이고, p95는 100번 중 95번이 그 안에 끝난 시간으로, 평균이 가리는 느린 경우를 보여 줍니다.
  12. 12. 이 페이지를 위해 Adobe DNG Converter를 실행하지는 않았습니다. 수치는 외부 추정치(최신 하드웨어에서 CR3 파일 1,000개에 20–30분, 컴퓨터 사양은 밝히지 않음)로, convertintomp4.com의 RAW에서 DNG로 일괄 변환하는 방법에 관한 블로그 글에서 가져왔습니다. Adobe는 Adobe Inc.의 등록 상표입니다.
  13. 13. CMOS와 CCD는 두 종류의 이미지 센서로, 빛을 전하로 바꾸는 감광 셀의 격자입니다. 오늘날 거의 모든 카메라와 스마트폰이 CMOS(상보형 금속 산화막 반도체)를 쓰며, CCD(전하 결합 소자)는 이전 카메라에서 흔했습니다.
  14. 14. PSNR(최대 신호 대 잡음비)은 두 이미지를 픽셀마다 비교해 그 차이를 데시벨로 나타냅니다. 높을수록 가깝고, 약 40 dB를 넘으면 차이가 거의 보이지 않습니다.
  15. 15. TIFF(Tagged Image File Format)는 유연한 이미지 형식으로, 지금은 Adobe가 관리합니다. DNG를 비롯한 많은 RAW 형식이 그 구조를 바탕으로 합니다.
  16. 16. ΔE2000(CIEDE2000)은 국제조명위원회(CIE)의 색차 공식으로, ISO/CIE 11664-6으로 표준화되었습니다. 계산에 쓰는 CIELAB 색 공간은 ISO/CIE 11664-4입니다.
  17. 17. SSIM은 Zhou Wang, Alan C. Bovik, Hamid R. Sheikh, Eero P. Simoncelli가 논문 ‘Image quality assessment: from error visibility to structural similarity’(IEEE Transactions on Image Processing, 13(4), 2004)에서 제안했습니다.
  18. 18. HEIF(High Efficiency Image File Format)는 ISO/IEC 23008-12의 이미지 형식이고, HEIC는 이를 HEVC(H.265)로 압축한 것으로 iPhone이 기본으로 사진을 저장하는 형식입니다. HEIC 사진은 비슷한 품질의 JPEG의 약 절반 크기입니다.
  19. 19. sRGB는 1996년 HP와 Microsoft가 만들었고, IEC 61966-2-1로 표준화되었습니다.
  20. 20. Display P3는 Apple Inc.가 정의한 색 공간으로, 영화 업계(SMPTE)의 DCI-P3 색 공간을 바탕으로 합니다.
  21. 21. Adobe RGB (1998)는 Adobe Inc.가 사양을 정한 색 공간입니다. Adobe는 Adobe Inc.의 등록 상표입니다.

스크린샷 속 서울 사진은 @9adox(Fujifilm XF10)와 @imyourctus(Sony ZV-1)가 촬영했습니다: © 각 작가, 무단 전재 금지. 앱의 라이선스에 포함되지 않으며 재사용할 수 없습니다. 스크린샷 속 프라하 사진(트램, 거리, 블타바강)은 @hoangphi01이 2026년 11월 Lumix GX9로 촬영한 것입니다: © @hoangphi01, 무단 전재 금지. 앱의 라이선스에 포함되지 않으며 재사용할 수 없습니다. 그 밖의 데모 사진은 Wikimedia Commons의 퍼블릭 도메인(CC0)으로, 작가는 Dktue(7장), 프랑스 파리의 Pierre Blaché(2장), Kate Branch(1장)입니다. 프린트 바구니와 베스트 샷 스크린샷의 고양이도 @hoangphi01이 GX9로 촬영했으며, 무단 전재 금지입니다. 옆의 더 흐리고, 흔들리고, 어두운 사본은 베스트 샷이 어떻게 골라지는지 보여 주려고 이 한 장에서 만들었습니다. 모든 파일과 그 페이지, 체크섬.

RAW 측정에는 raw.pixls.us의 퍼블릭 도메인(CC0) 샘플을 형식마다 하나씩, 모두 9개 사용합니다. scripts/fetch-raw-samples.py가 다운로드하고 검증합니다.

이 사이트에서 언급한 RAW 형식은 그것을 정한 카메라 제조사의 것입니다: RW2(Panasonic Holdings Corporation), CR2와 CR3(Canon Inc.), NEF(Nikon Corporation), ARW(Sony Group Corporation), RAF(FUJIFILM Corporation), ORF(OM Digital Solutions Corporation, 옛 Olympus). DNG는 Adobe Inc.가 공개한 개방형 사양입니다. Fotollection은 내장 리더로 이를 읽고, macOS에서는 운영체제의 코덱을 먼저 사용합니다(Windows에서는 Microsoft Raw Image Extension이 설치되어 있으면 마지막 수단으로). 이 회사들 중 어느 곳도 Fotollection을 만들거나 승인하지 않았습니다.

스크린샷과 앱의 정보 프레임에 나오는 카메라 이름과 로고는 각 소유자의 상표이며, 어떤 카메라로 찍은 사진인지 보여 주기 위해서만 사용합니다: Apple(Apple Inc.), Canon(Canon Inc.), Fujifilm(FUJIFILM Corporation), Hasselblad(Victor Hasselblad AB), Leica(Leica Camera AG), Lumix(Panasonic Holdings Corporation), Nikon(Nikon Corporation), Noritsu(Noritsu Koki Co., Ltd.), Phase One(Phase One A/S), Ricoh(Ricoh Company, Ltd.), Samsung(Samsung Electronics Co., Ltd.), Sony(Sony Group Corporation).

Apple과 macOS는 Apple Inc.의 상표입니다. Windows는 Microsoft Corporation의, Linux는 미국 및 기타 국가에서 Linus Torvalds의 등록 상표입니다. Ubuntu는 Canonical Ltd.의, Debian은 Software in the Public Interest, Inc.의, Fedora, Red Hat, RHEL, CentOS는 Red Hat, Inc.의, openSUSE는 SUSE LLC의, Pop!_OS는 System76, Inc.의, Rocky Linux는 Rocky Enterprise Software Foundation의, AlmaLinux는 AlmaLinux OS Foundation의, ChromeOS는 Google LLC의, NVIDIA는 NVIDIA Corporation의 상표입니다. 그 밖의 Linux 배포판 이름은 각 프로젝트의 것입니다. Facebook과 Instagram은 Meta Platforms, Inc.의, GitHub은 GitHub, Inc.의, Google Analytics는 Google LLC의, Lightroom은 Adobe Inc.의, IrfanView는 Irfan Škiljan의, VietQR은 NAPAS의, Wikimedia Commons는 Wikimedia Foundation의 것입니다. Apple, Windows, Linux(Tux, 처음 그린 사람은 Larry Ewing) 마크는 Simple Icons(CC0)에서 가져왔으며, 열이나 단계가 어느 운영체제에 관한 것인지 보여 주기 위해서만 사용합니다.

Fotollection은 독립적인 오픈 소스 프로젝트입니다. 이 회사들과 제휴, 후원, 승인 관계가 없으며, 그 밖의 모든 상표는 각 소유자에게 있습니다.

Fotollection 이름과 로고는 @hoangphi01이 만드는 공식 앱을 나타냅니다. 공식 다운로드는 fotollection.org와 프로젝트의 GitHub 릴리스에서만 제공됩니다. GPL-3.0 라이선스에 따라, 이 라이선스를 유지하고 소스 코드를 제공하는 한 누구나 수정 여부와 관계없이 사본을 공유하거나 판매할 수 있습니다. 수정하거나 재판매한 사본은 공식 앱인 것처럼 보이도록 Fotollection 이름이나 로고를 사용할 수 없습니다.

Fotollection을 공유하거나 판매하거나, 그 위에 무언가를 만들 계획인가요? 먼저 GitHub에 이슈를 열어(github.com/hoangphi01/fotollection/issues) 만든 사람에게 알려 주세요. 앱은 무료이고 여가 시간에 만들어집니다. 짧은 메시지가 가장 좋은 감사 인사입니다.

앱을 인용하거나, 리뷰하거나, 소개하거나, 이 스크린샷을 사용하나요? Fotollection을 출처로 밝히고 fotollection.org로 링크해 주세요.