at main 2.1 kB view raw
1import 'dart:io'; 2 3import 'package:image/image.dart' as img; 4 5enum ResizeMode { cover, contain, stretch } 6 7class ResizeResult { 8 final File file; 9 final int width; 10 final int height; 11 final int size; 12 final String mime; 13 ResizeResult({ 14 required this.file, 15 required this.width, 16 required this.height, 17 required this.size, 18 this.mime = 'image/jpeg', 19 }); 20} 21 22Future<ResizeResult> resizeImage({ 23 required File file, 24 int targetWidth = 2000, 25 int targetHeight = 2000, 26 int maxBytes = 1000000, 27 ResizeMode mode = ResizeMode.cover, 28}) async { 29 final bytes = await file.readAsBytes(); 30 img.Image? image = img.decodeImage(bytes); 31 if (image == null) throw Exception('Could not decode image'); 32 33 // Calculate scale 34 double scale; 35 if (mode == ResizeMode.cover) { 36 scale = [ 37 targetWidth / image.width, 38 targetHeight / image.height, 39 ].reduce((a, b) => a > b ? a : b); 40 } else if (mode == ResizeMode.contain) { 41 scale = [ 42 targetWidth / image.width, 43 targetHeight / image.height, 44 ].reduce((a, b) => a < b ? a : b); 45 } else { 46 scale = 1.0; 47 } 48 49 int newWidth = (image.width * scale).round(); 50 int newHeight = (image.height * scale).round(); 51 52 if (mode == ResizeMode.stretch) { 53 newWidth = targetWidth; 54 newHeight = targetHeight; 55 } 56 57 img.Image resized = img.copyResize(image, width: newWidth, height: newHeight); 58 59 // Binary search for best quality under maxBytes 60 int minQ = 0, maxQ = 101; 61 List<int> bestJpg = []; 62 while (maxQ - minQ > 1) { 63 int q = ((minQ + maxQ) / 2).round(); 64 final jpg = img.encodeJpg(resized, quality: q); 65 if (jpg.length < maxBytes) { 66 minQ = q; 67 bestJpg = jpg; 68 } else { 69 maxQ = q; 70 } 71 } 72 if (bestJpg.isEmpty) { 73 // fallback: lowest quality 74 bestJpg = img.encodeJpg(resized, quality: minQ); 75 } 76 77 final outFile = File(file.path.replaceFirst(RegExp(r'\.(jpg|jpeg|png)?'), '_resized.jpg')); 78 await outFile.writeAsBytes(bestJpg); 79 80 return ResizeResult( 81 file: outFile, 82 width: resized.width, 83 height: resized.height, 84 size: bestJpg.length, 85 mime: 'image/jpeg', 86 ); 87}