generate LVGL 9 binary

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2025-12-06 21:08:52 +01:00
parent 187b42e465
commit d100221876
5 changed files with 127 additions and 4 deletions

View File

@@ -0,0 +1,45 @@
import 'package:image/image.dart' as img;
import 'package:injectable/injectable.dart';
@singleton
class ImageResizer {
static const int maxWidth = 480;
static const int maxHeight = 320;
img.Image resizeToFit(img.Image image) {
final w = image.width;
final h = image.height;
if (w <= maxWidth && h <= maxHeight) {
return image;
}
final aspectRatio = w / h;
int newWidth;
int newHeight;
if (w > h) {
newWidth = maxWidth;
newHeight = (maxWidth / aspectRatio).round();
if (newHeight > maxHeight) {
newHeight = maxHeight;
newWidth = (maxHeight * aspectRatio).round();
}
} else {
newHeight = maxHeight;
newWidth = (maxHeight * aspectRatio).round();
if (newWidth > maxWidth) {
newWidth = maxWidth;
newHeight = (maxWidth / aspectRatio).round();
}
}
return img.copyResize(
image,
width: newWidth,
height: newHeight,
interpolation: img.Interpolation.linear,
);
}
}

View File

@@ -0,0 +1,68 @@
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<void> 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(),
]);
}
}