Load Image in and outside data folder

The question is, I can upload images via:
img = loadImage(“img.png”);

And then they will be loaded from the sketch.
But can I at the same time in the sketch (data folder) them:
img = loadImage(“subfloder/img.png”);
???

I need to distribute a lot of my images into subfolders in my sketch, but I don’t know how to do it.

1 Like

the person who tweaks my threads every time, THANK YOU SO MUCH AND FORGIVE ME. I TRULY TRY TO DO EVERYTHING RIGHT, BUT I ONLY USE THIS FORUM ONCE A SIX YEAR AND FORGET WHAT IS HERE AND HOW.

here… this works for me…


// 
PImage pg1; 

void setup() {
  size(1222, 1222); 
  String s1=dataPath("");
  println(s1); 
  pg1 = loadImage(s1+"//"+"2016.jpg");
}

void draw() {
  image(pg1, 
    22, 22);
}
//
2 Likes

You are the best!

This is really what you need. Thank. God bless you!

1 Like

Hello!!!
I’m try your solution, but not working for me
I catch java.lang.IllegalArgumentException: File /data/user/0/com.erkgjer.test/files/sgip.png contains a path separator

PImage i;
void setup(){
    String s1=dataPath("");
  println(s1); 
  i = loadImage(s1+"/"+"sgip.png");
}
void draw(){
   image(i, mouseX-150, mouseY-150,300, 300);
}

You need a double // here. It might depend a bit on your operating system.

s1+"//"+"sgip.png"

@Chrisir
Yes,I try it but not work for me

java.lang.IllegalArgumentException: File /data/user/0/processing.test.androidtest/files//sgip.png contains a path separator
I cannot open this folder and see what is there, because even through adb there is no access to it

why is the folder not being created along the path /emulated/storage/0/Android/data/com ....?

the data folder i add, scketch->addFile

I this for Android device?

Because it says processing in the section?

oops
Yes, I’m doing this for android, can you tell me if you know or where to write?

I assume you want to load and save images outside the data folder.
Since the latest 10/11 android versions, this is more difficult because Android is implementing “Scoped Storage”, for security reasons.
Before you could use the method

Environment.getExternalStorageDirectory()

but it’s deprecated above Pie (version 28) It can still be used on Android 10 using

android:requestLegacyExternalStorage=“true”

in the Manifest, but above that, you need another solution. Tomorrow I will look into this. For the moment I’ll leave an updated code I recently wrote for all android versions to upload an image with your build-in android image explorer.
However, you have to set your SDK target from 17 to 29.

import android.net.Uri; 
import android.database.Cursor; 
import android.content.Intent; 
import android.provider.MediaStore; 
import android.app.Activity; 
import android.content.Context; 
import android.graphics.Bitmap; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileOutputStream; 
import android.os.Environment; 
import android.graphics.BitmapFactory; 
import android.Manifest; 
import android.content.pm.PackageManager; 
import android.os.Build; 
import android.os.Build.VERSION_CODES; 
import processing.core.PConstants;

Activity activity; 
Context context; 
PImage img; 
boolean image_loaded; 

void setup() { 
  fullScreen(); 
  background(#F9C454); 
  fill(#4A3A16); 
  textSize(38); 
  textAlign(CENTER); 
  text("Click to open Image Explorer", width/2, height/3); 
  activity = this.getActivity(); 
  context = activity.getApplicationContext(); 
  if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { 
    requestParticularPermission();
  }
} 

void draw() { 
  if (image_loaded) {
    background(255);
    image(img, 0, 0);
  }
} 

void mousePressed() { 
  openImageExplorer();
} 

@Override 
  void onActivityResult(int requestCode, int resultCode, Intent data) { 
  super.onActivityResult(requestCode, resultCode, data); 
  if (requestCode == 1) { 
    if (resultCode == activity.RESULT_OK) { 
      if (data != null) {
        Uri image_uri = data.getData(); 
        String[] filePathColumn = { MediaStore.Images.Media.DATA };
        Cursor cursor = context.getContentResolver().query(image_uri, filePathColumn, null, null, null); 
        cursor.moveToFirst(); 
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]); 
        String imgDecodableString = cursor.getString(columnIndex); 
        cursor.close();
        println(imgDecodableString); 
        if (Build.VERSION.SDK_INT >= 28) {
          try { 
            InputStream ips = context.getContentResolver().openInputStream(image_uri); 
            Bitmap bitmap = BitmapFactory.decodeStream(ips);
            img = new PImage(bitmap.getWidth(), bitmap.getHeight(), PConstants.ARGB);
            bitmap.getPixels(img.pixels, 0, img.width, 0, 0, img.width, img.height);
            img.updatePixels();
            image_loaded = true;
          }
          catch (Exception e) { 
            e.printStackTrace();
          }
        } else { 
          img = loadImage(imgDecodableString); 
          image_loaded = true;
        }
      } else {
        println("No data");
      }
    }
  }
} 

private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; 
private void requestParticularPermission() { 
  activity.requestPermissions(PERMISSIONS_STORAGE, 2020);
}

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
  switch (requestCode) { 
  case 2020: 
    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
      println("permissions granted");
    } else { 
      println("permissions not granted");
    } 
    break; 
  default: 
    activity.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }
}

void openImageExplorer() {
  Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 
  intent.setType("image/*"); 
  activity.startActivityForResult(intent, 1);
}

I tested this code for loading an image placed outside the data folder on Lollipop and Android 10.

// Do not forget to give READ/WRITE permission

import android.os.Environment;
import android.Manifest; 
import android.content.pm.PackageManager; 
import android.os.Build; 
import android.os.Build.VERSION_CODES; 
import processing.core.PConstants;
import android.app.Activity; 

String image_folder = "MyPhotos"; // Must be an existing folder
PImage img;
boolean image_loaded;
Activity activity; 

void setup() {
  size(displayWidth, displayHeight);
  background(0, 0, 200); 
  textAlign(CENTER);
  String str = "Click to load image.";
  textSize(12);
  float twf = width/textWidth(str);
  textSize(8*twf);
  text(str, width/2, height/2);
  activity = this.getActivity();
  if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { 
    requestParticularPermission();
  }
  imageMode(CENTER);
}

void draw() {
  if (image_loaded) {
    if (img != null) {
      background(0, 0, 200); 
      image(img, width/2, height/2);
    } else {
      text("Image could not be found", width/2, height/2);
    }
  }
}

void mousePressed() {
  loadMyImage("jelly.jpg");
}

void loadMyImage(String s) {
  try {
    String directory = new String(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+image_folder+"/");
    img = loadImage(directory+s);
    image_loaded = true;
  } 
  catch (Exception e) {
    background(0, 0, 200);
    text("Image could not be found.", width/2, height/2);
  }
}

private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; 
private void requestParticularPermission() { 
  activity.requestPermissions(PERMISSIONS_STORAGE, 2020);
}

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
  switch (requestCode) { 
  case 2020: 
    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
      println("permissions granted");
    } else { 
      println("permissions not granted");
    } 
    break; 
  default: 
    activity.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }
}

1 Like

I tested this code for saving images outside the data folder on Android 10 and Lollipop.

// Do not forget to give READ/WRITE permission
import android.os.Environment;
import android.Manifest; 
import android.content.pm.PackageManager; 
import android.os.Build; 
import android.os.Build.VERSION_CODES; 
import processing.core.PConstants;
import android.app.Activity; 

PImage img;
Activity activity; 
boolean image_saved;
boolean permissions_granted;

// Folowing file name is the folder you save your image file in.
// If it does not exist it will be created automatically
String folder_name = "MyImageFolder";

// Folowing string is the name of your image file
// Be sure to include extension.
String image_file = "MyImage.png";

void setup() {
  size(displayWidth, displayHeight);
  background(0, 0, 200); 
  rectMode(CENTER);
  rect(width/2, height/2, width, height/2);
  textAlign(CENTER);
  String str = "Click to save an image.";
  textSize(12);
  float twf = width/textWidth(str);
  textSize(8*twf);
  fill(0);
  text(str, width/2, height/2);
  activity = this.getActivity();
  if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { 
    requestParticularPermission();
  }
  img = get();
}

