import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/widgets.dart' show Size; import 'package:image/image.dart' as img; /// Görüntü dosyasının gerçek piksel boyutu — tam decode yapmadan. /// /// PNG/GIF/BMP/WebP: boyut ilk 33 baytta → elle parse. /// JPEG: SOF büyük APP/EXIF segmentlerinin ardından gelebilir → package:image startDecode. Size? pixelSizeOfFile(String path) { try { final file = File(path); final stat = file.statSync(); const maxHead = 512 * 1024; final raf = file.openSync(); final header = raf.readSync(stat.size < maxHead ? stat.size : maxHead); raf.closeSync(); return _headerPixelSize(header); } catch (_) {} return null; } Size? _headerPixelSize(Uint8List b) { try { if (b.length >= 24 && b[0] == 0x89 && b[1] == 0x50) { // PNG final w = (b[16] << 24) | (b[17] << 16) | (b[18] << 8) | b[19]; final h = (b[20] << 24) | (b[21] << 16) | (b[22] << 8) | b[23]; return Size(w.toDouble(), h.toDouble()); } if (b.length >= 10 && b[0] == 0x47 && b[1] == 0x49 && b[2] == 0x46) { // GIF (WBMP da GIF tabanlı olabilir) final w = b[6] | (b[7] << 8); final h = b[8] | (b[9] << 8); return Size(w.toDouble(), h.toDouble()); } if (b.length >= 26 && b[0] == 0x42 && b[1] == 0x4D) { // BMP final w = b[18] | (b[19] << 8) | (b[20] << 16) | (b[21] << 24); final h = b[22] | (b[23] << 8) | (b[24] << 16) | (b[25] << 24); return Size(w.toDouble(), h.abs().toDouble()); } if (b.length >= 30 && b[0] == 0x52 && b[1] == 0x49 && b[2] == 0x46 && b[3] == 0x46 && b[8] == 0x57 && b[9] == 0x45 && b[10] == 0x42 && b[11] == 0x50) { // WebP if (b[12] == 0x56 && b[13] == 0x50 && b[15] == 0x58) { // VP8X final w = b[24] | (b[25] << 8) | (b[26] << 16); final h = b[27] | (b[28] << 8) | (b[29] << 16); return Size((w + 1).toDouble(), (h + 1).toDouble()); } if (b.length >= 25 && b[12] == 0x56 && b[13] == 0x50 && b[15] == 0x4C && b[20] == 0x2F) { // VP8L final w = (b[21] & 0x3F) | ((b[22] & 0x0F) << 6); final h = (b[23] & 0x3F) | ((b[24] & 0x0F) << 6); return Size((w + 1).toDouble(), (h + 1).toDouble()); } if (b[12] == 0x56 && b[13] == 0x50 && b[15] == 0x20) { // VP8 (lossy) final w = (b[26] | (b[27] << 8)) & 0x3FFF; final h = (b[28] | (b[29] << 8)) & 0x3FFF; return Size(w.toDouble(), h.toDouble()); } } } catch (_) {} try { // JPEG final info = img.JpegDecoder().startDecode(b); if (info != null) return Size(info.width.toDouble(), info.height.toDouble()); } catch (_) {} return null; }