I am currently coding a flutter app that takes a picture and sends it to the gpt-4-vision-preview API. When I run this on my pixel 7, I get no errors, everything works just as it should.
But, when I run it on a samsung s22 ultra, I get the error: "“error”: {
“message”: “You uploaded an unsupported image. Please make sure your image is below 20 MB in size and is of one the following formats: [‘png’, ‘jpeg’, ‘gif’, ‘webp’].”,
“type”: “invalid_request_error”,
“param”: null,
“code”: “image_parse_error”
I’ve tried many different options, but none of them have worked. I currently upload a base64 encoded version of the image. However, on the samsung s22 ultra, I do get this message which I do not get from the pixel: D/qdgralloc( 8299): GetYUVPlaneInfo: Invalid format passed: 0x21
I have tried changing the imageformat group to be jpeg and to be yuv420, both of which haven’t worked. I have seen that while the pixel takes images that are around 400,000 bytes, the samsung s22 ultra takes images that are around 80,000 - 150,000 bytes, though I’m not sure if the decreased image quality is part of the problem. Here is my code:
import ‘dart:async’;
import ‘dart:io’;import ‘package:camera/camera.dart’;
import ‘package:flutter/material.dart’;Future processImage(String imagePath, String message) async {
// Perform API request to GPT Vision API for analysis
// Use imagePath and send it as a request payload
String encodedImage = encodeImage(imagePath);
// Example:
var apiUrl = API_URL;
var response = await http.post(Uri.parse(apiUrl),
headers: {
‘Content-type’: ‘application/json’,
‘Authorization’: ‘Bearer $chatgptApiKey’
},
body: jsonEncode({
“model”: “gpt-4-vision-preview”,
“messages”: [
{
“role”: “system”,
“content”: “You are an assistant for the visually impaired.”
},
{
“role”: “user”,
“content”: [
{
“type”: “text”,
“text”:
“$message.”
},
{
“type”: “image_url”,
“image_url”: {“url”: "data:image/jpeg;base64, encodedImage"}
}
],
}
],
"max_tokens": 60,
}));
if (response.statusCode == 200) {
// Extract and return analysis results
var responseJson = jsonDecode(response.body);
String result = responseJson['choices'][0]['message']['content'];
return result;
} else {
print('Error: {response.body}');
return “Error: Sorry, but your request could not be handled. Make sure you have internet, and haven’t sent too many requests.”;
}
}
String encodeImage(String imagePath) {
File imageFile = File(imagePath);
print(imageFile);
List imageBytes = imageFile.readAsBytesSync();
print(imageBytes);
var lengthBytes = imageFile.readAsBytesSync().lengthInBytes;
print(lengthBytes);
String base64Image = base64Encode(imageBytes);
print(base64Image);
return base64Image;
}
Future main() async {
// Ensure that plugin services are initialized so thatavailableCameras()
// can be called beforerunApp()
WidgetsFlutterBinding.ensureInitialized();// Obtain a list of the available cameras on the device.
final cameras = await availableCameras();// Get a specific camera from the list of available cameras.
final firstCamera = cameras.first;runApp(
MaterialApp(
theme: ThemeData.dark(),
home: TakePictureScreen(
// Pass the appropriate camera to the TakePictureScreen widget.
camera: firstCamera,
),
),
);
}// A screen that allows users to take a picture using a given camera.
class TakePictureScreen extends StatefulWidget {
const TakePictureScreen({
super.key,
required this.camera,
});final CameraDescription camera;
@override
TakePictureScreenState createState() => TakePictureScreenState();
}class TakePictureScreenState extends State {
late CameraController _controller;
late Future _initializeControllerFuture;@override
void initState() {
super.initState();
// To display the current output from the Camera,
// create a CameraController.
_controller = CameraController(
// Get a specific camera from the list of available cameras.
widget.camera,
// Define the resolution to use.
ResolutionPreset.medium,
);// Next, initialize the controller. This returns a Future. _initializeControllerFuture = _controller.initialize();
}
@override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text(‘Take a picture’)),
// You must wait until the controller is initialized before displaying the
// camera preview. Use a FutureBuilder to display a loading spinner until the
// controller has finished initializing.
body: FutureBuilder(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
// Otherwise, display a loading indicator.
return const Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
// Provide an onPressed callback.
onPressed: () async {
// Take the Picture in a try / catch block. If anything goes wrong,
// catch the error.
try {
// Ensure that the camera is initialized.
await _initializeControllerFuture;// Attempt to take a picture and get the file `image` // where it was saved. final image = await _controller.takePicture(); gptResponse = await processImage(image.path, "Describe this > > image"); print(gptResponse); if (!context.mounted) return; // If the picture was taken, display it on a new screen. await Navigator.of(context).push( MaterialPageRoute( builder: (context) => DisplayPictureScreen( // Pass the automatically generated path to // the DisplayPictureScreen widget. imagePath: image.path, ), ), ); } catch (e) { // If an error occurs, log the error to the console. print(e); } }, child: const Icon(Icons.camera_alt), ), );
}
}// A widget that displays the picture taken by the user.
class DisplayPictureScreen extends StatelessWidget {
final String imagePath;const DisplayPictureScreen({super.key, required this.imagePath});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text(‘Display the Picture’)),
// The image is stored as a file on the device. Use theImage.file
// constructor with the given path to display the image.
body: Image.file(File(imagePath)),
);
}
}
Blockquote
Blockquote
Blockquote