Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Images Compression crashes Android #49

Closed
friebetill opened this issue May 22, 2019 · 8 comments
Closed

Images Compression crashes Android #49

friebetill opened this issue May 22, 2019 · 8 comments
Labels
platform: android android type: question Further information is requested

Comments

@friebetill
Copy link

friebetill commented May 22, 2019

With the latest version 0.5.1 I get sometimes a crash when compressing a JPEG image on Android. Didn't test if it works with a version before that. The code is here:

Future<File> _compressImage(File image) async {
    final tempDir = await getTemporaryDirectory();
    final compressedFile = await FlutterImageCompress.compressAndGetFile(
      image.absolute.path,
      '${tempDir.path}/${basename(image.path)}',
      quality: 90,
    );
    return compressedFile.lengthSync() < image.lengthSync() ? compressedFile : image;
  }

And the exception is here:

E/AndroidRuntime(21107): FATAL EXCEPTION: pool-4-thread-2
E/AndroidRuntime(21107): Process: com.example.example, PID: 21107
E/AndroidRuntime(21107): java.lang.IndexOutOfBoundsException: Invalid index 65542, size is 65536
E/AndroidRuntime(21107): 	at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
E/AndroidRuntime(21107): 	at java.util.ArrayList.get(ArrayList.java:308)
E/AndroidRuntime(21107): 	at com.example.flutterimagecompress.ExifKt.getUint16(Exif.kt:4)
E/AndroidRuntime(21107): 	at com.example.flutterimagecompress.ExifKt.access$getUint16(Exif.kt:1)
E/AndroidRuntime(21107): 	at com.example.flutterimagecompress.Exif.getRotationDegrees(Exif.kt:51)
E/AndroidRuntime(21107): 	at com.example.flutterimagecompress.CompressFileHandler$handleGetFile$1.run(CompressFileHandler.kt:58)
E/AndroidRuntime(21107): 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
E/AndroidRuntime(21107): 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
E/AndroidRuntime(21107): 	at java.lang.Thread.run(Thread.java:818)
@CaiJingLong
Copy link
Member

Please send your picture here as an attachment. I'll try the problem, because I have no problem using the picture in Example here.

@CaiJingLong CaiJingLong added platform: android android type: question Further information is requested labels May 23, 2019
@ahde46
Copy link

ahde46 commented May 23, 2019

I have the same issue that show exact error message when I try to compress an image that taken from camera plugin v0.5.0.

@CaiJingLong
Copy link
Member

@ahde46
Can you post the image file as an attachment?
Or provide a complete example that can be reproduced.

@ahde46
Copy link

ahde46 commented May 23, 2019

@CaiJingLong
Thank you for your prompt reply!
Here is the minimal code to reproduce the issue.
When the floating button is clicked, the app will capture the image and saved it on a path after that the crash happens during the image compression testCompressFile(String imagePath) is being called.

  • please add 'camera: ^0.5.0' and also 'flutter_image_compress: ^0.5.1' on pubspec.yaml

    import 'dart:async';
    import 'dart:io';
    import 'package:camera/camera.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_image_compress/flutter_image_compress.dart';
    import 'package:path/path.dart' show join;
    import 'package:path_provider/path_provider.dart';
    import 'package:image/image.dart' as Im;
    
    Future<void> main() async {
      // 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 {
      final CameraDescription camera;
    
      const TakePictureScreen({
        Key key,
        @required this.camera,
      }) : super(key: key);
    
      @override
      TakePictureScreenState createState() => TakePictureScreenState();
    }
    
    class TakePictureScreenState extends State<TakePictureScreen> {
      CameraController _controller;
      Future<void> _initializeControllerFuture;
    
      static Future<void> testCompressFile(String imagePath) async {
        try {
          File file = new File(imagePath);
    
          var result = await FlutterImageCompress.compressWithFile(
            file.absolute.path,
            minWidth: 400,
            minHeight: 400, // 720
            quality: 30,
            rotate: 90,
          );
          print(file.lengthSync());
          print(result.length);
          Im.Image image = Im.decodeImage(result);
          File(imagePath).writeAsBytes(Im.encodeJpg(image));
        } catch (e) {
          print("compressFile(): exception $e");
        }
      }
    
      @override
      void initState() {
        super.initState();
        // In order to display the current output from the Camera, you need to
        // 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, you need to initialize the controller. This returns a Future
        _initializeControllerFuture = _controller.initialize();
      }
    
      @override
      void dispose() {
        // Make sure to dispose of the controller when the Widget is disposed
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: 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<void>(
            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 Center(child: CircularProgressIndicator());
              }
            },
          ),
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.camera_alt),
            // Provide an onPressed callback
            onPressed: () async {
              // Take the Picture in a try / catch block. If anything goes wrong,
              // catch the error.
              try {
                // Ensure the camera is initialized
                await _initializeControllerFuture;
    
                // Construct the path where the image should be saved using the path
                // package.
                final path = join(
                  // In this example, store the picture in the temp directory. Find
                  // the temp directory using the `path_provider` plugin.
                  (await getTemporaryDirectory()).path,
                  '${DateTime.now()}.png',
                );
    
                // Attempt to take a picture and log where it's been saved
                await _controller.takePicture(path);
    
                // Attempt to compress the image
                await testCompressFile(path);
    
                // If the picture was taken, display it on a new screen
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => DisplayPictureScreen(imagePath: path),
                  ),
                );
              } catch (e) {
                // If an error occurs, log the error to the console.
                print(e);
              }
            },
          ),
        );
      }
    }
    
    // A Widget that displays the picture taken by the user
    class DisplayPictureScreen extends StatelessWidget {
      final String imagePath;
    
      const DisplayPictureScreen({Key key, this.imagePath}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('Display the Picture')),
          // The image is stored as a file on the device. Use the `Image.file`
          // constructor with the given path to display the image
          body: Image.file(File(imagePath)),
        );
      }
    }
    

@CaiJingLong
Copy link
Member

@ahde46
Because I haven't encountered this problem here, can you try use the git ref version?

Replace your pubspec.yaml version
from

dependencies:
  flutter_image_compress: ^0.5.1

to

dependencies:
  flutter_image_compress:
    git:
      url: https://github.com/OpenFlutter/flutter_image_compress.git
      ref: 3494661d21b4948670a178c5fdc60f052f7f24cf

@CaiJingLong
Copy link
Member

If the problem can be solved, please leave a message here and I will push this ref version to pub.

@ahde46
Copy link

ahde46 commented May 23, 2019

If the problem can be solved, please leave a message here and I will push this ref version to pub.

The git ref version works like a charm!

@CaiJingLong
Copy link
Member

@friebetill @ahde46
I update pub version to 0.5.2, you can use it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform: android android type: question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants