Files
imajviewer/docs/yonerge-downsampling-swap.md
Alhan 45cf56a1e6
Some checks failed
Build & Release / build-linux (push) Has been cancelled
Build & Release / build-windows (push) Has been cancelled
Build & Release / create-release (push) Has been cancelled
feat: downsampling + full-res swap + RAM leak fix
- Büyük resimler ilk yüklemede max 2048px'e downsampling (RAM ~1.6MB)
- Zoom 1.5x stretch'i geçince full-res'e swap (orijinal çözünürlük)
- Resim geçişinde eski provider evict + ImageCache.evict() (RAM leak)
- Tiled render kodu tamamen kaldırıldı
2026-08-14 21:22:26 +03:00

102 lines
2.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Yönerge: Downsampling + Full-Res Swap + RAM Leak Fix
## Amaç
Yüksek çözünürlüklü görsellerde RAM tüketimini azaltmak ve resim geçişlerinde bellek sızıntısını gidermek.
## Dosya
`lib/widgets/image_canvas.dart`
## 1. State değişkenleri ekle
`_ImageCanvasState` sınıfına aşağıdaki değişkenleri ekle:
```dart
ui.Image? _uiImage;
ui.Image? _fullResImage;
bool _fullResLoading = false;
bool _usingFullRes = false;
static const int _downsampleTarget = 2048;
```
## 2. `_loadUiImage()` — Downsample decode
Mevcut `_loadUiImage()` metodunu aşağıdaki gibi değiştir:
- `ui.instantiateImageCodec()` çağrısına `targetWidth: _downsampleTarget, targetHeight: _downsampleTarget` parametrelerini ekle
- Decode edilen resmin boyutunu `_uiImage` ve `_tiledImageSize` olarak kaydet
- Eğer decode boyutu target'tan büyükse → `_loadFullResImage(bytes)` başlat (arka plan)
- Eğer decode boyutu target'tan küçükse → resim zaten küçük, `_usingFullRes = true` yap
## 3. `_loadFullResImage()` — Arka plan full-res yükleme
Yeni metot:
```dart
Future<void> _loadFullResImage(Uint8List bytes) async {
if (_fullResLoading) return;
_fullResLoading = true;
try {
final codec = await ui.instantiateImageCodec(bytes);
final frame = await codec.getNextFrame();
if (mounted && !_usingFullRes) {
setState(() => _fullResImage = frame.image);
} else {
frame.image.dispose();
}
} catch (e) { /* log */ }
finally { _fullResLoading = false; }
}
```
## 4. `_checkFullResSwap()` — Zoom threshold'unda swap
Yeni metot. `_handleScroll()` içinde `_sc` güncellendikten sonra çağrılır.
- Downsample resmin ne kadar stretch edildiğini hesapla (`stretchX`, `stretchY`)
- `maxStretch >= 1.5` ise:
- `_uiImage?.dispose()`
- `_uiImage = _fullResImage`
- `_fullResImage = null`
- `_tiledImageSize` güncelle
- `_usingFullRes = true`
## 5. `_handleScroll()` — Swap kontrolü ekle
`_sc = newSc;` satırından sonra `_checkFullResSwap()` çağrısı ekle.
## 6. RAM Leak Fix — `didUpdateWidget`
Resim değiştiğinde eski tüm referansları temizle:
```dart
_uiImage?.dispose();
_fullResImage?.dispose();
_cachedFileImage?.evict();
_cachedProvider?.evict();
_cachedFileImage = null;
_cachedProvider = null;
_cachedPath = null;
_cachedCacheWidth = null;
PaintingBinding.instance.imageCache.evict(FileImage(File(old.filePath)));
```
## 7. `_resetView()` — Tüm state sıfırla
`_fullResImage`, `_fullResLoading`, `_usingFullRes` sıfırlansın.
## 8. `dispose()` — Her iki resmi de dispose et
```dart
_uiImage?.dispose();
_fullResImage?.dispose();
```
## 9. Import
`dart:typed_data` import'u ekle (`Uint8List` için).
## Sonuç
- İlk yükleme: max 2048px downsample (RAM ~1.6MB)
- Zoom ile yakınlaşınca: full-res swap (~512MB+ büyük resimlerde)
- Resim geçişinde: eski tüm cache dispose + evict