notebookVb
This commit is contained in:
@@ -0,0 +1,377 @@
|
||||
# FotkyBuzalkovi — návrh systému a poznámky z analýzy
|
||||
|
||||
> Pracovní dokument shrnující rozhodnutí a poznatky z prvotní analýzy projektu.
|
||||
> Datum diskuze: 2026-05-21
|
||||
|
||||
---
|
||||
|
||||
## 1. Cíl projektu
|
||||
|
||||
- Organizovat a tagovat **cca 200 000** rodinných fotografií
|
||||
- Lokální nasazení (žádný cloud, žádní externí uživatelé)
|
||||
- Současný stav: prázdný projekt s ukázkovými fotkami v `demo_fotky/`
|
||||
|
||||
---
|
||||
|
||||
## 2. Architektonické rozhodnutí
|
||||
|
||||
### Finální stack: **jen PostgreSQL + filesystem**
|
||||
|
||||
```
|
||||
┌─────────────────────┐
|
||||
│ Python aplikace │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
┌──────┴──────┐
|
||||
▼ ▼
|
||||
┌─────────┐ ┌──────────┐
|
||||
│PostgreSQL│ │Filesystem│
|
||||
│ metadata │ │ .jpg/.png│
|
||||
└─────────┘ └──────────┘
|
||||
```
|
||||
|
||||
### Co bylo zvažováno a zavrženo
|
||||
|
||||
| Technologie | Verdikt | Důvod |
|
||||
|-------------|---------|-------|
|
||||
| MongoDB | ❌ vynecháno | `JSONB` v PostgreSQL nahradí veškerou potřebnou funkcionalitu |
|
||||
| Redis | ❌ vynecháno (zatím) | Pro lokální 200k fotek bez webových uživatelů zbytečný |
|
||||
| MySQL | ❌ vynecháno | Projekt používá PostgreSQL (jiná databáze byla v původním plánu) |
|
||||
|
||||
### Kdy přidat Redis (pozdější fáze)
|
||||
|
||||
- Web UI s rychlým vyhledáváním (cache výsledků)
|
||||
- Paralelní workery pro import / generování thumbnailů
|
||||
- Background fronty (zpracování AI tagů)
|
||||
|
||||
### Kdy přidat něco dalšího
|
||||
|
||||
- **`pgvector`** extension pro PostgreSQL — až budeme chtít sémantické hledání (CLIP embeddings)
|
||||
- **Elasticsearch** — kdyby PostgreSQL fulltext nestačil (u 200k řádků nestane)
|
||||
|
||||
---
|
||||
|
||||
## 3. JSONB v PostgreSQL vs MongoDB BSON
|
||||
|
||||
### Terminologie
|
||||
|
||||
- **BSON** = binární JSON od MongoDB (s typy jako `ObjectId`, `Date`, `Decimal128`)
|
||||
- **JSONB** = binární JSON v PostgreSQL (vlastní formát, ne BSON, ale funkčně podobný)
|
||||
|
||||
### Srovnání vyhledávání
|
||||
|
||||
**MongoDB:**
|
||||
```javascript
|
||||
db.photos.find({ "exif.camera": "Canon EOS 5D" })
|
||||
db.photos.find({ "exif.iso": { $gte: 800 } })
|
||||
db.photos.find({ "tags": { $in: ["dovolená", "moře"] } })
|
||||
```
|
||||
|
||||
**PostgreSQL JSONB:**
|
||||
```sql
|
||||
SELECT * FROM photos WHERE exif_data->>'camera' = 'Canon EOS 5D';
|
||||
SELECT * FROM photos WHERE (exif_data->>'iso')::int >= 800;
|
||||
SELECT * FROM photos WHERE exif_data @> '{"camera": "Canon EOS 5D"}';
|
||||
```
|
||||
|
||||
### Co umí stejně
|
||||
|
||||
| Funkce | MongoDB | PostgreSQL JSONB |
|
||||
|--------|---------|------------------|
|
||||
| Filtr podle pole v JSON | ano | ano (`->>`, `@>`) |
|
||||
| Vnořené cesty | `"a.b.c"` | `data#>>'{a,b,c}'` |
|
||||
| Existence klíče | `$exists` | `?` operátor |
|
||||
| Index na JSON cestu | ano | ano (GIN) |
|
||||
| Fulltext | ano | ano |
|
||||
|
||||
### Výhody PostgreSQL JSONB pro náš případ
|
||||
|
||||
1. **JOINy** s tabulkami tagů a kamer — v Mongo by to vyžadovalo `$lookup` (pomalé)
|
||||
2. **Transakce** napříč JSONB a relačními tabulkami
|
||||
3. **Jeden backup nástroj** (`pg_dump`)
|
||||
|
||||
---
|
||||
|
||||
## 4. Identita fotky — 4 úrovně hashů
|
||||
|
||||
**Klíčový problém:** Když změníte byť jediný keyword v IPTC, SHA256 souboru se kompletně změní. Jak detekovat, že je to stále ta samá fotka?
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Stejná identita Stejný obsah │
|
||||
│ ←─────────────────────────────────────────────────────→ │
|
||||
│ │
|
||||
│ SHA256 Pixel hash Perceptual Embedding │
|
||||
│ souboru (jen pixely) hash (pHash) (CLIP/DINO) │
|
||||
│ │
|
||||
│ byte-by-byte metadata +recomprese +sémantika │
|
||||
│ identické ignorováno +resize podobnost │
|
||||
│ +crop │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1. SHA256 souboru (`sha256_file`)
|
||||
- Detekuje **přesnou kopii** souboru
|
||||
- Změna IPTC/EXIF, otočení, znovuuložení → jiný hash
|
||||
|
||||
### 2. Pixel hash (`sha256_pixels`)
|
||||
- SHA256 dekódovaných pixelů (po aplikaci EXIF orientation)
|
||||
- **Stejná fotka po změně metadat** → identický hash
|
||||
- Toto je odpověď na otázku "jak detekovat, že je to ta samá fotka po změně keywords"
|
||||
|
||||
```python
|
||||
with Image.open(path) as img:
|
||||
img = ImageOps.exif_transpose(img)
|
||||
if img.mode != "RGB":
|
||||
img = img.convert("RGB")
|
||||
pixel_hash = hashlib.sha256(img.tobytes()).hexdigest()
|
||||
```
|
||||
|
||||
### 3. Perceptual hash (`pHash`, `dHash`, `wHash`)
|
||||
- 64-bit "otisk obsahu" — vizuálně podobné fotky → blízké hashe
|
||||
- Porovnává se přes **Hamming distance** (`bin(h1 ^ h2).count("1")`)
|
||||
- < 10 = velmi podobné, > 20 = odlišné
|
||||
- Detekuje: recompresi, resize, drobné úpravy, watermark, crop
|
||||
- Knihovna: [`imagehash`](https://pypi.org/project/ImageHash/)
|
||||
|
||||
### 4. Deep learning embedding (budoucnost)
|
||||
- Vektor 512–1024 dimenzí z CLIP / DINOv2
|
||||
- Sémantická podobnost ("dvě fotky stejné scény z různých úhlů")
|
||||
- Uložení v PostgreSQL přes `pgvector` extension
|
||||
|
||||
### Workflow při importu nové fotky
|
||||
|
||||
```
|
||||
1. Spočítej sha256_file
|
||||
↓
|
||||
2. Najdi v DB stejný sha256_file?
|
||||
ANO → identická kopie, přeskočit
|
||||
NE → ↓
|
||||
3. Spočítej sha256_pixels
|
||||
↓
|
||||
4. Najdi v DB stejný sha256_pixels?
|
||||
ANO → stejná fotka, jen jiná metadata → updatuj, nepřidávej duplikát
|
||||
NE → ↓
|
||||
5. Spočítej phash, ulož do DB
|
||||
↓
|
||||
6. (Volitelně) najdi podobné: WHERE hamming(phash, ?) < 10
|
||||
```
|
||||
|
||||
### Poznámka k JPEG
|
||||
|
||||
- Před hashingem **vždy aplikovat EXIF orientation** (`ImageOps.exif_transpose`)
|
||||
- Konvertovat do RGB pro konzistenci
|
||||
- Jinak by se rotovaná fotka vs nerotovaná lišila
|
||||
|
||||
---
|
||||
|
||||
## 5. Tři vrstvy metadat ve fotce
|
||||
|
||||
| Standard | Co tam je | Kdo to vyplňuje |
|
||||
|----------|-----------|-----------------|
|
||||
| **EXIF** | Technická data (clona, ISO, čas, GPS, model kamery) | Kamera automaticky |
|
||||
| **IPTC** | Popisná data (titulek, popis, klíčová slova, autor, copyright) | Člověk / software |
|
||||
| **XMP** | Modernější nástupce IPTC od Adobe, často duplikuje + edits, ratings, regions | Software (Lightroom, Apple Photos) |
|
||||
|
||||
### Pro náš případ
|
||||
|
||||
- iPhone vyplňuje hlavně **EXIF** a **XMP** (ne IPTC)
|
||||
- Apple Photos do XMP ukládá **rozpoznané obličeje** (`mwg-rs:Regions`) — i se jmény, pokud je pojmenuješ!
|
||||
- iOS screenshoty mají v XMP `description: "Screenshot"` → automatická detekce
|
||||
- Pokud budeme tagovat, je dobré tagy ukládat **i do IPTC `Keywords`** — přežijí export do jiné aplikace
|
||||
|
||||
---
|
||||
|
||||
## 6. Výsledky exploration na 7 demo fotkách
|
||||
|
||||
### Souhrn dat z `explore_photos.py`
|
||||
|
||||
| # | Soubor | Mpx | EXIF tagů | IPTC | XMP | GPS | Kamera |
|
||||
|---|--------|-----|-----------|------|-----|-----|--------|
|
||||
| 1 | 2026-04-22 09.05.08.jpg | 24.47 | 121 | 0 | 4 | ano | iPhone 16 Pro Max |
|
||||
| 2 | 2026-04-24 15.15.47.jpg | 12.19 | 107 | 0 | 0 | ne | iPhone 13 Pro Max |
|
||||
| 3 | 2026-05-02 10.04.44.png | 3.57 | 12 | 0 | 1 | ne | Screenshot |
|
||||
| 4 | 2026-05-18 06.22.37.jpg | 12.19 | 105 | 0 | 4 | ne | iPhone 13 Pro Max |
|
||||
| 5 | 2026-05-18 06.22.41.jpg | 12.19 | 105 | 0 | 4 | ne | iPhone 13 Pro Max |
|
||||
| 6 | 2026-05-18 13.54.47.jpg | 12.19 | 98 | 6 | 0 | ne | iPhone 13 Pro Max |
|
||||
| 7 | 2026-05-18 14.10.59.jpg | 2.36 | 0 | 0 | 0 | ne | (sirotek) |
|
||||
|
||||
### Klíčové objevy
|
||||
|
||||
1. **Perceptual hash funguje** — fotky [4] a [5] (pořízené 4 sekundy po sobě) mají Hamming distance pouze **4** = klasický burst snapshot.
|
||||
|
||||
2. **Apple face detection v XMP** — fotky 1, 4, 5 mají `face_regions_count: 1`. iPhone už **detekoval obličej** a uložil to do XMP. Můžeme číst přímo, bez vlastní AI.
|
||||
|
||||
3. **Screenshot rozpoznán** — foto [3] má v XMP `description: "Screenshot"` → automatická kategorizace.
|
||||
|
||||
4. **Foto [7] = sirotek** — žádné metadata. Pravděpodobně přeposlané přes WhatsApp/Messenger, kde se EXIF maže. **Pro 200k fotek bude tato kategorie významná.**
|
||||
|
||||
5. **GPS jen u 1/7 fotek** — u většiny iPhone fotek máte vypnuté lokační služby.
|
||||
|
||||
6. **Time zone** — fotky mají `OffsetTime: +02:00`. **Datum pořízení ukládat jako `TIMESTAMPTZ`** (s timezone).
|
||||
|
||||
7. **ExifRead > Pillow** — Pillow má GPS bug (`'int' object has no attribute 'items'`). **Primární parser bude ExifRead.**
|
||||
|
||||
8. **MakerNote (Apple binary blob)** — obsahuje burst ID, HDR příznak, focus distance. Pro rozluštění potřeba [`exiftool`](https://exiftool.org/) (volat přes `pyexiftool`).
|
||||
|
||||
---
|
||||
|
||||
## 7. Návrh databázového schématu (draft)
|
||||
|
||||
```sql
|
||||
CREATE TABLE photos (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
|
||||
-- identita (3 úrovně)
|
||||
sha256_file CHAR(64) UNIQUE NOT NULL, -- byte identita
|
||||
sha256_pixels CHAR(64), -- pixel identita
|
||||
phash BIGINT, -- vizuální podobnost
|
||||
|
||||
-- soubor
|
||||
file_path VARCHAR(1000) NOT NULL,
|
||||
file_name VARCHAR(255) NOT NULL,
|
||||
file_size BIGINT,
|
||||
mime_type VARCHAR(50),
|
||||
format VARCHAR(20), -- JPEG, PNG, HEIC, ...
|
||||
width INT,
|
||||
height INT,
|
||||
|
||||
-- pořízení
|
||||
taken_at TIMESTAMPTZ, -- s timezone (máme OffsetTime!)
|
||||
taken_at_source VARCHAR(20), -- 'exif' / 'mtime' / 'iptc' / 'unknown'
|
||||
|
||||
-- technika (z EXIF)
|
||||
camera_make VARCHAR(100),
|
||||
camera_model VARCHAR(255),
|
||||
lens_model VARCHAR(255),
|
||||
iso INT,
|
||||
aperture NUMERIC(4,2),
|
||||
exposure_time VARCHAR(20), -- "1/500"
|
||||
focal_length_mm NUMERIC(5,2),
|
||||
|
||||
-- GPS (NULL pokud chybí)
|
||||
gps_lat NUMERIC(10,7),
|
||||
gps_lon NUMERIC(10,7),
|
||||
gps_altitude NUMERIC(7,2),
|
||||
|
||||
-- klasifikace
|
||||
is_screenshot BOOLEAN DEFAULT FALSE,
|
||||
face_count INT, -- z XMP, rozšířit AI
|
||||
|
||||
-- flexibilní JSONB pro celý dump
|
||||
exif_raw JSONB,
|
||||
iptc_raw JSONB,
|
||||
xmp_raw JSONB,
|
||||
|
||||
-- import / zpracování
|
||||
imported_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
processed_at TIMESTAMPTZ,
|
||||
processing_status VARCHAR(50) DEFAULT 'pending'
|
||||
);
|
||||
|
||||
CREATE INDEX idx_photos_sha256_pixels ON photos(sha256_pixels);
|
||||
CREATE INDEX idx_photos_phash ON photos(phash);
|
||||
CREATE INDEX idx_photos_taken_at ON photos(taken_at);
|
||||
CREATE INDEX idx_photos_camera_model ON photos(camera_model);
|
||||
CREATE INDEX idx_photos_exif_gin ON photos USING GIN (exif_raw);
|
||||
|
||||
CREATE TABLE tags (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
parent_tag_id INT REFERENCES tags(id), -- hierarchie "místo > Praha > Karlův most"
|
||||
UNIQUE(name, parent_tag_id)
|
||||
);
|
||||
|
||||
CREATE TABLE photo_tags (
|
||||
photo_id BIGINT REFERENCES photos(id) ON DELETE CASCADE,
|
||||
tag_id INT REFERENCES tags(id) ON DELETE CASCADE,
|
||||
source VARCHAR(20), -- 'manual' / 'iptc' / 'xmp' / 'auto'
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
PRIMARY KEY (photo_id, tag_id)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Otevřené otázky pro příště
|
||||
|
||||
### Foto bez EXIF (sirotek typu [7])
|
||||
|
||||
- **a)** Importovat (s `taken_at` z `mtime`)
|
||||
- **b)** Odmítnout jako "nezpracovatelnou"
|
||||
- **c)** Importovat, ale označit `processing_status = 'no_metadata'`
|
||||
|
||||
### Detekce duplikátů (shoda `sha256_pixels`)
|
||||
|
||||
- **a)** Přeskočit (nepřidávat duplicitu)
|
||||
- **b)** Sloučit (aktualizovat metadata u existujícího záznamu)
|
||||
- **c)** Uložit oba, jen označit jako související
|
||||
|
||||
### Storage layout fotek
|
||||
|
||||
- **a)** Necháme v aktuálním umístění, do DB jen cestu
|
||||
- **b)** Kopie do `archiv/YYYY/MM/původní_název.jpg`
|
||||
- **c)** Kopie do `archiv/{sha[:2]}/{sha}.jpg` (content-addressable = auto-dedup na FS)
|
||||
|
||||
---
|
||||
|
||||
## 9. Co dál — nápady k prozkoumání
|
||||
|
||||
- **`exiftool`** — rozluští Apple MakerNote (burst ID by potvrdilo, že [4] a [5] patří k sobě)
|
||||
- **Embedded thumbnail z EXIF** — telefon ukládá malou náhledovku přímo v souboru → rychlejší galerie bez generování
|
||||
- **CLIP embeddings + pgvector** — sémantické vyhledávání ("ukaž fotky pejsků na pláži")
|
||||
- **Reverse geocoding** — z GPS souřadnic na čitelné místo (Nominatim / Photon, lokálně)
|
||||
- **Apple Photos jména osob** — z XMP `mwg-rs:Regions` jdou číst i jména, pokud jsou v Photos pojmenovaná
|
||||
- **Datum z názvu souboru** — fallback když chybí EXIF i sensible `mtime` (regex z "2026-05-18 13.54.47.jpg")
|
||||
|
||||
---
|
||||
|
||||
## 10. Aktuální stav projektu (k 2026-05-21)
|
||||
|
||||
### Soubory v projektu
|
||||
|
||||
```
|
||||
FotkyBuzalkovi/
|
||||
├── demo_fotky/ # 7 ukázkových fotek
|
||||
├── explore_photos.py # Explorační skript (hashe, EXIF, IPTC, XMP)
|
||||
├── photo_exploration.json # Výstup exploreru
|
||||
├── create_schema.py # ZASTARALÉ - obsahuje MySQL syntaxi a hardcoded hesla
|
||||
├── test_db_connection.py # Test PG + Mongo + Redis (Mongo/Redis nebudou potřeba)
|
||||
├── test_mongo.py # ZASTARALÉ - Mongo nepoužijeme
|
||||
├── README.md
|
||||
└── NAVRH.md # Tento dokument
|
||||
```
|
||||
|
||||
### Co bude potřeba udělat
|
||||
|
||||
- [ ] Smazat nebo přepsat `create_schema.py` (MySQL syntaxe `INDEX` uvnitř `CREATE TABLE` v PG nefunguje)
|
||||
- [ ] Migrovat hesla do `.env` + `python-dotenv`
|
||||
- [ ] Smazat / archivovat `test_mongo.py`
|
||||
- [ ] Vytvořit migraci podle schématu v sekci 7
|
||||
- [ ] Skript pro import fotek s deduplikací (workflow v sekci 4)
|
||||
- [ ] Rozhodnout otevřené otázky ze sekce 8
|
||||
|
||||
### Nainstalované Python balíčky
|
||||
|
||||
```
|
||||
psycopg2-binary 2.9.12 # PostgreSQL driver
|
||||
pymongo 4.17.0 # (nepotřebujeme)
|
||||
redis 7.4.0 # (zatím nepotřebujeme)
|
||||
pillow 12.2.0 # Základní práce s obrázky
|
||||
ExifRead 3.5.1 # Primární EXIF parser (lepší než Pillow)
|
||||
imagehash 4.3.2 # Perceptuální hashe (pHash, dHash, wHash)
|
||||
+ numpy, scipy, PyWavelets (závislosti imagehash)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. Užitečné odkazy
|
||||
|
||||
- [Pillow](https://pillow.readthedocs.io/) — Python Imaging Library
|
||||
- [ExifRead](https://github.com/ianare/exif-py) — EXIF parser
|
||||
- [imagehash](https://github.com/JohannesBuchner/imagehash) — perceptuální hashe
|
||||
- [exiftool](https://exiftool.org/) — gold standard pro metadata (Perl, ale `pyexiftool` wrapper)
|
||||
- [pgvector](https://github.com/pgvector/pgvector) — vektory v PostgreSQL pro sémantické hledání
|
||||
- [PostgreSQL JSONB docs](https://www.postgresql.org/docs/current/datatype-json.html)
|
||||
- [IPTC Photo Metadata Standard](https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata)
|
||||
- [XMP Specification (Adobe)](https://www.adobe.com/devnet/xmp.html)
|
||||
@@ -0,0 +1,153 @@
|
||||
# FotkyBuzalkovi
|
||||
|
||||
Systém pro zpracování, ukládání a vyhledávání rodinných fotografií s automatickou extrakcí EXIF metadat.
|
||||
|
||||
## Architektura
|
||||
|
||||
Projekt používá kombinaci tří databází, kde každá řeší specifickou úlohu:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Python aplikace │
|
||||
│ (zpracování fotek, EXIF, hash) │
|
||||
└────────────┬──────────────┬──────────────┬───────────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────────┐ ┌────────────┐ ┌────────────┐
|
||||
│ PostgreSQL │ │ MongoDB │ │ Redis │
|
||||
│ (relační) │ │ (EXIF/doc) │ │ (cache) │
|
||||
└────────────┘ └────────────┘ └────────────┘
|
||||
192.168.1.76 192.168.1.76 localhost
|
||||
:5432 :27017 :6379
|
||||
```
|
||||
|
||||
### Proč tři databáze?
|
||||
|
||||
| Databáze | Role | Co ukládá |
|
||||
|----------|------|-----------|
|
||||
| **PostgreSQL** | Strukturovaná data, relace | `photos`, `cameras`, `photo_tags` - ID, cesty, hashe, FK |
|
||||
| **MongoDB** | Flexibilní dokumenty | Plná EXIF metadata (různé fotoaparáty = různá pole) |
|
||||
| **Redis** | Cache + fronty | Miniatury, výsledky vyhledávání, fronta zpracování |
|
||||
|
||||
## Datové úložiště
|
||||
|
||||
### PostgreSQL - `fotky_buzalkovi`
|
||||
|
||||
- **cameras** - seznam fotoaparátů (model, vyrobce)
|
||||
- **photos** - hlavní tabulka (file_name, file_path, file_hash, taken_at, rozměry, FK na camera)
|
||||
- **photo_tags** - tagy ke každé fotce (many-to-many)
|
||||
|
||||
### MongoDB - `fotky_buzalkovi`
|
||||
|
||||
- **photos** kolekce - kompletní EXIF data, GPS souřadnice, nastavení clony, ISO, atd.
|
||||
|
||||
### Redis (plánováno)
|
||||
|
||||
- **cache:thumb:{photo_id}** - cached miniatury (TTL 1h)
|
||||
- **queue:process** - fronta nezpracovaných fotek
|
||||
- **session:{user_id}** - session data
|
||||
|
||||
## K čemu Redis
|
||||
|
||||
1. **Cache miniatur** - generování miniatur je drahé, Redis je drží v RAM (rychlost ~0.1ms vs ~50ms z disku)
|
||||
2. **Cache vyhledávání** - "fotky z dovolené 2025" se může opakovat, výsledek se cachuje
|
||||
3. **Fronta zpracování** - když nahrajete 1000 fotek, Redis funguje jako worker queue
|
||||
4. **Deduplikace** - rychlá kontrola, zda hash fotky už existuje
|
||||
5. **Rate limiting** - omezení uploadů
|
||||
|
||||
## Instalace
|
||||
|
||||
### 1. Python prostředí
|
||||
|
||||
```powershell
|
||||
python -m venv .venv
|
||||
.venv\Scripts\Activate.ps1
|
||||
pip install psycopg2-binary pymongo redis pillow exifread python-dotenv
|
||||
```
|
||||
|
||||
### 2. PostgreSQL
|
||||
|
||||
Předpoklad: PostgreSQL běží na `192.168.1.76:5432`.
|
||||
|
||||
```powershell
|
||||
python create_schema.py
|
||||
```
|
||||
|
||||
### 3. MongoDB
|
||||
|
||||
Předpoklad: MongoDB běží na `192.168.1.76:27017`.
|
||||
|
||||
```powershell
|
||||
python test_mongo.py
|
||||
```
|
||||
|
||||
### 4. Redis (Windows)
|
||||
|
||||
Redis oficiálně Windows nepodporuje. Tři možnosti:
|
||||
|
||||
**Možnost A - WSL2 (doporučeno):**
|
||||
```powershell
|
||||
wsl --install
|
||||
# v WSL:
|
||||
sudo apt update
|
||||
sudo apt install redis-server
|
||||
sudo service redis-server start
|
||||
```
|
||||
|
||||
**Možnost B - Docker:**
|
||||
```powershell
|
||||
docker run -d --name redis -p 6379:6379 redis:latest
|
||||
```
|
||||
|
||||
**Možnost C - Memurai (Windows-native Redis-kompatibilní):**
|
||||
- Stáhnout z https://www.memurai.com/
|
||||
|
||||
Test:
|
||||
```powershell
|
||||
python test_db_connection.py
|
||||
```
|
||||
|
||||
## Konfigurace
|
||||
|
||||
**⚠️ Hesla v současných skriptech jsou v plain textu - před nasazením přesunout do `.env`:**
|
||||
|
||||
```env
|
||||
PG_HOST=192.168.1.76
|
||||
PG_PORT=5432
|
||||
PG_USER=vladimir.buzalka
|
||||
PG_PASSWORD=...
|
||||
PG_DB=fotky_buzalkovi
|
||||
|
||||
MONGO_URI=mongodb://192.168.1.76:27017/
|
||||
MONGO_DB=fotky_buzalkovi
|
||||
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
```
|
||||
|
||||
## Struktura projektu
|
||||
|
||||
```
|
||||
FotkyBuzalkovi/
|
||||
├── demo_fotky/ # Testovací fotografie
|
||||
├── create_schema.py # Vytvoření PostgreSQL schématu
|
||||
├── test_db_connection.py # Test všech tří databází
|
||||
├── test_mongo.py # Test MongoDB + vytvoření kolekcí
|
||||
├── .gitignore
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Známé problémy
|
||||
|
||||
- `create_schema.py` používá MySQL syntaxi `INDEX idx_x` uvnitř `CREATE TABLE` - v PostgreSQL je potřeba `CREATE INDEX` zvlášť po `CREATE TABLE`
|
||||
- Hesla jsou hardcodovaná v Python souborech - migrovat do `.env` + `python-dotenv`
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [ ] Opravit PostgreSQL schéma (INDEX syntaxe)
|
||||
- [ ] Migrace hesel do `.env`
|
||||
- [ ] Instalace Redis
|
||||
- [ ] Skript pro hromadný import fotek z `demo_fotky/`
|
||||
- [ ] EXIF parser (pillow + exifread)
|
||||
- [ ] Generování miniatur s Redis cache
|
||||
- [ ] Web UI pro prohlížení galerie
|
||||
@@ -0,0 +1,398 @@
|
||||
"""
|
||||
Explorační skript: projde všechny fotky v demo_fotky/ a vytáhne maximum dat.
|
||||
Výstup do konzole + JSON soubor pro detailní analýzu.
|
||||
"""
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
# Windows konzole - vynutit UTF-8
|
||||
if sys.stdout.encoding.lower() != "utf-8":
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
sys.stderr.reconfigure(encoding="utf-8")
|
||||
|
||||
import exifread
|
||||
import imagehash
|
||||
from PIL import Image, ImageOps, IptcImagePlugin
|
||||
from PIL.ExifTags import TAGS, GPSTAGS
|
||||
|
||||
PHOTOS_DIR = Path(__file__).parent / "demo_fotky"
|
||||
OUTPUT_JSON = Path(__file__).parent / "photo_exploration.json"
|
||||
|
||||
|
||||
def file_hash_sha256(path: Path, chunk_size: int = 65536) -> str:
|
||||
"""Hash celého souboru - detekce přesné kopie."""
|
||||
h = hashlib.sha256()
|
||||
with open(path, "rb") as f:
|
||||
while chunk := f.read(chunk_size):
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def pixel_hash_sha256(path: Path) -> str | None:
|
||||
"""Hash dekódovaných pixelů - identita fotky nezávisle na metadatech.
|
||||
Aplikuje EXIF orientation pro konzistenci."""
|
||||
try:
|
||||
with Image.open(path) as img:
|
||||
img = ImageOps.exif_transpose(img)
|
||||
if img.mode != "RGB":
|
||||
img = img.convert("RGB")
|
||||
return hashlib.sha256(img.tobytes()).hexdigest()
|
||||
except Exception as e:
|
||||
return None
|
||||
|
||||
|
||||
def perceptual_hashes(path: Path) -> dict:
|
||||
"""Perceptuální hashe - detekce vizuálně podobných fotek.
|
||||
Každý hash je 64-bit, porovnává se Hamming distance."""
|
||||
out = {}
|
||||
try:
|
||||
with Image.open(path) as img:
|
||||
img = ImageOps.exif_transpose(img)
|
||||
out["phash"] = str(imagehash.phash(img))
|
||||
out["dhash"] = str(imagehash.dhash(img))
|
||||
out["ahash"] = str(imagehash.average_hash(img))
|
||||
out["whash"] = str(imagehash.whash(img))
|
||||
except Exception as e:
|
||||
out["_error"] = str(e)
|
||||
return out
|
||||
|
||||
|
||||
def iptc_info(path: Path) -> dict:
|
||||
"""IPTC metadata - keywords, title, description, author atd."""
|
||||
out = {}
|
||||
# Mapování IPTC numerických tagů na čitelné názvy
|
||||
iptc_names = {
|
||||
(2, 5): "ObjectName", # Title
|
||||
(2, 10): "Urgency",
|
||||
(2, 15): "Category",
|
||||
(2, 20): "SupplementalCategories",
|
||||
(2, 25): "Keywords",
|
||||
(2, 40): "SpecialInstructions",
|
||||
(2, 55): "DateCreated",
|
||||
(2, 60): "TimeCreated",
|
||||
(2, 80): "Byline", # Creator/Author
|
||||
(2, 85): "BylineTitle",
|
||||
(2, 90): "City",
|
||||
(2, 92): "SubLocation",
|
||||
(2, 95): "ProvinceState",
|
||||
(2, 100): "CountryCode",
|
||||
(2, 101): "CountryName",
|
||||
(2, 103): "OriginalTransmissionReference",
|
||||
(2, 105): "Headline",
|
||||
(2, 110): "Credit",
|
||||
(2, 115): "Source",
|
||||
(2, 116): "Copyright",
|
||||
(2, 118): "Contact",
|
||||
(2, 120): "Caption", # Description
|
||||
(2, 122): "WriterEditor",
|
||||
}
|
||||
try:
|
||||
with Image.open(path) as img:
|
||||
raw = IptcImagePlugin.getiptcinfo(img)
|
||||
if not raw:
|
||||
return {}
|
||||
for key, value in raw.items():
|
||||
name = iptc_names.get(key, f"IPTC{key}")
|
||||
if isinstance(value, bytes):
|
||||
value = value.decode("utf-8", errors="replace")
|
||||
elif isinstance(value, list):
|
||||
value = [v.decode("utf-8", errors="replace") if isinstance(v, bytes) else v for v in value]
|
||||
out[name] = value
|
||||
except Exception as e:
|
||||
out["_error"] = str(e)
|
||||
return out
|
||||
|
||||
|
||||
def xmp_info(path: Path) -> dict:
|
||||
"""XMP metadata - moderní alternativa IPTC, často keywords/rating/regions."""
|
||||
out = {}
|
||||
try:
|
||||
with Image.open(path) as img:
|
||||
xmp_raw = img.info.get("xmp")
|
||||
if not xmp_raw:
|
||||
return {}
|
||||
if isinstance(xmp_raw, bytes):
|
||||
xmp_raw = xmp_raw.decode("utf-8", errors="replace")
|
||||
|
||||
# Velmi jednoduchý parser - vytáhne nejčastější pole regexem
|
||||
patterns = {
|
||||
"creator_tool": r'xmp:CreatorTool="([^"]+)"',
|
||||
"create_date": r'xmp:CreateDate="([^"]+)"',
|
||||
"modify_date": r'xmp:ModifyDate="([^"]+)"',
|
||||
"rating": r'xmp:Rating="([^"]+)"',
|
||||
"label": r'xmp:Label="([^"]+)"',
|
||||
"title": r'<dc:title[^>]*>.*?<rdf:li[^>]*>([^<]+)</rdf:li>',
|
||||
"description": r'<dc:description[^>]*>.*?<rdf:li[^>]*>([^<]+)</rdf:li>',
|
||||
"creator": r'<dc:creator[^>]*>.*?<rdf:li[^>]*>([^<]+)</rdf:li>',
|
||||
"subject_keywords": r'<dc:subject[^>]*>(.*?)</dc:subject>',
|
||||
}
|
||||
for name, pat in patterns.items():
|
||||
m = re.search(pat, xmp_raw, re.DOTALL)
|
||||
if m:
|
||||
out[name] = m.group(1).strip()
|
||||
|
||||
# Keywords z dc:subject - vytáhnout jednotlivé rdf:li
|
||||
if "subject_keywords" in out:
|
||||
kws = re.findall(r'<rdf:li[^>]*>([^<]+)</rdf:li>', out["subject_keywords"])
|
||||
out["subject_keywords"] = kws
|
||||
|
||||
# Apple regions (rozpoznané obličeje s pozicí)
|
||||
face_count = len(re.findall(r'mwg-rs:Type="Face"', xmp_raw))
|
||||
if face_count:
|
||||
out["face_regions_count"] = face_count
|
||||
|
||||
# Délka raw XMP pro představu
|
||||
out["_xmp_length_bytes"] = len(xmp_raw)
|
||||
except Exception as e:
|
||||
out["_error"] = str(e)
|
||||
return out
|
||||
|
||||
|
||||
def filesystem_info(path: Path) -> dict:
|
||||
stat = path.stat()
|
||||
return {
|
||||
"file_name": path.name,
|
||||
"file_path": str(path),
|
||||
"file_size_bytes": stat.st_size,
|
||||
"file_size_mb": round(stat.st_size / 1024 / 1024, 2),
|
||||
"mtime": datetime.fromtimestamp(stat.st_mtime).isoformat(),
|
||||
"ctime": datetime.fromtimestamp(stat.st_ctime).isoformat(),
|
||||
"extension": path.suffix.lower(),
|
||||
}
|
||||
|
||||
|
||||
def pillow_info(path: Path) -> dict:
|
||||
info = {}
|
||||
try:
|
||||
with Image.open(path) as img:
|
||||
info["format"] = img.format
|
||||
info["mode"] = img.mode
|
||||
info["width"] = img.width
|
||||
info["height"] = img.height
|
||||
info["megapixels"] = round((img.width * img.height) / 1_000_000, 2)
|
||||
info["has_transparency"] = img.mode in ("RGBA", "LA") or "transparency" in img.info
|
||||
info["dpi"] = img.info.get("dpi")
|
||||
info["icc_profile_present"] = "icc_profile" in img.info
|
||||
info["exif_present"] = bool(img.getexif())
|
||||
|
||||
# XMP (často v JPG od Adobe)
|
||||
if "xmp" in img.info:
|
||||
xmp_raw = img.info["xmp"]
|
||||
if isinstance(xmp_raw, bytes):
|
||||
xmp_raw = xmp_raw[:500].decode("utf-8", errors="ignore")
|
||||
info["xmp_snippet"] = str(xmp_raw)[:500]
|
||||
|
||||
# Thumbnail embedded?
|
||||
info["has_embedded_thumbnail"] = "thumbnail" in img.info
|
||||
except Exception as e:
|
||||
info["error"] = str(e)
|
||||
return info
|
||||
|
||||
|
||||
def pillow_exif(path: Path) -> dict:
|
||||
"""Pillow EXIF — čitelné názvy."""
|
||||
out = {}
|
||||
try:
|
||||
with Image.open(path) as img:
|
||||
exif = img.getexif()
|
||||
if not exif:
|
||||
return {}
|
||||
for tag_id, value in exif.items():
|
||||
tag = TAGS.get(tag_id, f"Tag{tag_id}")
|
||||
# GPS info jako vnořený dict
|
||||
if tag == "GPSInfo":
|
||||
gps = {}
|
||||
for gps_tag_id, gps_value in value.items():
|
||||
gps_tag = GPSTAGS.get(gps_tag_id, f"GPSTag{gps_tag_id}")
|
||||
gps[gps_tag] = _serializable(gps_value)
|
||||
out[tag] = gps
|
||||
else:
|
||||
out[tag] = _serializable(value)
|
||||
except Exception as e:
|
||||
out["_error"] = str(e)
|
||||
return out
|
||||
|
||||
|
||||
def exifread_tags(path: Path) -> dict:
|
||||
"""ExifRead — často víc tagů než Pillow, mj. detailní MakerNote."""
|
||||
out = {}
|
||||
try:
|
||||
with open(path, "rb") as f:
|
||||
tags = exifread.process_file(f, details=True)
|
||||
for k, v in tags.items():
|
||||
# přeskočit binární thumbnail
|
||||
if "Thumbnail" in k and "JPEGInterchangeFormat" not in k:
|
||||
continue
|
||||
out[k] = str(v)
|
||||
except Exception as e:
|
||||
out["_error"] = str(e)
|
||||
return out
|
||||
|
||||
|
||||
def _serializable(v):
|
||||
"""Pillow vrací občas IFDRational, bytes apod. → převést na JSON-friendly."""
|
||||
if isinstance(v, bytes):
|
||||
return v[:200].decode("utf-8", errors="replace")
|
||||
if isinstance(v, (tuple, list)):
|
||||
return [_serializable(x) for x in v]
|
||||
if isinstance(v, dict):
|
||||
return {str(k): _serializable(val) for k, val in v.items()}
|
||||
if hasattr(v, "numerator") and hasattr(v, "denominator"):
|
||||
try:
|
||||
return float(v)
|
||||
except Exception:
|
||||
return str(v)
|
||||
try:
|
||||
json.dumps(v)
|
||||
return v
|
||||
except (TypeError, ValueError):
|
||||
return str(v)
|
||||
|
||||
|
||||
def explore_photo(path: Path) -> dict:
|
||||
return {
|
||||
"filesystem": filesystem_info(path),
|
||||
"hashes": {
|
||||
"sha256_file": file_hash_sha256(path),
|
||||
"sha256_pixels": pixel_hash_sha256(path),
|
||||
**perceptual_hashes(path),
|
||||
},
|
||||
"pillow": pillow_info(path),
|
||||
"exif_pillow": pillow_exif(path),
|
||||
"exif_exifread": exifread_tags(path),
|
||||
"iptc": iptc_info(path),
|
||||
"xmp": xmp_info(path),
|
||||
}
|
||||
|
||||
|
||||
def hamming_distance(h1: str, h2: str) -> int:
|
||||
"""Hamming distance mezi dvěma hex perceptual hashes."""
|
||||
return bin(int(h1, 16) ^ int(h2, 16)).count("1")
|
||||
|
||||
|
||||
def print_summary(photos: list[dict]) -> None:
|
||||
print(f"\n{'=' * 70}")
|
||||
print(f"PŘEHLED: {len(photos)} fotek")
|
||||
print(f"{'=' * 70}\n")
|
||||
|
||||
# Které EXIF tagy existují napříč fotkami?
|
||||
all_pillow_keys = set()
|
||||
all_exifread_keys = set()
|
||||
for p in photos:
|
||||
all_pillow_keys.update(p["exif_pillow"].keys())
|
||||
all_exifread_keys.update(p["exif_exifread"].keys())
|
||||
|
||||
print(f"Unikátní EXIF tagy (Pillow): {len(all_pillow_keys)}")
|
||||
print(f"Unikátní EXIF tagy (ExifRead): {len(all_exifread_keys)}")
|
||||
print()
|
||||
|
||||
for i, p in enumerate(photos, 1):
|
||||
fs = p["filesystem"]
|
||||
pi = p["pillow"]
|
||||
h = p["hashes"]
|
||||
er = p["exif_exifread"]
|
||||
print(f"[{i}] {fs['file_name']}")
|
||||
print(f" Velikost: {fs['file_size_mb']} MB ({pi.get('width')}x{pi.get('height')}, {pi.get('megapixels')} Mpx)")
|
||||
print(f" Formát: {pi.get('format')} / mode={pi.get('mode')}")
|
||||
print(f" sha256_file: {h['sha256_file'][:16]}...")
|
||||
print(f" sha256_pixels: {(h.get('sha256_pixels') or 'N/A')[:16]}...")
|
||||
print(f" phash: {h.get('phash')} (perceptual)")
|
||||
print(f" EXIF tagů: ExifRead={len(er)}, Pillow={len(p['exif_pillow'])}")
|
||||
print(f" IPTC polí: {len([k for k in p['iptc'] if not k.startswith('_')])}")
|
||||
print(f" XMP polí: {len([k for k in p['xmp'] if not k.startswith('_')])}")
|
||||
|
||||
# ExifRead je spolehlivější (Pillow má GPS bug)
|
||||
interesting = {
|
||||
"Kamera": f"{er.get('Image Make', '')} {er.get('Image Model', '')}".strip(),
|
||||
"Objektiv": er.get("EXIF LensModel"),
|
||||
"Datum": er.get("EXIF DateTimeOriginal") or er.get("Image DateTime"),
|
||||
"TZ offset": er.get("EXIF OffsetTimeOriginal") or er.get("EXIF OffsetTime"),
|
||||
"Clona": er.get("EXIF FNumber"),
|
||||
"ISO": er.get("EXIF ISOSpeedRatings"),
|
||||
"Expozice": er.get("EXIF ExposureTime"),
|
||||
"Ohnisko mm": er.get("EXIF FocalLength"),
|
||||
"Flash": er.get("EXIF Flash"),
|
||||
"GPS lat": er.get("GPS GPSLatitude"),
|
||||
"GPS lon": er.get("GPS GPSLongitude"),
|
||||
"Software": er.get("Image Software"),
|
||||
}
|
||||
for k, v in interesting.items():
|
||||
if v and str(v).strip():
|
||||
print(f" {k:12s}: {v}")
|
||||
|
||||
# IPTC / XMP — vypsat všechno, co je
|
||||
if p["iptc"]:
|
||||
for k, v in p["iptc"].items():
|
||||
if not k.startswith("_"):
|
||||
print(f" IPTC.{k:8s}: {v}")
|
||||
if p["xmp"]:
|
||||
for k, v in p["xmp"].items():
|
||||
if not k.startswith("_"):
|
||||
print(f" XMP.{k:9s}: {v}")
|
||||
print()
|
||||
|
||||
# Tabulka perceptuálních podobností (Hamming distance phash)
|
||||
print(f"{'=' * 70}")
|
||||
print("PERCEPTUÁLNÍ PODOBNOST (phash Hamming distance)")
|
||||
print("Hodnota 0-10 = vizuálně velmi podobné, >20 = odlišné")
|
||||
print(f"{'=' * 70}")
|
||||
n = len(photos)
|
||||
header = " " + "".join(f" [{i+1}]" for i in range(n))
|
||||
print(header)
|
||||
for i in range(n):
|
||||
row = f" [{i+1}] "
|
||||
for j in range(n):
|
||||
if i == j:
|
||||
row += " -"
|
||||
else:
|
||||
h1 = photos[i]["hashes"].get("phash")
|
||||
h2 = photos[j]["hashes"].get("phash")
|
||||
if h1 and h2:
|
||||
d = hamming_distance(h1, h2)
|
||||
marker = "*" if d <= 10 and i != j else " "
|
||||
row += f" {d:3d}{marker}"
|
||||
else:
|
||||
row += " N/A "
|
||||
print(row)
|
||||
print("\n * = vizuálně podobné fotky (možná duplikát po editaci)")
|
||||
print()
|
||||
|
||||
|
||||
def main():
|
||||
if not PHOTOS_DIR.exists():
|
||||
print(f"[ERROR] Složka neexistuje: {PHOTOS_DIR}")
|
||||
return
|
||||
|
||||
files = sorted([p for p in PHOTOS_DIR.iterdir()
|
||||
if p.is_file() and p.suffix.lower() in {".jpg", ".jpeg", ".png", ".heic", ".tiff", ".tif", ".webp"}])
|
||||
|
||||
if not files:
|
||||
print(f"[WARN] Žádné fotky v {PHOTOS_DIR}")
|
||||
return
|
||||
|
||||
print(f"Nalezeno {len(files)} fotek v {PHOTOS_DIR}\n")
|
||||
|
||||
photos = []
|
||||
for f in files:
|
||||
print(f" zpracovávám: {f.name} ...", end=" ", flush=True)
|
||||
try:
|
||||
photos.append(explore_photo(f))
|
||||
print("OK")
|
||||
except Exception as e:
|
||||
print(f"FAIL: {e}")
|
||||
|
||||
print_summary(photos)
|
||||
|
||||
# Uložit do JSON pro detailní analýzu
|
||||
with open(OUTPUT_JSON, "w", encoding="utf-8") as f:
|
||||
json.dump(photos, f, indent=2, ensure_ascii=False, default=str)
|
||||
print(f"\n[OK] Detailní data uložena: {OUTPUT_JSON}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,906 @@
|
||||
[
|
||||
{
|
||||
"filesystem": {
|
||||
"file_name": "2026-04-22 09.05.08.jpg",
|
||||
"file_path": "U:\\PycharmProjects\\FotkyBuzalkovi\\demo_fotky\\2026-04-22 09.05.08.jpg",
|
||||
"file_size_bytes": 10186179,
|
||||
"file_size_mb": 9.71,
|
||||
"mtime": "2026-04-22T09:05:08",
|
||||
"ctime": "2026-05-19T06:22:12.659966",
|
||||
"extension": ".jpg"
|
||||
},
|
||||
"hashes": {
|
||||
"sha256_file": "4ea38e22f815c4512e6bfe06d9203180e5920ac7324d2e0e9271e918d53adff5",
|
||||
"sha256_pixels": "b95b72d63a300cde544091c11f8e884896d583afa0dc380cdebc47b3ade8d05f",
|
||||
"phash": "f7a2c8606d4c76d4",
|
||||
"dhash": "c4884c4c4c4cc010",
|
||||
"ahash": "feffe6a702246098",
|
||||
"whash": "feffe7a702006098"
|
||||
},
|
||||
"pillow": {
|
||||
"format": "JPEG",
|
||||
"mode": "RGB",
|
||||
"width": 5712,
|
||||
"height": 4284,
|
||||
"megapixels": 24.47,
|
||||
"has_transparency": false,
|
||||
"dpi": [
|
||||
"72.0",
|
||||
"72.0"
|
||||
],
|
||||
"icc_profile_present": true,
|
||||
"exif_present": true,
|
||||
"xmp_snippet": "<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?> <x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"XMP Core 6.0.0\"> <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"> <rdf:Description rdf:about=\"\" xmlns:exif=\"http://ns.adobe.com/exif/1.0/\" xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\" xmlns:tiff=\"http://ns.adobe.com/tiff/1.0/\" xmlns:exifEX=\"http://cipa.jp/exif/1.0/\" xmlns:mwg-rs=\"http://www.metadataworkinggroup.com/schemas/regions/\" xmlns:stDim=\"http://ns.adobe.com/xap/1.0/sType/Dimens",
|
||||
"has_embedded_thumbnail": false
|
||||
},
|
||||
"exif_pillow": {
|
||||
"_error": "'int' object has no attribute 'items'"
|
||||
},
|
||||
"exif_exifread": {
|
||||
"Image Make": "Apple",
|
||||
"Image Model": "iPhone 16 Pro Max",
|
||||
"Image Orientation": "Rotated 90 CW",
|
||||
"Image XResolution": "72",
|
||||
"Image YResolution": "72",
|
||||
"Image ResolutionUnit": "Pixels/Inch",
|
||||
"Image Software": "26.3.1",
|
||||
"Image DateTime": "2026:04:22 09:05:07",
|
||||
"Image HostComputer": "iPhone 16 Pro Max",
|
||||
"Image ExifOffset": "232",
|
||||
"GPS GPSLatitudeRef": "N",
|
||||
"GPS GPSLatitude": "[50, 5, 1009/100]",
|
||||
"GPS GPSLongitudeRef": "E",
|
||||
"GPS GPSLongitude": "[14, 24, 3089/100]",
|
||||
"GPS GPSAltitudeRef": "0",
|
||||
"GPS GPSAltitude": "299875/1571",
|
||||
"GPS GPSTimeStamp": "[7, 5, 6]",
|
||||
"GPS GPSSpeedRef": "K",
|
||||
"GPS GPSSpeed": "0",
|
||||
"GPS GPSImgDirectionRef": "T",
|
||||
"GPS GPSImgDirection": "379301/2482",
|
||||
"GPS GPSDestBearingRef": "T",
|
||||
"GPS GPSDestBearing": "379301/2482",
|
||||
"GPS GPSDate": "2026:04:22",
|
||||
"GPS Tag 0x001F": "43090/3283",
|
||||
"Image GPSInfo": "2808",
|
||||
"Thumbnail JPEGInterchangeFormat": "3224",
|
||||
"Thumbnail JPEGInterchangeFormatLength": "10108",
|
||||
"EXIF ExposureTime": "1/715",
|
||||
"EXIF FNumber": "1244236/699009",
|
||||
"EXIF ExposureProgram": "Program Normal",
|
||||
"EXIF ISOSpeedRatings": "80",
|
||||
"EXIF ExifVersion": "0232",
|
||||
"EXIF DateTimeOriginal": "2026:04:22 09:05:07",
|
||||
"EXIF DateTimeDigitized": "2026:04:22 09:05:07",
|
||||
"EXIF OffsetTime": "+02:00",
|
||||
"EXIF OffsetTimeOriginal": "+02:00",
|
||||
"EXIF OffsetTimeDigitized": "+02:00",
|
||||
"EXIF ComponentsConfiguration": "YCbCr",
|
||||
"EXIF ShutterSpeedValue": "18849/1988",
|
||||
"EXIF ApertureValue": "42657/25639",
|
||||
"EXIF BrightnessValue": "72829/10013",
|
||||
"EXIF ExposureBiasValue": "0",
|
||||
"EXIF MeteringMode": "Pattern",
|
||||
"EXIF Flash": "Flash did not fire, compulsory flash mode",
|
||||
"EXIF FocalLength": "251773/37217",
|
||||
"EXIF SubjectArea": "[1375, 2179, 413, 416]",
|
||||
"EXIF MakerNote": "[65, 112, 112, 108, 101, 32, 105, 79, 83, 0, 0, 1, 77, 77, 0, 59, 0, 1, 0, 9, ... ]",
|
||||
"EXIF SubSecTimeOriginal": "565",
|
||||
"EXIF SubSecTimeDigitized": "565",
|
||||
"EXIF FlashPixVersion": "0100",
|
||||
"EXIF ColorSpace": "Uncalibrated",
|
||||
"EXIF ExifImageWidth": "5712",
|
||||
"EXIF ExifImageLength": "4284",
|
||||
"EXIF SensingMethod": "One-chip color area",
|
||||
"EXIF SceneType": "Directly Photographed",
|
||||
"EXIF ExposureMode": "Auto Exposure",
|
||||
"EXIF WhiteBalance": "Auto",
|
||||
"EXIF FocalLengthIn35mmFilm": "24",
|
||||
"EXIF SceneCaptureType": "Standard",
|
||||
"EXIF LensSpecification": "[253126/37417, 2052196/131047, 1244236/699009, 14/5]",
|
||||
"EXIF LensMake": "Apple",
|
||||
"EXIF LensModel": "iPhone 16 Pro Max back triple camera 6.765mm f/1.78",
|
||||
"EXIF Tag 0xA460": "2",
|
||||
"MakerNote MakerNoteVersion": "16",
|
||||
"MakerNote Tag 0x0002": "[161, 0, 127, 0, 112, 0, 61, 0, 40, 0, 49, 0, 45, 0, 10, 0, 31, 0, 213, 1, ... ]",
|
||||
"MakerNote Tag 0x0003": "[6, 7, 8, 85, 102, 108, 97, 103, 115, 85, 118, 97, 108, 117, 101, 89, 116, 105, 109, 101, ... ]",
|
||||
"MakerNote AEStable": "No",
|
||||
"MakerNote AETarget": "188",
|
||||
"MakerNote AEAverage": "204",
|
||||
"MakerNote AFStable": "Yes",
|
||||
"MakerNote Tag 0x0008": "[-856227839/729350144, -1321/103, 64/3]",
|
||||
"MakerNote Tag 0x000C": "[279109/1162032945, 876031301/809906477]",
|
||||
"MakerNote Tag 0x000D": "41",
|
||||
"MakerNote Tag 0x000E": "0",
|
||||
"MakerNote Tag 0x0010": "1",
|
||||
"MakerNote Tag 0x0011": "4E88-B357-FC9658AA6BCC",
|
||||
"MakerNote ImageCaptureType": "Scene",
|
||||
"MakerNote Tag 0x0019": "19013666",
|
||||
"MakerNote Tag 0x001A": "8D88B1",
|
||||
"MakerNote Tag 0x001D": "842542391/1128675373",
|
||||
"MakerNote Tag 0x001F": "1",
|
||||
"MakerNote Tag 0x0020": "497E-A420-FA5685058AE3",
|
||||
"MakerNote Tag 0x0021": "106496/43",
|
||||
"MakerNote Tag 0x0023": "[277217292, 1443889152]",
|
||||
"MakerNote Tag 0x0026": "3",
|
||||
"MakerNote Tag 0x0027": "909192513/926431021",
|
||||
"MakerNote Tag 0x002B": "459C-B603-F499EADDB45A",
|
||||
"MakerNote Tag 0x002D": "5227",
|
||||
"MakerNote CameraType": "Back Normal",
|
||||
"MakerNote Tag 0x002F": "51",
|
||||
"MakerNote Tag 0x0030": "71686300/454712541",
|
||||
"MakerNote Tag 0x0036": "13797",
|
||||
"MakerNote Tag 0x0037": "8",
|
||||
"MakerNote Tag 0x0038": "121",
|
||||
"MakerNote Tag 0x0039": "1",
|
||||
"MakerNote Tag 0x003A": "164",
|
||||
"MakerNote Tag 0x003B": "0",
|
||||
"MakerNote Tag 0x003C": "4",
|
||||
"MakerNote Tag 0x003D": "100",
|
||||
"MakerNote Tag 0x003F": "0",
|
||||
"MakerNote Tag 0x0041": "0",
|
||||
"MakerNote Tag 0x0042": "0",
|
||||
"MakerNote Tag 0x0043": "0",
|
||||
"MakerNote Tag 0x0044": "0",
|
||||
"MakerNote Tag 0x0045": "0",
|
||||
"MakerNote Tag 0x0046": "0",
|
||||
"MakerNote Tag 0x0048": "0",
|
||||
"MakerNote Tag 0x0049": "0",
|
||||
"MakerNote Tag 0x004A": "2",
|
||||
"MakerNote Tag 0x004D": "808505857/33752145",
|
||||
"MakerNote Tag 0x004E": "[49, 81, 50, 16, 3, 162, 5, 10, 210, 6, 7, 8, 9, 83, 50, 46, 49, 83, 50, 46, ... ]",
|
||||
"MakerNote Tag 0x004F": "[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 98, 112, 108, 105, 115, 116, 48, 48, 216, 1, 2, 3, 4, 5]",
|
||||
"MakerNote Tag 0x0052": "3",
|
||||
"MakerNote Tag 0x0053": "2",
|
||||
"MakerNote Tag 0x0054": "[6, 7, 8, 9, 10, 11, 11, 11, 12, 13, 12, 81, 55, 81, 51, 81, 52, 81, 48, 81, ... ]",
|
||||
"MakerNote Tag 0x0055": "126",
|
||||
"MakerNote Tag 0x0058": "2307",
|
||||
"MakerNote Tag 0x005A": "[6, 7, 8, 7, 9, 81, 51, 81, 49, 81, 52, 81, 50, 81, 48, 34, 60, 189, 98, 49, ... ]",
|
||||
"MakerNote Tag 0x0060": "2048",
|
||||
"MakerNote Tag 0x0061": "24"
|
||||
},
|
||||
"iptc": {},
|
||||
"xmp": {
|
||||
"creator_tool": "26.3.1",
|
||||
"create_date": "2026-04-22T09:05:07.565",
|
||||
"modify_date": "2026-04-22T09:05:07",
|
||||
"face_regions_count": 1,
|
||||
"_xmp_length_bytes": 6047
|
||||
}
|
||||
},
|
||||
{
|
||||
"filesystem": {
|
||||
"file_name": "2026-04-24 15.15.47.jpg",
|
||||
"file_path": "U:\\PycharmProjects\\FotkyBuzalkovi\\demo_fotky\\2026-04-24 15.15.47.jpg",
|
||||
"file_size_bytes": 5928247,
|
||||
"file_size_mb": 5.65,
|
||||
"mtime": "2026-04-24T15:15:47",
|
||||
"ctime": "2026-05-19T06:22:06.110438",
|
||||
"extension": ".jpg"
|
||||
},
|
||||
"hashes": {
|
||||
"sha256_file": "500ac874b758feb80f02d5c95d7cb60fd3d651de6220631e9e836c0e9efcf9bf",
|
||||
"sha256_pixels": "48e05ab5ee5e532117c76d7f6000ede03c1e382ebdb90e22b3df158a90e3933e",
|
||||
"phash": "e99c96b8b493a4b4",
|
||||
"dhash": "182062829393cb4e",
|
||||
"ahash": "fff8f8f0c1c1e0e3",
|
||||
"whash": "fff8f8e0c0c0e0e1"
|
||||
},
|
||||
"pillow": {
|
||||
"format": "JPEG",
|
||||
"mode": "RGB",
|
||||
"width": 4032,
|
||||
"height": 3024,
|
||||
"megapixels": 12.19,
|
||||
"has_transparency": false,
|
||||
"dpi": [
|
||||
"72.0",
|
||||
"72.0"
|
||||
],
|
||||
"icc_profile_present": true,
|
||||
"exif_present": true,
|
||||
"has_embedded_thumbnail": false
|
||||
},
|
||||
"exif_pillow": {
|
||||
"ResolutionUnit": 2.0,
|
||||
"ExifOffset": 232.0,
|
||||
"Make": "Apple",
|
||||
"Model": "iPhone 13 Pro Max",
|
||||
"Software": "26.4.1",
|
||||
"Orientation": 1.0,
|
||||
"DateTime": "2026:04:24 15:15:46",
|
||||
"YCbCrPositioning": 1.0,
|
||||
"XResolution": 72.0,
|
||||
"YResolution": 72.0,
|
||||
"HostComputer": "iPhone 13 Pro Max"
|
||||
},
|
||||
"exif_exifread": {
|
||||
"Image Make": "Apple",
|
||||
"Image Model": "iPhone 13 Pro Max",
|
||||
"Image Orientation": "Horizontal (normal)",
|
||||
"Image XResolution": "72",
|
||||
"Image YResolution": "72",
|
||||
"Image ResolutionUnit": "Pixels/Inch",
|
||||
"Image Software": "26.4.1",
|
||||
"Image DateTime": "2026:04:24 15:15:46",
|
||||
"Image HostComputer": "iPhone 13 Pro Max",
|
||||
"Image YCbCrPositioning": "Centered",
|
||||
"Image ExifOffset": "232",
|
||||
"Thumbnail JPEGInterchangeFormat": "2750",
|
||||
"Thumbnail JPEGInterchangeFormatLength": "7338",
|
||||
"EXIF ExposureTime": "1/184",
|
||||
"EXIF FNumber": "3/2",
|
||||
"EXIF ExposureProgram": "Program Normal",
|
||||
"EXIF ISOSpeedRatings": "40",
|
||||
"EXIF ExifVersion": "0232",
|
||||
"EXIF DateTimeOriginal": "2026:04:24 15:15:46",
|
||||
"EXIF DateTimeDigitized": "2026:04:24 15:15:46",
|
||||
"EXIF OffsetTime": "+02:00",
|
||||
"EXIF OffsetTimeOriginal": "+02:00",
|
||||
"EXIF OffsetTimeDigitized": "+02:00",
|
||||
"EXIF ComponentsConfiguration": "YCbCr",
|
||||
"EXIF ShutterSpeedValue": "83635/11111",
|
||||
"EXIF ApertureValue": "27767/23734",
|
||||
"EXIF BrightnessValue": "80499/13364",
|
||||
"EXIF ExposureBiasValue": "0",
|
||||
"EXIF MeteringMode": "Pattern",
|
||||
"EXIF Flash": "Flash did not fire, compulsory flash mode",
|
||||
"EXIF FocalLength": "57/10",
|
||||
"EXIF SubjectArea": "[2014, 1508, 2218, 1328]",
|
||||
"EXIF MakerNote": "[65, 112, 112, 108, 101, 32, 105, 79, 83, 0, 0, 1, 77, 77, 0, 60, 0, 1, 0, 9, ... ]",
|
||||
"EXIF SubSecTimeOriginal": "964",
|
||||
"EXIF SubSecTimeDigitized": "964",
|
||||
"EXIF FlashPixVersion": "0100",
|
||||
"EXIF ColorSpace": "Uncalibrated",
|
||||
"EXIF ExifImageWidth": "4032",
|
||||
"EXIF ExifImageLength": "3024",
|
||||
"EXIF SensingMethod": "One-chip color area",
|
||||
"EXIF SceneType": "Directly Photographed",
|
||||
"EXIF ExposureMode": "Auto Exposure",
|
||||
"EXIF WhiteBalance": "Auto",
|
||||
"EXIF FocalLengthIn35mmFilm": "26",
|
||||
"EXIF SceneCaptureType": "Standard",
|
||||
"EXIF LensSpecification": "[299253/190607, 9, 3/2, 14/5]",
|
||||
"EXIF LensMake": "Apple",
|
||||
"EXIF LensModel": "iPhone 13 Pro Max back triple camera 5.7mm f/1.5",
|
||||
"EXIF Tag 0xA460": "2",
|
||||
"MakerNote MakerNoteVersion": "16",
|
||||
"MakerNote Tag 0x0002": "[171, 1, 108, 1, 146, 1, 148, 1, 102, 1, 61, 1, 15, 1, 225, 0, 191, 0, 107, 2, ... ]",
|
||||
"MakerNote Tag 0x0003": "[6, 7, 8, 85, 102, 108, 97, 103, 115, 85, 118, 97, 108, 117, 101, 89, 116, 105, 109, 101, ... ]",
|
||||
"MakerNote AEStable": "Yes",
|
||||
"MakerNote AETarget": "199",
|
||||
"MakerNote AEAverage": "208",
|
||||
"MakerNote AFStable": "Yes",
|
||||
"MakerNote Tag 0x0008": "[401975979/194379776, 22723/23, 256/9]",
|
||||
"MakerNote Tag 0x000C": "[16384/1061, 67112487/105295456]",
|
||||
"MakerNote Tag 0x000D": "34",
|
||||
"MakerNote Tag 0x000E": "0",
|
||||
"MakerNote Tag 0x0010": "1",
|
||||
"MakerNote ImageCaptureType": "Photo",
|
||||
"MakerNote Tag 0x0019": "2",
|
||||
"MakerNote Tag 0x001A": "-9193-",
|
||||
"MakerNote Tag 0x001F": "0",
|
||||
"MakerNote Tag 0x0020": "4018-B96D-3A65CF0E00D6",
|
||||
"MakerNote Tag 0x0021": "2228224/0",
|
||||
"MakerNote Tag 0x0023": "[8781826, -950272000]",
|
||||
"MakerNote Tag 0x0026": "3",
|
||||
"MakerNote Tag 0x0027": "163616959/158636587",
|
||||
"MakerNote Tag 0x0028": "1",
|
||||
"MakerNote Tag 0x002B": "443A-AA33-717906FF9D4E",
|
||||
"MakerNote Tag 0x002D": "5365",
|
||||
"MakerNote CameraType": "Back Normal",
|
||||
"MakerNote Tag 0x002F": "71",
|
||||
"MakerNote Tag 0x0030": "808506369/33752069",
|
||||
"MakerNote Tag 0x0033": "4096",
|
||||
"MakerNote Tag 0x0034": "4",
|
||||
"MakerNote Tag 0x0035": "3",
|
||||
"MakerNote Tag 0x0036": "4214",
|
||||
"MakerNote Tag 0x0037": "4",
|
||||
"MakerNote Tag 0x0038": "121",
|
||||
"MakerNote Tag 0x0039": "0",
|
||||
"MakerNote Tag 0x003A": "0",
|
||||
"MakerNote Tag 0x003B": "0",
|
||||
"MakerNote Tag 0x003C": "4",
|
||||
"MakerNote Tag 0x003D": "34",
|
||||
"MakerNote Tag 0x003F": "45",
|
||||
"MakerNote Tag 0x0040": "[6, 6, 7, 81, 51, 81, 49, 81, 50, 81, 48, 16, 0, 34, 0, 0, 0, 0, 16, 1, ... ]",
|
||||
"MakerNote Tag 0x0041": "0",
|
||||
"MakerNote Tag 0x0042": "0",
|
||||
"MakerNote Tag 0x0043": "0",
|
||||
"MakerNote Tag 0x0044": "0",
|
||||
"MakerNote Tag 0x0045": "0",
|
||||
"MakerNote Tag 0x0046": "0",
|
||||
"MakerNote Tag 0x0048": "570",
|
||||
"MakerNote Tag 0x0049": "0",
|
||||
"MakerNote Tag 0x004A": "2",
|
||||
"MakerNote Tag 0x004D": "808505857/33752145",
|
||||
"MakerNote Tag 0x004E": "[49, 81, 50, 16, 3, 162, 5, 10, 210, 6, 7, 8, 9, 83, 50, 46, 49, 83, 50, 46, ... ]",
|
||||
"MakerNote Tag 0x004F": "[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 4, 144, 245, 0, 2, 232, 143, 0, 0, 0, 9, 0, 0]",
|
||||
"MakerNote Tag 0x0052": "3",
|
||||
"MakerNote Tag 0x0053": "1",
|
||||
"MakerNote Tag 0x0055": "0",
|
||||
"MakerNote Tag 0x0058": "1795",
|
||||
"MakerNote Tag 0x0060": "11057",
|
||||
"MakerNote Tag 0x0061": "26"
|
||||
},
|
||||
"iptc": {},
|
||||
"xmp": {}
|
||||
},
|
||||
{
|
||||
"filesystem": {
|
||||
"file_name": "2026-05-02 10.04.44.png",
|
||||
"file_path": "U:\\PycharmProjects\\FotkyBuzalkovi\\demo_fotky\\2026-05-02 10.04.44.png",
|
||||
"file_size_bytes": 652043,
|
||||
"file_size_mb": 0.62,
|
||||
"mtime": "2026-05-02T10:04:44",
|
||||
"ctime": "2026-05-19T06:22:01.483987",
|
||||
"extension": ".png"
|
||||
},
|
||||
"hashes": {
|
||||
"sha256_file": "bfbebc9c3db1b1c50af4925c7208c422425e637da1b497271096e298382ca2c3",
|
||||
"sha256_pixels": "53bb4fd7cb92bb3e709f3bef385324034ed608a0fb23f54de1f5b5d1c3b3fa67",
|
||||
"phash": "8f4be06bd2f0161e",
|
||||
"dhash": "4b6b755d7b6f6fea",
|
||||
"ahash": "f9b91fff17839fff",
|
||||
"whash": "b8980fef030303ff"
|
||||
},
|
||||
"pillow": {
|
||||
"format": "PNG",
|
||||
"mode": "RGB",
|
||||
"width": 1284,
|
||||
"height": 2778,
|
||||
"megapixels": 3.57,
|
||||
"has_transparency": false,
|
||||
"dpi": [
|
||||
143.99259999999998,
|
||||
143.99259999999998
|
||||
],
|
||||
"icc_profile_present": false,
|
||||
"exif_present": true,
|
||||
"xmp_snippet": "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"XMP Core 6.0.0\">\n <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n <rdf:Description rdf:about=\"\"\n xmlns:exif=\"http://ns.adobe.com/exif/1.0/\"\n xmlns:photoshop=\"http://ns.adobe.com/photoshop/1.0/\"\n xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\"\n xmlns:tiff=\"http://ns.adobe.com/tiff/1.0/\"\n xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n <exif:UserComment>Screenshot</exif:User",
|
||||
"has_embedded_thumbnail": false
|
||||
},
|
||||
"exif_pillow": {
|
||||
"ResolutionUnit": 2.0,
|
||||
"ExifOffset": 146.0,
|
||||
"ImageDescription": "Screenshot",
|
||||
"Orientation": 1.0,
|
||||
"DateTime": "2026:05:02 10:04:44",
|
||||
"XResolution": 144.0,
|
||||
"YResolution": 144.0
|
||||
},
|
||||
"exif_exifread": {
|
||||
"Image ImageDescription": "Screenshot",
|
||||
"Image Orientation": "Horizontal (normal)",
|
||||
"Image XResolution": "144",
|
||||
"Image YResolution": "144",
|
||||
"Image ResolutionUnit": "Pixels/Inch",
|
||||
"Image DateTime": "2026:05:02 10:04:44",
|
||||
"Image ExifOffset": "146",
|
||||
"EXIF DateTimeOriginal": "2026:05:02 10:04:44",
|
||||
"EXIF UserComment": "Screenshot",
|
||||
"EXIF ColorSpace": "sRGB",
|
||||
"EXIF ExifImageWidth": "1284",
|
||||
"EXIF ExifImageLength": "2778"
|
||||
},
|
||||
"iptc": {},
|
||||
"xmp": {
|
||||
"description": "Screenshot",
|
||||
"_xmp_length_bytes": 909
|
||||
}
|
||||
},
|
||||
{
|
||||
"filesystem": {
|
||||
"file_name": "2026-05-18 06.22.37.jpg",
|
||||
"file_path": "U:\\PycharmProjects\\FotkyBuzalkovi\\demo_fotky\\2026-05-18 06.22.37.jpg",
|
||||
"file_size_bytes": 9331138,
|
||||
"file_size_mb": 8.9,
|
||||
"mtime": "2026-05-18T06:22:37",
|
||||
"ctime": "2026-05-19T06:21:53.390486",
|
||||
"extension": ".jpg"
|
||||
},
|
||||
"hashes": {
|
||||
"sha256_file": "9b9395396fd7893cdcdc69703a9e8e331bd93ce64da53ef9b5b25f3d786036ed",
|
||||
"sha256_pixels": "47d95e29f8972b2d4d8f4f28b42a335bac4a629248486bc2ad1694467d1d4630",
|
||||
"phash": "edcc9e48e832b5a4",
|
||||
"dhash": "a2e2c68383d6d002",
|
||||
"ahash": "f8f8f3f1f0600080",
|
||||
"whash": "f8f8fbf1f06000f0"
|
||||
},
|
||||
"pillow": {
|
||||
"format": "JPEG",
|
||||
"mode": "RGB",
|
||||
"width": 4032,
|
||||
"height": 3024,
|
||||
"megapixels": 12.19,
|
||||
"has_transparency": false,
|
||||
"dpi": [
|
||||
"72.0",
|
||||
"72.0"
|
||||
],
|
||||
"icc_profile_present": true,
|
||||
"exif_present": true,
|
||||
"xmp_snippet": "<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?> <x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"XMP Core 6.0.0\"> <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"> <rdf:Description rdf:about=\"\" xmlns:exif=\"http://ns.adobe.com/exif/1.0/\" xmlns:exifEX=\"http://cipa.jp/exif/1.0/\" xmlns:tiff=\"http://ns.adobe.com/tiff/1.0/\" xmlns:photoshop=\"http://ns.adobe.com/photoshop/1.0/\" xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\" xmlns:mwg-rs=\"http://www.metadataworkinggroup.com/schemas/regions/\" ",
|
||||
"has_embedded_thumbnail": false
|
||||
},
|
||||
"exif_pillow": {
|
||||
"ResolutionUnit": 2.0,
|
||||
"ExifOffset": 220.0,
|
||||
"Make": "Apple",
|
||||
"Model": "iPhone 13 Pro Max",
|
||||
"Software": "26.4.2",
|
||||
"Orientation": 6.0,
|
||||
"DateTime": "2026:05:18 06:22:37",
|
||||
"XResolution": 72.0,
|
||||
"YResolution": 72.0,
|
||||
"HostComputer": "iPhone 13 Pro Max"
|
||||
},
|
||||
"exif_exifread": {
|
||||
"Image Make": "Apple",
|
||||
"Image Model": "iPhone 13 Pro Max",
|
||||
"Image Orientation": "Rotated 90 CW",
|
||||
"Image XResolution": "72",
|
||||
"Image YResolution": "72",
|
||||
"Image ResolutionUnit": "Pixels/Inch",
|
||||
"Image Software": "26.4.2",
|
||||
"Image DateTime": "2026:05:18 06:22:37",
|
||||
"Image HostComputer": "iPhone 13 Pro Max",
|
||||
"Image ExifOffset": "220",
|
||||
"Thumbnail JPEGInterchangeFormat": "2776",
|
||||
"Thumbnail JPEGInterchangeFormatLength": "7602",
|
||||
"EXIF ExposureTime": "1/50",
|
||||
"EXIF FNumber": "3/2",
|
||||
"EXIF ExposureProgram": "Program Normal",
|
||||
"EXIF ISOSpeedRatings": "200",
|
||||
"EXIF ExifVersion": "0232",
|
||||
"EXIF DateTimeOriginal": "2026:05:18 06:22:37",
|
||||
"EXIF DateTimeDigitized": "2026:05:18 06:22:37",
|
||||
"EXIF OffsetTime": "+02:00",
|
||||
"EXIF OffsetTimeOriginal": "+02:00",
|
||||
"EXIF OffsetTimeDigitized": "+02:00",
|
||||
"EXIF ComponentsConfiguration": "YCbCr",
|
||||
"EXIF ShutterSpeedValue": "48307/8559",
|
||||
"EXIF ApertureValue": "27767/23734",
|
||||
"EXIF BrightnessValue": "22485/14578",
|
||||
"EXIF ExposureBiasValue": "0",
|
||||
"EXIF MeteringMode": "Pattern",
|
||||
"EXIF Flash": "Flash did not fire, compulsory flash mode",
|
||||
"EXIF FocalLength": "57/10",
|
||||
"EXIF SubjectArea": "[1000, 1528, 190, 191]",
|
||||
"EXIF MakerNote": "[65, 112, 112, 108, 101, 32, 105, 79, 83, 0, 0, 1, 77, 77, 0, 59, 0, 1, 0, 9, ... ]",
|
||||
"EXIF SubSecTimeOriginal": "375",
|
||||
"EXIF SubSecTimeDigitized": "375",
|
||||
"EXIF FlashPixVersion": "0100",
|
||||
"EXIF ColorSpace": "Uncalibrated",
|
||||
"EXIF ExifImageWidth": "4032",
|
||||
"EXIF ExifImageLength": "3024",
|
||||
"EXIF SensingMethod": "One-chip color area",
|
||||
"EXIF SceneType": "Directly Photographed",
|
||||
"EXIF ExposureMode": "Auto Exposure",
|
||||
"EXIF WhiteBalance": "Auto",
|
||||
"EXIF FocalLengthIn35mmFilm": "26",
|
||||
"EXIF SceneCaptureType": "Standard",
|
||||
"EXIF LensSpecification": "[299253/190607, 9, 3/2, 14/5]",
|
||||
"EXIF LensMake": "Apple",
|
||||
"EXIF LensModel": "iPhone 13 Pro Max back triple camera 5.7mm f/1.5",
|
||||
"EXIF Tag 0xA460": "2",
|
||||
"MakerNote MakerNoteVersion": "16",
|
||||
"MakerNote Tag 0x0002": "[22, 2, 104, 2, 90, 1, 152, 0, 121, 0, 109, 0, 108, 0, 118, 0, 121, 0, 139, 0, ... ]",
|
||||
"MakerNote Tag 0x0003": "[6, 7, 8, 85, 102, 108, 97, 103, 115, 85, 118, 97, 108, 117, 101, 89, 116, 105, 109, 101, ... ]",
|
||||
"MakerNote AEStable": "Yes",
|
||||
"MakerNote AETarget": "192",
|
||||
"MakerNote AEAverage": "184",
|
||||
"MakerNote AFStable": "Yes",
|
||||
"MakerNote Tag 0x0008": "[653568683/78381056, 13267/125, 256/55]",
|
||||
"MakerNote Tag 0x000C": "[2103323/437786648, 314292673/392696335]",
|
||||
"MakerNote Tag 0x000D": "24",
|
||||
"MakerNote Tag 0x000E": "0",
|
||||
"MakerNote Tag 0x0010": "1",
|
||||
"MakerNote Tag 0x0011": "4FAB-8319-C67E13D5DB53",
|
||||
"MakerNote ImageCaptureType": "Scene",
|
||||
"MakerNote Tag 0x0019": "8194",
|
||||
"MakerNote Tag 0x001A": "-BB21-",
|
||||
"MakerNote Tag 0x001F": "0",
|
||||
"MakerNote Tag 0x0020": "497C-BF6F-D6B9ACA3BAEA",
|
||||
"MakerNote Tag 0x0021": "2818048/0",
|
||||
"MakerNote Tag 0x0023": "[344850434, -1100677120]",
|
||||
"MakerNote Tag 0x0026": "3",
|
||||
"MakerNote Tag 0x0027": "910503235/1177825837",
|
||||
"MakerNote Tag 0x002B": "45D3-801F-A154352C61C6",
|
||||
"MakerNote Tag 0x002D": "3476",
|
||||
"MakerNote CameraType": "Back Normal",
|
||||
"MakerNote Tag 0x002F": "50",
|
||||
"MakerNote Tag 0x0030": "808506369/33752069",
|
||||
"MakerNote Tag 0x0033": "12288",
|
||||
"MakerNote Tag 0x0034": "5",
|
||||
"MakerNote Tag 0x0035": "4",
|
||||
"MakerNote Tag 0x0036": "179",
|
||||
"MakerNote Tag 0x0037": "4",
|
||||
"MakerNote Tag 0x0038": "201",
|
||||
"MakerNote Tag 0x0039": "1",
|
||||
"MakerNote Tag 0x003A": "133",
|
||||
"MakerNote Tag 0x003B": "0",
|
||||
"MakerNote Tag 0x003C": "4",
|
||||
"MakerNote Tag 0x003D": "33",
|
||||
"MakerNote Tag 0x0040": "[6, 6, 7, 81, 51, 81, 49, 81, 50, 81, 48, 16, 0, 34, 0, 0, 0, 0, 16, 1, ... ]",
|
||||
"MakerNote Tag 0x0041": "0",
|
||||
"MakerNote Tag 0x0042": "0",
|
||||
"MakerNote Tag 0x0043": "0",
|
||||
"MakerNote Tag 0x0044": "0",
|
||||
"MakerNote Tag 0x0045": "0",
|
||||
"MakerNote Tag 0x0046": "0",
|
||||
"MakerNote Tag 0x0048": "569",
|
||||
"MakerNote Tag 0x0049": "0",
|
||||
"MakerNote Tag 0x004A": "2",
|
||||
"MakerNote Tag 0x004D": "808505857/33752145",
|
||||
"MakerNote Tag 0x004E": "[49, 81, 50, 16, 1, 162, 5, 10, 210, 6, 7, 8, 9, 83, 50, 46, 49, 83, 50, 46, ... ]",
|
||||
"MakerNote Tag 0x004F": "[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 4, 144, 245, 0, 2, 232, 143, 0, 0, 0, 9, 0]",
|
||||
"MakerNote Tag 0x0052": "3",
|
||||
"MakerNote Tag 0x0053": "0",
|
||||
"MakerNote Tag 0x0055": "174",
|
||||
"MakerNote Tag 0x0058": "1795",
|
||||
"MakerNote Tag 0x0060": "6424",
|
||||
"MakerNote Tag 0x0061": "26"
|
||||
},
|
||||
"iptc": {},
|
||||
"xmp": {
|
||||
"creator_tool": "26.4.2",
|
||||
"create_date": "2026-05-18T06:22:37.375",
|
||||
"modify_date": "2026-05-18T06:22:37",
|
||||
"face_regions_count": 1,
|
||||
"_xmp_length_bytes": 5345
|
||||
}
|
||||
},
|
||||
{
|
||||
"filesystem": {
|
||||
"file_name": "2026-05-18 06.22.41.jpg",
|
||||
"file_path": "U:\\PycharmProjects\\FotkyBuzalkovi\\demo_fotky\\2026-05-18 06.22.41.jpg",
|
||||
"file_size_bytes": 8328001,
|
||||
"file_size_mb": 7.94,
|
||||
"mtime": "2026-05-18T06:22:41",
|
||||
"ctime": "2026-05-19T06:21:46.033863",
|
||||
"extension": ".jpg"
|
||||
},
|
||||
"hashes": {
|
||||
"sha256_file": "e22b409fecfd997585b8bb16850c8568e876b780d54d091fc086803c5e884c80",
|
||||
"sha256_pixels": "3fb2350a514b8840984fbb8e85e0aad834a670f14d01aef56ce07d1dbb1d6c62",
|
||||
"phash": "e9cc9e496a32b5a4",
|
||||
"dhash": "a2e2c68383d2d002",
|
||||
"ahash": "f8f8f3f1f0600080",
|
||||
"whash": "f8f8fbf1f16000b0"
|
||||
},
|
||||
"pillow": {
|
||||
"format": "JPEG",
|
||||
"mode": "RGB",
|
||||
"width": 4032,
|
||||
"height": 3024,
|
||||
"megapixels": 12.19,
|
||||
"has_transparency": false,
|
||||
"dpi": [
|
||||
"72.0",
|
||||
"72.0"
|
||||
],
|
||||
"icc_profile_present": true,
|
||||
"exif_present": true,
|
||||
"xmp_snippet": "<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?> <x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"XMP Core 6.0.0\"> <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"> <rdf:Description rdf:about=\"\" xmlns:exif=\"http://ns.adobe.com/exif/1.0/\" xmlns:exifEX=\"http://cipa.jp/exif/1.0/\" xmlns:tiff=\"http://ns.adobe.com/tiff/1.0/\" xmlns:photoshop=\"http://ns.adobe.com/photoshop/1.0/\" xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\" xmlns:mwg-rs=\"http://www.metadataworkinggroup.com/schemas/regions/\" ",
|
||||
"has_embedded_thumbnail": false
|
||||
},
|
||||
"exif_pillow": {
|
||||
"ResolutionUnit": 2.0,
|
||||
"ExifOffset": 220.0,
|
||||
"Make": "Apple",
|
||||
"Model": "iPhone 13 Pro Max",
|
||||
"Software": "26.4.2",
|
||||
"Orientation": 6.0,
|
||||
"DateTime": "2026:05:18 06:22:41",
|
||||
"XResolution": 72.0,
|
||||
"YResolution": 72.0,
|
||||
"HostComputer": "iPhone 13 Pro Max"
|
||||
},
|
||||
"exif_exifread": {
|
||||
"Image Make": "Apple",
|
||||
"Image Model": "iPhone 13 Pro Max",
|
||||
"Image Orientation": "Rotated 90 CW",
|
||||
"Image XResolution": "72",
|
||||
"Image YResolution": "72",
|
||||
"Image ResolutionUnit": "Pixels/Inch",
|
||||
"Image Software": "26.4.2",
|
||||
"Image DateTime": "2026:05:18 06:22:41",
|
||||
"Image HostComputer": "iPhone 13 Pro Max",
|
||||
"Image ExifOffset": "220",
|
||||
"Thumbnail JPEGInterchangeFormat": "2776",
|
||||
"Thumbnail JPEGInterchangeFormatLength": "7639",
|
||||
"EXIF ExposureTime": "1/50",
|
||||
"EXIF FNumber": "3/2",
|
||||
"EXIF ExposureProgram": "Program Normal",
|
||||
"EXIF ISOSpeedRatings": "200",
|
||||
"EXIF ExifVersion": "0232",
|
||||
"EXIF DateTimeOriginal": "2026:05:18 06:22:41",
|
||||
"EXIF DateTimeDigitized": "2026:05:18 06:22:41",
|
||||
"EXIF OffsetTime": "+02:00",
|
||||
"EXIF OffsetTimeOriginal": "+02:00",
|
||||
"EXIF OffsetTimeDigitized": "+02:00",
|
||||
"EXIF ComponentsConfiguration": "YCbCr",
|
||||
"EXIF ShutterSpeedValue": "48307/8559",
|
||||
"EXIF ApertureValue": "27767/23734",
|
||||
"EXIF BrightnessValue": "5765/3682",
|
||||
"EXIF ExposureBiasValue": "0",
|
||||
"EXIF MeteringMode": "Pattern",
|
||||
"EXIF Flash": "Flash did not fire, compulsory flash mode",
|
||||
"EXIF FocalLength": "57/10",
|
||||
"EXIF SubjectArea": "[1025, 1438, 190, 191]",
|
||||
"EXIF MakerNote": "[65, 112, 112, 108, 101, 32, 105, 79, 83, 0, 0, 1, 77, 77, 0, 59, 0, 1, 0, 9, ... ]",
|
||||
"EXIF SubSecTimeOriginal": "023",
|
||||
"EXIF SubSecTimeDigitized": "023",
|
||||
"EXIF FlashPixVersion": "0100",
|
||||
"EXIF ColorSpace": "Uncalibrated",
|
||||
"EXIF ExifImageWidth": "4032",
|
||||
"EXIF ExifImageLength": "3024",
|
||||
"EXIF SensingMethod": "One-chip color area",
|
||||
"EXIF SceneType": "Directly Photographed",
|
||||
"EXIF ExposureMode": "Auto Exposure",
|
||||
"EXIF WhiteBalance": "Auto",
|
||||
"EXIF FocalLengthIn35mmFilm": "26",
|
||||
"EXIF SceneCaptureType": "Standard",
|
||||
"EXIF LensSpecification": "[299253/190607, 9, 3/2, 14/5]",
|
||||
"EXIF LensMake": "Apple",
|
||||
"EXIF LensModel": "iPhone 13 Pro Max back triple camera 5.7mm f/1.5",
|
||||
"EXIF Tag 0xA460": "2",
|
||||
"MakerNote MakerNoteVersion": "16",
|
||||
"MakerNote Tag 0x0002": "[9, 2, 186, 2, 164, 1, 174, 0, 132, 0, 109, 0, 107, 0, 118, 0, 120, 0, 136, 0, ... ]",
|
||||
"MakerNote Tag 0x0003": "[6, 7, 8, 85, 102, 108, 97, 103, 115, 85, 118, 97, 108, 117, 101, 89, 116, 105, 109, 101, ... ]",
|
||||
"MakerNote AEStable": "Yes",
|
||||
"MakerNote AETarget": "192",
|
||||
"MakerNote AEAverage": "187",
|
||||
"MakerNote AFStable": "Yes",
|
||||
"MakerNote Tag 0x0008": "[-1233846271/1143537664, -1825/49, 64/187]",
|
||||
"MakerNote Tag 0x000C": "[16790593/909130039, 1093741891/1127760685]",
|
||||
"MakerNote Tag 0x000D": "24",
|
||||
"MakerNote Tag 0x000E": "0",
|
||||
"MakerNote Tag 0x0010": "1",
|
||||
"MakerNote Tag 0x0011": "4345-8E58-D5B765E42693",
|
||||
"MakerNote ImageCaptureType": "Scene",
|
||||
"MakerNote Tag 0x0019": "8194",
|
||||
"MakerNote Tag 0x001A": "-3ED5-",
|
||||
"MakerNote Tag 0x001F": "0",
|
||||
"MakerNote Tag 0x0020": "42CB-8A14-2D09F1435647",
|
||||
"MakerNote Tag 0x0021": "2228224/0",
|
||||
"MakerNote Tag 0x0023": "[344850436, -1787625472]",
|
||||
"MakerNote Tag 0x0026": "3",
|
||||
"MakerNote Tag 0x0027": "1178873142/875704621",
|
||||
"MakerNote Tag 0x002B": "4B9E-8FE9-F6739C66DC97",
|
||||
"MakerNote Tag 0x002D": "3476",
|
||||
"MakerNote CameraType": "Back Normal",
|
||||
"MakerNote Tag 0x002F": "50",
|
||||
"MakerNote Tag 0x0030": "808506369/33752069",
|
||||
"MakerNote Tag 0x0033": "12288",
|
||||
"MakerNote Tag 0x0034": "5",
|
||||
"MakerNote Tag 0x0035": "4",
|
||||
"MakerNote Tag 0x0036": "180",
|
||||
"MakerNote Tag 0x0037": "4",
|
||||
"MakerNote Tag 0x0038": "203",
|
||||
"MakerNote Tag 0x0039": "1",
|
||||
"MakerNote Tag 0x003A": "133",
|
||||
"MakerNote Tag 0x003B": "0",
|
||||
"MakerNote Tag 0x003C": "4",
|
||||
"MakerNote Tag 0x003D": "66",
|
||||
"MakerNote Tag 0x0040": "[6, 6, 7, 81, 51, 81, 49, 81, 50, 81, 48, 16, 0, 34, 0, 0, 0, 0, 16, 1, ... ]",
|
||||
"MakerNote Tag 0x0041": "0",
|
||||
"MakerNote Tag 0x0042": "0",
|
||||
"MakerNote Tag 0x0043": "0",
|
||||
"MakerNote Tag 0x0044": "0",
|
||||
"MakerNote Tag 0x0045": "0",
|
||||
"MakerNote Tag 0x0046": "0",
|
||||
"MakerNote Tag 0x0048": "569",
|
||||
"MakerNote Tag 0x0049": "0",
|
||||
"MakerNote Tag 0x004A": "2",
|
||||
"MakerNote Tag 0x004D": "808505857/33752145",
|
||||
"MakerNote Tag 0x004E": "[49, 81, 50, 16, 1, 162, 5, 10, 210, 6, 7, 8, 9, 83, 50, 46, 49, 83, 50, 46, ... ]",
|
||||
"MakerNote Tag 0x004F": "[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 4, 144, 245, 0, 2, 232, 143, 0, 0, 0, 9, 0]",
|
||||
"MakerNote Tag 0x0052": "3",
|
||||
"MakerNote Tag 0x0053": "0",
|
||||
"MakerNote Tag 0x0055": "185",
|
||||
"MakerNote Tag 0x0058": "1795",
|
||||
"MakerNote Tag 0x0060": "10127",
|
||||
"MakerNote Tag 0x0061": "26"
|
||||
},
|
||||
"iptc": {},
|
||||
"xmp": {
|
||||
"creator_tool": "26.4.2",
|
||||
"create_date": "2026-05-18T06:22:41.023",
|
||||
"modify_date": "2026-05-18T06:22:41",
|
||||
"face_regions_count": 1,
|
||||
"_xmp_length_bytes": 5345
|
||||
}
|
||||
},
|
||||
{
|
||||
"filesystem": {
|
||||
"file_name": "2026-05-18 13.54.47.jpg",
|
||||
"file_path": "U:\\PycharmProjects\\FotkyBuzalkovi\\demo_fotky\\2026-05-18 13.54.47.jpg",
|
||||
"file_size_bytes": 3149514,
|
||||
"file_size_mb": 3.0,
|
||||
"mtime": "2026-05-18T13:54:47",
|
||||
"ctime": "2026-05-19T06:21:40.360916",
|
||||
"extension": ".jpg"
|
||||
},
|
||||
"hashes": {
|
||||
"sha256_file": "be41557d3ef6822c24a00905e65ad9fba5950bf03ed5c2a434d25c893ed0a87d",
|
||||
"sha256_pixels": "417d6fc06052eba388922d61af72674becb044b8650f2ac528a59aa3109d0408",
|
||||
"phash": "f8124da5f87a0e27",
|
||||
"dhash": "0b926d3902230203",
|
||||
"ahash": "000000dcfffffbf8",
|
||||
"whash": "000000dcfffff9f8"
|
||||
},
|
||||
"pillow": {
|
||||
"format": "JPEG",
|
||||
"mode": "RGB",
|
||||
"width": 4032,
|
||||
"height": 3024,
|
||||
"megapixels": 12.19,
|
||||
"has_transparency": false,
|
||||
"dpi": [
|
||||
"72.0",
|
||||
"72.0"
|
||||
],
|
||||
"icc_profile_present": true,
|
||||
"exif_present": true,
|
||||
"has_embedded_thumbnail": false
|
||||
},
|
||||
"exif_pillow": {
|
||||
"ResolutionUnit": 2.0,
|
||||
"ExifOffset": 220.0,
|
||||
"Make": "Apple",
|
||||
"Model": "iPhone 13 Pro Max",
|
||||
"Software": "26.4.2",
|
||||
"Orientation": 6.0,
|
||||
"DateTime": "2026:05:18 13:54:46",
|
||||
"XResolution": 72.0,
|
||||
"YResolution": 72.0,
|
||||
"HostComputer": "iPhone 13 Pro Max"
|
||||
},
|
||||
"exif_exifread": {
|
||||
"Image Make": "Apple",
|
||||
"Image Model": "iPhone 13 Pro Max",
|
||||
"Image Orientation": "Rotated 90 CW",
|
||||
"Image XResolution": "72",
|
||||
"Image YResolution": "72",
|
||||
"Image ResolutionUnit": "Pixels/Inch",
|
||||
"Image Software": "26.4.2",
|
||||
"Image DateTime": "2026:05:18 13:54:46",
|
||||
"Image HostComputer": "iPhone 13 Pro Max",
|
||||
"Image ExifOffset": "220",
|
||||
"EXIF ExposureTime": "1/100",
|
||||
"EXIF FNumber": "3/2",
|
||||
"EXIF ExposureProgram": "Program Normal",
|
||||
"EXIF ISOSpeedRatings": "40",
|
||||
"EXIF DateTimeOriginal": "2026:05:18 13:54:46",
|
||||
"EXIF DateTimeDigitized": "2026:05:18 13:54:46",
|
||||
"EXIF OffsetTime": "+02:00",
|
||||
"EXIF OffsetTimeOriginal": "+02:00",
|
||||
"EXIF OffsetTimeDigitized": "+02:00",
|
||||
"EXIF ShutterSpeedValue": "135889/20452",
|
||||
"EXIF ApertureValue": "27767/23734",
|
||||
"EXIF BrightnessValue": "99413/19450",
|
||||
"EXIF ExposureBiasValue": "0",
|
||||
"EXIF MeteringMode": "Pattern",
|
||||
"EXIF Flash": "Flash did not fire, compulsory flash mode",
|
||||
"EXIF FocalLength": "57/10",
|
||||
"EXIF SubjectArea": "[2014, 1508, 2218, 1328]",
|
||||
"EXIF MakerNote": "[65, 112, 112, 108, 101, 32, 105, 79, 83, 0, 0, 1, 77, 77, 0, 58, 0, 1, 0, 9, ... ]",
|
||||
"EXIF SubSecTimeOriginal": "334",
|
||||
"EXIF SubSecTimeDigitized": "334",
|
||||
"EXIF ColorSpace": "Uncalibrated",
|
||||
"EXIF ExifImageWidth": "4032",
|
||||
"EXIF ExifImageLength": "3024",
|
||||
"EXIF SensingMethod": "One-chip color area",
|
||||
"EXIF SceneType": "Directly Photographed",
|
||||
"EXIF ExposureMode": "Auto Exposure",
|
||||
"EXIF WhiteBalance": "Auto",
|
||||
"EXIF FocalLengthIn35mmFilm": "26",
|
||||
"EXIF LensSpecification": "[299253/190607, 9, 3/2, 14/5]",
|
||||
"EXIF LensMake": "Apple",
|
||||
"EXIF LensModel": "iPhone 13 Pro Max back triple camera 5.7mm f/1.5",
|
||||
"EXIF Tag 0xA460": "2",
|
||||
"MakerNote MakerNoteVersion": "16",
|
||||
"MakerNote Tag 0x0002": "[9, 1, 5, 1, 252, 0, 245, 0, 237, 0, 223, 0, 199, 0, 177, 0, 163, 0, 136, 0, ... ]",
|
||||
"MakerNote Tag 0x0003": "[6, 7, 8, 85, 102, 108, 97, 103, 115, 85, 118, 97, 108, 117, 101, 85, 101, 112, 111, 99, ... ]",
|
||||
"MakerNote AEStable": "Yes",
|
||||
"MakerNote AETarget": "207",
|
||||
"MakerNote AEAverage": "202",
|
||||
"MakerNote AFStable": "Yes",
|
||||
"MakerNote Tag 0x0008": "[-1352269823/1435631616, 22289/49, 128/101]",
|
||||
"MakerNote Tag 0x000C": "[1048576/1061, 536888888/959919927]",
|
||||
"MakerNote Tag 0x000D": "24",
|
||||
"MakerNote Tag 0x000E": "0",
|
||||
"MakerNote Tag 0x0010": "1",
|
||||
"MakerNote ImageCaptureType": "Photo",
|
||||
"MakerNote Tag 0x0019": "2",
|
||||
"MakerNote Tag 0x001F": "0",
|
||||
"MakerNote Tag 0x0020": "4C30-A38C-5D8C18006FEF",
|
||||
"MakerNote Tag 0x0021": "2621440/0",
|
||||
"MakerNote Tag 0x0023": "[9043971, -445775872]",
|
||||
"MakerNote Tag 0x0026": "3",
|
||||
"MakerNote Tag 0x0027": "61983868/46144959",
|
||||
"MakerNote Tag 0x0028": "1",
|
||||
"MakerNote Tag 0x002B": "4C1B-ADDB-46C891A19178",
|
||||
"MakerNote Tag 0x002D": "6004",
|
||||
"MakerNote CameraType": "Back Normal",
|
||||
"MakerNote Tag 0x002F": "143",
|
||||
"MakerNote Tag 0x0030": "17549364/151570847",
|
||||
"MakerNote Tag 0x0033": "4096",
|
||||
"MakerNote Tag 0x0034": "4",
|
||||
"MakerNote Tag 0x0035": "3",
|
||||
"MakerNote Tag 0x0036": "2044",
|
||||
"MakerNote Tag 0x0037": "4",
|
||||
"MakerNote Tag 0x0038": "19",
|
||||
"MakerNote Tag 0x0039": "0",
|
||||
"MakerNote Tag 0x003A": "0",
|
||||
"MakerNote Tag 0x003B": "0",
|
||||
"MakerNote Tag 0x003C": "4",
|
||||
"MakerNote Tag 0x003D": "11",
|
||||
"MakerNote Tag 0x003F": "1",
|
||||
"MakerNote Tag 0x0041": "0",
|
||||
"MakerNote Tag 0x0042": "0",
|
||||
"MakerNote Tag 0x0043": "0",
|
||||
"MakerNote Tag 0x0044": "0",
|
||||
"MakerNote Tag 0x0045": "0",
|
||||
"MakerNote Tag 0x0046": "0",
|
||||
"MakerNote Tag 0x0048": "19",
|
||||
"MakerNote Tag 0x0049": "100",
|
||||
"MakerNote Tag 0x004A": "2",
|
||||
"MakerNote Tag 0x004D": "808505857/33752145",
|
||||
"MakerNote Tag 0x004E": "[49, 81, 50, 16, 1, 162, 5, 10, 210, 6, 7, 8, 9, 83, 50, 46, 49, 83, 50, 46, ... ]",
|
||||
"MakerNote Tag 0x004F": "[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 4, 144, 245, 0, 2, 232, 143, 0, 0, 0, 9, 0, 0]",
|
||||
"MakerNote Tag 0x0052": "3",
|
||||
"MakerNote Tag 0x0053": "1",
|
||||
"MakerNote Tag 0x0055": "0",
|
||||
"MakerNote Tag 0x0058": "1795",
|
||||
"MakerNote Tag 0x0060": "2856",
|
||||
"MakerNote Tag 0x0061": "26"
|
||||
},
|
||||
"iptc": {
|
||||
"IPTC(1, 90)": "\u001b%G",
|
||||
"IPTC(2, 0)": "\u0000\u0002",
|
||||
"IPTC(2, 63)": "135446",
|
||||
"IPTC(2, 62)": "20260518",
|
||||
"DateCreated": "20260518",
|
||||
"TimeCreated": "135446"
|
||||
},
|
||||
"xmp": {}
|
||||
},
|
||||
{
|
||||
"filesystem": {
|
||||
"file_name": "2026-05-18 14.10.59.jpg",
|
||||
"file_path": "U:\\PycharmProjects\\FotkyBuzalkovi\\demo_fotky\\2026-05-18 14.10.59.jpg",
|
||||
"file_size_bytes": 304048,
|
||||
"file_size_mb": 0.29,
|
||||
"mtime": "2026-05-18T14:10:59",
|
||||
"ctime": "2026-05-19T06:21:38.476009",
|
||||
"extension": ".jpg"
|
||||
},
|
||||
"hashes": {
|
||||
"sha256_file": "a4b20aa73cbc2fe845f12709ccc7e1d227e8fc1c84605a538e86f4a00b899754",
|
||||
"sha256_pixels": "5b5e19daae775d21822891aef4558ae2c241bf082dfb54ae62cd0be1a045f223",
|
||||
"phash": "c7226934de856937",
|
||||
"dhash": "e74fc3ec6c3fc663",
|
||||
"ahash": "0000217eb683fff9",
|
||||
"whash": "000060feb6c3fff9"
|
||||
},
|
||||
"pillow": {
|
||||
"format": "JPEG",
|
||||
"mode": "RGB",
|
||||
"width": 1153,
|
||||
"height": 2048,
|
||||
"megapixels": 2.36,
|
||||
"has_transparency": false,
|
||||
"dpi": null,
|
||||
"icc_profile_present": false,
|
||||
"exif_present": false,
|
||||
"has_embedded_thumbnail": false
|
||||
},
|
||||
"exif_pillow": {},
|
||||
"exif_exifread": {},
|
||||
"iptc": {},
|
||||
"xmp": {}
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user