Display Parallax images as wallpapers in Flutter/Dart using depth map and normal image

138 views Asked by At

I want to create a parallax effect 3D image using depth map in flutter. The gyroscope sensor of the phone will be used to create the 3D effect when user titles. What is the logic behind this creating a parallax image and display it on screen. Thanks

I tried using the following code but gives invalid image err.

double offsetX = 0.0;
  double offsetY = 0.0;

  late StreamSubscription<GyroscopeEvent> gyroscopeSubscription;

  @override
  void initState() {
    super.initState();
    // Start listening to gyroscope data
    gyroscopeSubscription = gyroscopeEvents.listen((GyroscopeEvent event) {
      // Update the position based on gyroscope data
      setState(() {
        offsetX = event.y; // Adjust based on your preferred axis
        offsetY = event.x; // Adjust based on your preferred axis
      });
    });
  }

  @override
  void dispose() {
    // Stop listening to gyroscope data when the widget is disposed
    gyroscopeSubscription.cancel();
    super.dispose();
  }

  Future<MemoryImage> createParallaxImage(String imagePath, String depthMapPath) async {
    final ByteData data = await rootBundle.load(depthMapPath);
    final Uint8List depthMapBytes = data.buffer.asUint8List();

    final ByteData imageData = await rootBundle.load(imagePath);
    final Uint8List imageBytes = imageData.buffer.asUint8List();

    final Uint8List resultBytes = applyParallaxEffect(imageBytes, depthMapBytes);

    return MemoryImage(resultBytes);
  }

  double scaleFactor = 10.0;
  Uint8List applyParallaxEffect(Uint8List imageBytes, Uint8List depthMapBytes) {
    // Image dimensions (adjust based on your image)
    int width = 300;
    int height = 300;

    // Scaling factor for parallax effect

    // Create a copy of the original image
    Uint8List resultBytes = Uint8List.fromList(imageBytes);

    // Iterate over each pixel in the image
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
        // Calculate the index for the current pixel
        int index = (i * width + j) * 4;

        // Extract intensity from the depth map
        int depthIndex = (i * width + j) * 4;
        int depth = depthMapBytes[depthIndex];

        // Shift the pixel horizontally based on the depth
        int shiftedIndex = index + depth;
        if (shiftedIndex < resultBytes.length) {
          resultBytes[shiftedIndex] = imageBytes[index];
          resultBytes[shiftedIndex + 1] = imageBytes[index + 1];
          resultBytes[shiftedIndex + 2] = imageBytes[index + 2];
          resultBytes[shiftedIndex + 3] = imageBytes[index + 3];
        }
      }
    }

    return resultBytes;
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Transform(
        transform: Matrix4.translationValues(offsetX * scaleFactor, offsetY * scaleFactor, 0),
        child: FutureBuilder<MemoryImage>(
          future: createParallaxImage(
            Images.bb1, // Replace with the path to your visible image
            Images.bb1depth, // Replace with the path to your depth map
          ),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
              return Image.memory(
                snapshot.data!.bytes,
                width: 300, // Adjust based on your image dimensions
                height: 300, // Adjust based on your image dimensions
              );
            } else {
              return const CircularProgressIndicator();
            }
          },
        ),
      ),
    );
  }
1

There are 1 answers

0
Ozan Taskiran On

It's hard for me to understand what you really want without a visual reference (gif or video would be nice). But are you looking for a tilt parallax hover effect? Example can be found here:

https://amoshuke.github.io/flutter_tilt_book/#/Example

If yes, you can use the flutter_tilt package: https://pub.dev/packages/flutter_tilt