Reputation: 573
What my application does:
1- The user can take a picture through the device camera. (works)
2- The application creates a new File with the following folders (tested with the following folders to make sure that it saves the file properly):
a. File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "images");
- File mediaFile = new File(mediaStorageDir.getPath()+File.separator+fileName + ".jpg");
b. File mediaStorageDir = new File(Gdx.files.getExternalStoragePath().toString());
- File mediaFile = new File(mediaStorageDir.getPath()+File.separator+fileName+".jpg");
c. File mediaStorageDir = new File(Gdx.files.getLocalStoragePath().toString());
- File mediaFile = new File(mediaStorageDir.getPath()+File.separator+fileName+".jpg");
3- The application rescales+compresses the picture down to 1024x512 with bmp.compress(quality=25), then saves it. (works)
public boolean compressToFile(byte[] data, int quality, File fileHandle) {
File mediaFile = fileHandle;
Pixmap pixmap = new Pixmap(data, 0, data.length);
if(quality<0)
quality = 0;
if(quality>100)
quality = 100;
FileOutputStream fos;
int x=0,y=0;
int xl=0,yl=0;
try {
Bitmap bmp = Bitmap.createBitmap(pixmap.getWidth(), pixmap.getHeight(), Bitmap.Config.ARGB_8888);
// we need to switch between LibGDX RGBA format to Android ARGB format
for (x=0,xl=pixmap.getWidth(); x<xl;x++) {
for (y=0,yl=pixmap.getHeight(); y<yl;y++) {
int color = pixmap.getPixel(x, y);
// RGBA => ARGB
int RGB = color >> 8;
int A = (color & 0x000000ff) << 24;
int ARGB = A | RGB;
bmp.setPixel(x, y, ARGB);
}
}
fos = new FileOutputStream(mediaFile, false);
boolean compressed = bmp.compress(CompressFormat.JPEG, quality, fos);
if(compressed)
System.out.println("zgzg2020:: compressed SUCCESS!");
else
System.out.println("zgzg2020:: compressed FAILED!");
fos.close();
int WIDTH = 1024, HEIGHT = 512;
File f = mediaFile;
Bitmap shrunkBmp = downsizeImage(f, WIDTH, HEIGHT);
fos = new FileOutputStream(mediaFile, false);
shrunkBmp.compress(CompressFormat.JPEG, 100, fos);
fos.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
return false;
}
Scale down.
public Bitmap downsizeImage(File file, int width, int height) {
BitmapFactory.Options opts = new BitmapFactory.Options ();
opts.inSampleSize = 2; // for 1/2 the image to be loaded
Bitmap thumb = Bitmap.createScaledBitmap(BitmapFactory.decodeFile(file.getPath(), opts), width, height, false);
return thumb;
}
4- To confirm that the jpg was saved properly. I've tested with all the three above paths.
System.out.println("b4 pictureFile= " + file.getPath().toString() + "=> " + file.exists());//Returns false.
compressToFile(data, quality, file);//Here is where the compression, scale down, write to disk.
System.out.println("af pictureFile= " + file.getPath().toString() + "=> " + file.exists());//Returns true
5- Read that saved picture and render it on screen. The application crashes here!!!
mode = Mode.render;
System.out.println("AssessPath:"+file.toString());//to confirm the path
texture = new Texture(file.toString());//(FAILS!!)
ERROR
com.badlogic.gdx.utils.GdxRuntimeException: Couldn't load file
Notes:
I've tested my application on two machines, Marshmallow, Lollipop. Fails on both with the same error.
Permissions seem proper:
After saving the files on the machine, I manually copied the files into the assets folder. The application was able to open the file; so I'm sure that the file meets the LibGDX resolution...etc requirements.
I've searched through so many articles and question/answers, couldn't find the cause for my problem:
https://github.com/libgdx/libgdx/wiki/File-handling#writing-to-a-file
https://github.com/libgdx/libgdx/wiki/Integrating-libgdx-and-the-device-camera
com.badlogic.gdx.utils.GdxRuntimeException: Couldn't load file: - Error
Upvotes: 1
Views: 687
Reputation: 19776
I'm doing this with platform specific code. This interface is used in the core code.
public interface GalleryOpener {
void openGallery();
String getSelectedImagePath();
}
And this is the implementation on android.
public class AndroidLauncher extends AndroidApplication implements GalleryOpener {
public static final int SELECT_IMAGE_CODE = 1;
private String selectedImagePath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
initialize(new GreenWall(this), config);
}
@Override
public GalleryOpener galleryOpener() {
return this;
}
@Override
public void openGallery() {
selectedImagePath = null;
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Image"), SELECT_IMAGE_CODE);
}
@Override
public String getSelectedImagePath() {
return selectedImagePath;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == SELECT_IMAGE_CODE) {
Uri imageUri = data.getData();
selectedImagePath = getPath(imageUri);
}
//super.onActivityResult(requestCode, resultCode, data);
}
private String getPath(Uri uri) {
if (uri.getScheme().equalsIgnoreCase("file")) {
return uri.getPath();
}
Cursor cursor = getContentResolver().query(uri, new String[]{MediaStore.Images.Media.DATA}, null, null, null);
if (cursor == null) {
return null;
}
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String filePath = cursor.getString(column_index);
cursor.close();
return filePath;
}
}
Using this can look like that:
galleryOpener.openGallery();
String selectedImagePath = galleryOpener.getSelectedImagePath();
if (selectedImagePath != null) {
FileHandle fileHandle = Gdx.files.absolute(selectedImagePath);
Texture texture = new Texture(fileHandle);
}
Upvotes: 1