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

2.8 KiB
Raw Permalink Blame History

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:

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:

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:

_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

_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