import 'dart:io'; import 'dart:typed_data'; import 'package:image/image.dart' as img; import 'package:injectable/injectable.dart'; import 'image_resizer.dart'; @singleton class LvglImageConverter { final ImageResizer _imageResizer; LvglImageConverter(this._imageResizer); static const int _magic = 0x19; static const int _colorFormatRgb565 = 0x12; static const int _flags = 0x00; int _toRgb565(int r, int g, int b) { return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); } Future convertPngToBin(String imagePath, String binPath) async { final imageFile = File(imagePath); if (!await imageFile.exists()) { throw FileSystemException('Image file not found', imagePath); } final bytes = await imageFile.readAsBytes(); var image = img.decodeImage(bytes); if (image == null) { throw FormatException('Failed to decode image: $imagePath'); } image = _imageResizer.resizeToFit(image); final w = image.width; final h = image.height; final stride = (w * 16 + 7) ~/ 8; final header = ByteData(12); header.setUint8(0, _magic); header.setUint8(1, _colorFormatRgb565); header.setUint16(2, _flags, Endian.little); header.setUint16(4, w, Endian.little); header.setUint16(6, h, Endian.little); header.setUint16(8, stride, Endian.little); header.setUint16(10, 0, Endian.little); // reserved final body = ByteData(w * h * 2); var offset = 0; for (var y = 0; y < h; y++) { for (var x = 0; x < w; x++) { final pixel = image.getPixel(x, y); final rgb565 = _toRgb565(pixel.r.toInt(), pixel.g.toInt(), pixel.b.toInt()); body.setUint16(offset, rgb565, Endian.little); offset += 2; } } final binFile = File(binPath); await binFile.parent.create(recursive: true); await binFile.writeAsBytes([ ...header.buffer.asUint8List(), ...body.buffer.asUint8List(), ]); } }