From 7d3be11b76c5b79ce4576f25906df8cf089dacae Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 26 Dec 2023 17:53:36 -0800 Subject: [PATCH] feat: local testing for jpeg encoding --- app/assets/test.html | 28 +++++++ app/lib/openai_api.dart | 2 +- app/lib/paint_window.dart | 153 ++++++++++++++++++++++++++++++++++++-- app/pubspec.yaml | 2 + 4 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 app/assets/test.html diff --git a/app/assets/test.html b/app/assets/test.html new file mode 100644 index 0000000..a08b3d1 --- /dev/null +++ b/app/assets/test.html @@ -0,0 +1,28 @@ + + + + My Simple HTML File + + +

Hello, world!

+
+ Red dot +
+ + diff --git a/app/lib/openai_api.dart b/app/lib/openai_api.dart index 17ae9f0..9db09ea 100644 --- a/app/lib/openai_api.dart +++ b/app/lib/openai_api.dart @@ -482,7 +482,7 @@ The final output should be a single HTML file, starting with "". Avoid mar {"type": "text", "text": userPrompt}, { "type": "image_url", - "image_url": {"url": "data:image/png;base64,$imageBase64"} + "image_url": {"url": "data:image/jpeg;base64,${imageBase64}"} } ] } diff --git a/app/lib/paint_window.dart b/app/lib/paint_window.dart index fa90602..091552a 100644 --- a/app/lib/paint_window.dart +++ b/app/lib/paint_window.dart @@ -1,10 +1,13 @@ import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'dart:ui' as ui; import 'dart:typed_data'; import 'package:glowby/openai_api.dart'; +import 'package:image/image.dart' as img; +import 'dart:html' as html; class PaintWindow extends StatefulWidget { @override @@ -16,6 +19,7 @@ class _PaintWindowState extends State { final TextEditingController nameController = TextEditingController(); String creationName = ''; bool isLoading = false; + Uint8List? imgBytes; @override void dispose() { @@ -23,6 +27,137 @@ class _PaintWindowState extends State { super.dispose(); } + Future convertToBase64JpegWeb(List points) async { + // Create a canvas element + final canvas = html.CanvasElement(width: 300, height: 300); + final ctx = canvas.context2D; + + // Set your paint styles + ctx + ..fillStyle = 'white' + ..strokeStyle = 'black' + ..lineWidth = 2 + ..beginPath(); + + // Draw your points onto the canvas + for (int i = 0; i < points.length - 1; i++) { + if (points[i] != null && points[i + 1] != null) { + ctx.moveTo(points[i]!.dx, points[i]!.dy); + ctx.lineTo(points[i + 1]!.dx, points[i + 1]!.dy); + } + } + + ctx + ..closePath() + ..stroke(); + + // Convert the canvas to a Data URL with a JPEG format + final String dataUrl = canvas.toDataUrl('image/jpeg', 1.0); + + // Extract the base64 part of the Data URL + final String base64String = dataUrl.split(',')[1]; + + return base64String; + } + + Future convertToBase64Jpeg(List points) async { + // Create a picture recorder to record the canvas operations + final ui.PictureRecorder recorder = ui.PictureRecorder(); + final Canvas canvas = Canvas(recorder); + + // Draw your points here onto the canvas + final paint = Paint() + ..color = Colors.black + ..strokeCap = StrokeCap.round + ..strokeWidth = 2.0; + for (int i = 0; i < points.length - 1; i++) { + if (points[i] != null && points[i + 1] != null) { + canvas.drawLine(points[i]!, points[i + 1]!, paint); + } + } + + // End recording the canvas operations + final ui.Picture picture = recorder.endRecording(); + + // Convert the picture to an image + final ui.Image image = await picture.toImage(300, 300); + + // Get the byte data from the image in PNG format + final ByteData? byteData = + await image.toByteData(format: ui.ImageByteFormat.png); + if (byteData == null) { + print("Failed to obtain byte data from image"); + return ''; + } + + // Decode the PNG data to an img.Image + final img.Image? decodedImage = + img.decodeImage(byteData.buffer.asUint8List()); + if (decodedImage == null) { + print("Failed to decode image"); + return ''; + } + + // Encode the img.Image to JPEG + final List jpeg = img.encodeJpg(decodedImage); + + // Base64 encode the JPEG bytes + final String base64String = base64Encode(Uint8List.fromList(jpeg)); + + return base64String; + } + + // This function converts the drawing (list of points) to a base64 string + Future convertToBase64Jpeg2(List points) async { + // Create a picture recorder to record the canvas operations + final ui.PictureRecorder recorder = ui.PictureRecorder(); + final Canvas canvas = Canvas(recorder); + + // Draw your points here onto the canvas + final paint = Paint() + ..color = Colors.black + ..strokeCap = StrokeCap.round + ..strokeWidth = 2.0; + for (int i = 0; i < points.length - 1; i++) { + if (points[i] != null && points[i + 1] != null) { + canvas.drawLine(points[i]!, points[i + 1]!, paint); + } + } + + // End recording the canvas operations + final ui.Picture picture = recorder.endRecording(); + + // Convert the picture to an image + final ui.Image image = + await picture.toImage(300, 300); // Set the width and height as needed + final ByteData? byteData = + await image.toByteData(format: ui.ImageByteFormat.rawRgba); + + if (byteData == null) { + print("Failed to obtain byte data from image"); + return ''; + } + + // Compress the image and get JPEG format Uint8List + final Uint8List? imgBytes = await FlutterImageCompress.compressWithList( + byteData.buffer.asUint8List(), + minWidth: 300, + minHeight: 300, + quality: 100, // Adjust the quality as needed + format: CompressFormat.jpeg, + ); + + if (imgBytes == null) { + print("Failed to compress image"); + return ''; + } + + // Base64 encode the JPEG bytes + final String base64String = base64Encode(imgBytes); + + return base64String; + } + // This function converts the drawing (list of points) to a base64 string Future convertToBase64(List points) async { // Create a picture recorder to record the canvas operations @@ -64,12 +199,16 @@ class _PaintWindowState extends State { }); // Convert points to a suitable format and call OpenAI method // For example, you might convert points to an image and then to base64 - String imageBase64 = - await convertToBase64(points); // Implement this function + //String imageBase64 = await convertToBase64Jpeg(points); + String imageBase64 = await convertToBase64JpegWeb(points); + print(imageBase64); + //this.imgBytes = base64Decode(imageBase64); // Implement this function + + //String htmlResponse = + // await OpenAI_API().getHtmlFromOpenAI(imageBase64, creationName); + // print(htmlResponse); - String htmlResponse = - await OpenAI_API().getHtmlFromOpenAI(imageBase64, creationName); - print(htmlResponse); + //imgBytes = imageBase64; // Do something with htmlResponse @@ -80,6 +219,10 @@ class _PaintWindowState extends State { @override Widget build(BuildContext context) { + if (imgBytes != null) { + return Image.memory(imgBytes!); + } + return AlertDialog( title: const Text('Paint Window'), content: SingleChildScrollView( diff --git a/app/pubspec.yaml b/app/pubspec.yaml index ab667bb..25171a2 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -29,6 +29,8 @@ dependencies: shared_preferences: ^2.2.2 flutter_secure_storage: ^9.0.0 file_picker: ^6.1.1 + image: ^4.1.3 + flutter_image_compress: ^2.1.0 flutter: sdk: flutter