Future<File> mergeImagesVertically(File front, File back) async {
  final img.Image image1 = img.decodeImage(await front.readAsBytes())!;
  final img.Image image2 = img.decodeImage(await back.readAsBytes())!;
  
  // Determine max width and combined height
  final int finalWidth = max(image1.width, image2.width);
  final int finalHeight = image1.height + image2.height;

  // Create a new canvas with final dimensions
  final img.Image canvas = img.copyExpandCanvas(
    image1,
    newWidth: finalWidth,
    newHeight: finalHeight,
    position: img.ExpandCanvasPosition.topLeft,
  );

  // Place second image below the first one
  final img.Image finalImage = img.compositeImage(
    canvas,
    image2,
    dstX: 0,
    dstY: image1.height,
  );

  // Save the final image to local storage
  final dir = await getApplicationDocumentsDirectory();
  final path = join(dir.path, 'merged_${DateTime.now().millisecondsSinceEpoch}.jpg');
  final file = File(path);
  await file.writeAsBytes(img.encodeJpg(finalImage));
  return file;
}
            

Isolate

// A simple class to bundle parameters for the isolate function
class MergeImagesArgs {
  final String frontPath;
  final String backPath;
  final String outputPath;

  // Constructor
  MergeImagesArgs(this.frontPath, this.backPath, this.outputPath);
}

// This function will run in a separate isolate using 'compute'
Future<String> _mergeImagesInIsolate(MergeImagesArgs args) async {
  // Load images from file paths
  final front = File(args.frontPath);
  final back = File(args.backPath);

  // Decode image bytes to image objects
  final img.Image image1 = img.decodeImage(await front.readAsBytes())!;
  final img.Image image2 = img.decodeImage(await back.readAsBytes())!;

  // Determine final canvas size
  final int finalWidth = max(image1.width, image2.width);
  final int finalHeight = image1.height + image2.height;

  // Create canvas with enough height to hold both images vertically
  final img.Image canvas = img.copyExpandCanvas(
    image1,
    newWidth: finalWidth,
    newHeight: finalHeight,
    position: img.ExpandCanvasPosition.topLeft,
  );

  // Draw the second image below the first one on the canvas
  final img.Image finalImage = img.compositeImage(
    canvas,
    image2,
    dstX: 0,
    dstY: image1.height,
  );

  // Save the result to the specified output path
  final file = File(args.outputPath);
  await file.writeAsBytes(img.encodeJpg(finalImage));
  return file.path;
}

// This function is called from the main thread to perform image merge in the background
Future mergeImagesVerticallyInBackground(File frontImage, File backImage) async {
  // Define the output path
  final dir = await getApplicationDocumentsDirectory();
  final outputPath = join(dir.path, 'merged_${DateTime.now().millisecondsSinceEpoch}.jpg');

  // Run the merge function in a background isolate using 'compute'
  final mergedPath = await compute(
    _mergeImagesInIsolate,
    MergeImagesArgs(frontImage.path, backImage.path, outputPath),
  );

  // Return the result as a File
  return File(mergedPath);
}