saveImage static method

Future<OperationResult> saveImage(
  1. GlobalKey<State<StatefulWidget>> imagePinPointKey, {
  2. bool skipSaveToGallery = true,
  3. String? customName,
})

Captures and saves the current image state including pins

This method captures the current visual state of the widget (including all pins), processes the image to correct any orientation issues, and optionally saves it to the device gallery.

Parameters:

  • imagePinPointKey: The GlobalKey of the widget to capture
  • skipSaveToGallery: If true, the image will only be saved to a temporary file (default: true)
  • customName: Optional custom filename for the saved image

Returns:

  • An OperationResult object containing success/failure information and file path

The method follows these steps:

  1. Captures the current widget state as an image using RepaintBoundary
  2. Converts the captured image to bytes
  3. Creates a temporary file to check if the image needs orientation correction
  4. Applies vertical flipping if needed (some devices flip images during capture)
  5. Saves the processed image to the gallery with a unique timestamp-based filename
  6. Cleans up temporary files and returns success/error feedback to the user

Implementation

static Future<OperationResult> saveImage(GlobalKey imagePinPointKey,
    {bool skipSaveToGallery = true, String? customName}) async {
  try {
    final Directory tempDir = await getTemporaryDirectory();
    final String fileName = customName != null
        ? '$customName.png'
        : '${DateTime.now().microsecondsSinceEpoch}.png';
    final String finalFilePath = '${tempDir.path}/$fileName';

    // Remove existing file with the same name if it exists
    final File existingFile = File(finalFilePath);
    if (existingFile.existsSync()) {
      existingFile.deleteSync();
    }

    // Capture the current state of the widget as an image
    final RenderRepaintBoundary boundary = imagePinPointKey.currentContext
        ?.findRenderObject() as RenderRepaintBoundary;
    final ui.Image capturedImage = await boundary.toImage(pixelRatio: 2.5);

    // Convert the captured image to bytes
    final ByteData? byteData = await capturedImage.toByteData(
      format: ui.ImageByteFormat.png,
    );
    Uint8List? imageBytes = byteData?.buffer.asUint8List();

    if (imageBytes == null) {
      log(LogMessages.errorCapturingImage);
      return OperationResult(
          isSuccess: false, message: 'Failed to capture image');
    }

    // Create a temporary file to check if the image is flipped
    final String tempFilePath = '${tempDir.path}/temp_$fileName';
    final File tempFile = File(tempFilePath)..createSync(recursive: true);
    await tempFile.writeAsBytes(imageBytes);

    // Clean up the temporary file
    if (await tempFile.exists()) {
      await tempFile.delete();
    }

    // Create a local copy of the saved image
    final File finalFile = File(finalFilePath)..createSync(recursive: true);
    await finalFile.writeAsBytes(imageBytes);

    // Save to gallery if requested
    if (!skipSaveToGallery) {
      await SaverGallery.saveImage(
        imageBytes,
        fileName: fileName,
        skipIfExists: false,
      );
    }

    return OperationResult(
        isSuccess: true,
        filePath: finalFile.path,
        message: 'Image saved successfully');
  } catch (e) {
    log('${LogMessages.errorSavingImage}: $e');
    return OperationResult(isSuccess: false, message: 'Failed to save image');
  }
}