void draw() {
  if (permissions_granted && image_saved) {
    background(0, 0, 200);
    fill(255);
    text("Image saved.", width/2, height/2);
  } 
}

void mousePressed() {
  saveMyImage(folder_name, image_file);
}

void saveMyImage(String sf, String tf) { 
  try { 
    String absolute_path = new String(Environment.getExternalStorageDirectory().getAbsolutePath()); 
    File file = new File(absolute_path+"/"+sf); 
    println(file);
    if (!file.exists()) { 
      boolean success = true; 
      success = file.mkdirs();
    } 
    save(file+"/"+tf);
    image_saved = true;
    println("File saved successfully.");
  } 
  catch (Exception e) { 
    println("Error while saving file: " + e);
  }
}

private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; 
private void requestParticularPermission() { 
  activity.requestPermissions(PERMISSIONS_STORAGE, 2020);
}

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
  switch (requestCode) { 
  case 2020: 
    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
      println("permissions granted");
      permissions_granted = true;
    } else { 
      println("permissions not granted");
    } 
    break; 
  default: 
    activity.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }
}

1 Like

@Chrisir, @noel, @Nik_Gun ===
there are 3 or 4 questions in this post:

  • first one was (@Nik_Gun) how to load images from sub folder inside the data folder without the error explained in ths post (this file contains a path separator…) ; answer from @Chrisir does not works in this case.With android it will fire the same error . From a technical point of view that is the result of the classical way for loading an image (or some file) with P5: it uses fileInput and fileInput is waiting for the name of the file, and not the complete path (with 1 or more pathSeparators).
  • @noel explains another thing= how to get a file from the external dir storage or save it.That is not the same problem i think; and the other presision (“scopedStorage”) though it could be important it does not matter here (of course what is said about permissions by @noel is exact)
    In order to answer to @Nik_Gun (and others in the same case) the best way for android is to use the android AssetManager Api and kook inside the data directory : in the code below i have 2 subfolders inside data , the first one is callled “autredos” the second is called autresousdoss; here you put your images. The code below will get a image from the “autresousdos”; that will be done through the “special” loadImages function which is able to add all images in an array: then you choose the image from the list. Try!

import android.content.Context;
import android.app.Activity;
import android.content.res.AssetManager;

PImage imga;// the image which is inside the subfolder called "autredos" and you want to get
Activity act;
String finalPath;
PImage[] img;// arrayList for all images

void setup(){
  size(600,400);
  background(255);
  act= this.getActivity();
  img = loadImages("autredos"+"/"+"autresousdos");// for creating the list in the subfolder
  imga = img[0];// here i suppose that i know the image i will display; in some cases you have to create a list view and can choose from it
  
  
}

void draw(){
  background(255,0,0);
  image(imga, 0, 0); //displaying the image imaga, in the subfolder
}


PImage[] loadImages(String folderName_){
  
  
  AssetManager assetManager = act.getAssets();
  try{
    String[] imgPath = assetManager.list(folderName_);
    println(imgPath.length);
    File[] files = new File[imgPath.length];
    
    img = new PImage[imgPath.length];
     for(int i=0; i<imgPath.length; i++){
       println (imgPath[i]);
    
     img[i] = loadImage(folderName_ + "/" + imgPath[i]);
     files[i] = new File(folderName_+"/" + imgPath[i]);//pour des fichiers quelconque, here you can find all folders
     println("file=====" + files[i]);
    }
    
    
  }
  catch(IOException ex){
       System.out.println (ex.toString());   
  }
  
  return img;
}
4 Likes

Yeah, I assumed OP meant processing, not Android

I changed the category of the post to Android

Hi @akenaton
Great to see you back. I hope you had a complete recovery.
And yes, you are right. That was the actual question. I did not read the whole topic.
But anyway, someone searching will now find the whole gamma of possible image saving on Android.
I also fixed my code because of course there, permissions are always needed.
May I copy your code to my repo?

@noel === Happy to read you again, though i am always in hospital and waiting for a new operation on the 8 of Janvier; till this date i give a look to the posts and try to answer… Your idea fo a repo is defintely an excellent one and if you want to add some code from me, do as you want…I think only that you have to simplify : eg; mandelbrot has nothing to see withe menus or submenus…

2 Likes