Convert java bufferedimage to PImage


#1

I am using processing.core in java to work with layered psd images using TwelveMonkeys imageIO plugins. I can successfully read and display the layers of the image using swift but cant seem to figure out how to convert the bufferedimage to a PImage.

Does anyone here have any pointers on how to do this.

Thanks

try ( ImageInputStream input = ImageIO.createImageInputStream(file) ) 
{
            // Get the reader
                Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
                if (!readers.hasNext()) {
                    throw new IllegalArgumentException("No reader for: " + file);
              }

                ImageReader reader = readers.next();

                try {

                    reader.setInput(input);
                    int numImages = reader.getNumImages(true);
                    System.out.print("reader.getnumimages = " + numImages + "\n");
                    layers = new PImage[numImages];
                    ImageReadParam param = reader.getDefaultReadParam();



                    BufferedImage image6 = reader.read(0, param);
                    int pixelArraytest[] = new int[image6.getWidth()*image6.getHeight()];
                    image6.getRGB(0,0,image6.getWidth(), image6.getHeight(), pixelArraytest, PConstants.RGB, CLOSE);
                    
                    layers[0] = img;

#2

Is this last line correct? It is important to provide an MCVE for these cases. Also, could you provide one of the images that you want to convert? Don’t forget you can broad your search by looking at way to export your image not only to Processing but to Java. I will be surprise if an answer is not out there already…

Kf


#3

@kfrajer

Thanks for the reply, for brevity I’ve re-included the whole function at the bottom of this post.

my goal is to have an array of PImages representing the layers of the psd.

The example works if I do it in pure java/swift reading all the layers using a loop that wraps the line above ( in my test psd/psb there are 15 layers ) but I get null pointer exceptions past 5 like in the example below when I include the processing core jar.

I don’t know quite understand how it happens.

All the examples ( which are quite few ) talking about how to convert a bufferedImage to PImage either don’t specifically callout processing-core in java or are from very old versions of processing ( 2 and older ). I can’t include my test psd/psb as the file is quite large ( over 1 gb); Since the example works in java/swift I don’t see the size as an issue.

public PImage[] bufferedImagePSDtoPImage(PImage[] PImageLayers , String fileDir) throws IOException {
               
        File file = new File(" path to psd file  ");
        
        try ( 
                ImageInputStream input = ImageIO.createImageInputStream(file) // Close stream in finally block to avoid resource leaks
            ) {
            // Get the reader
                Iterator<ImageReader> readers = ImageIO.getImageReaders(input);

                if (!readers.hasNext()) {
                    throw new IllegalArgumentException("No reader for: " + file);
              }

                ImageReader reader = readers.next();

                try {

                    reader.setInput(input);

                    int numImages = reader.getNumImages(true); // in my test this = 15
                    System.out.print("reader.getnumimages = " + numImages + "\n");
                    layers = new PImage[numImages];   
                    
                    ImageReadParam param = reader.getDefaultReadParam();
                   
//  manually trying to read each layer fails after reader.read(6, param)
//                    BufferedImage image0 = reader.read(0, param);
//                    BufferedImage image1 = reader.read(1, param);
//                    BufferedImage image2 = reader.read(2, param);
//                    BufferedImage image3 = reader.read(3, param);
//                    BufferedImage image4 = reader.read(4, param);
//                    BufferedImage image5 = reader.read(5, param);
                    BufferedImage image6 = reader.read(5, param);
                    layers[0] = new PImage(image6);
                
                

                // Optionally, read thumbnails, meta data, etc...
                int numThumbs = reader.getNumThumbnails(0);
                
                // ...
            } finally {
                // Dispose reader in finally block to avoid memory leaks
                reader.dispose();
            }
        }

        return layers;
    }

#4

You can check Processing’s source code and see how they do it there.

Kf


#5

@kfrajer

that sadly is not an adequate answer. Given the fact that I have seen your posts on SO and the old processing forum telling others to “look at the code” and fork a solution I can only assume you don’t care to help.

This question and questions like it have died on the vine as a result of exactly that type of answer which will always put off people who just want to get things done and get help from people who have more knowledge of this project. People who have the time to dig in to the codebase and actually help the community.

So I will do what works and just do it in pure java where this issue does not exist.


#6

I have looked at the PImage source code and it appears to have a constructor to do just what you want.

If you have a Java bufferered image object called buff_image then you can create a PImage with

PImage image = new PImage(buff_image);


#7

@sulin

As you see, you get suggestions similar (if not the same) as I suggested before. So saying that I am not trying to help is really misleading.

Now, let’s make something clear. I am a volunteer in the forum. I am not affiliated with the Processing Foundation in any way beside helping in this forum. We receive criticism that we are not polite or that we don’t do enough. Ok. Let’s put this in perspective:

  1. The number of volunteers in the forum is a handful at best. They do help from their bottom of their hearts.
  2. They are taking their own time to [A] Read your post [B] Figure it out [C] put together an answer
  3. Time is gold, as you might now
  4. We need to find a line between been polite and efficient. Currently ppl do their best based on their intentions.
  5. Your case is very interesting. You are using an external library. Even if you provide a link to your resources, it will imply somebody needs to become familiar with this library. Please note point #3
  6. You provide a code that is not complete. Are you familiar with an MCVE? You don’t have to, but it helps a lot to be able to run and reproduce your issue.
  7. To generate a proper post, please check here
  8. If something is not working in the Processing engine, you are welcome to post in github ticket

So you are saying that ppl more knowledgeable will come to assist you? Great, you might want to check the forum and see that if a question is not answered but one of us, the volunteers of this forum, it will simply not get answered at all. The Processing Foundation does not have a core of volunteers, from my understanding, to come and resolve the issues that arises from cross-integration. Even ppl that know the library needs to go back and read the source code. They will also trace it to find an answer or provide a suggestion. However, don’t hold your breadth waiting from somebody from the foundation to come to assist you. That rarely happens, and in very special circumstances. This is the challenge of Open Source projects.

If anybody needs help with their projects, you can promote it some incentive. For instance, I know that @TfGuy44 is always available to hire. He is very knowledgeable and always willing to help. In our previous forum there was a channel for Events & Opportunities where ppl would make these intentions available to all members of the community.

I understand your point and I take this moment to make things clear from my end. You can arise issues directly to the foundation, if you feel like. You can even propose solutions if you think there is a problem. I can only tell people like you that we need to take care of the volunteers in this forum as ppl get burnt helping here with the waves of questions that arrive every day.

Kf


#8

thanks for the reply,

The line you provide is what the line below does in the function ( i assume).

layers[0] = new PImage(image6);

The issue I have is that it will read the first 6 layers ( 0 through 5 ) but when trying to read past that ( 6 through 15 ) I get the nullPointerException. Which is why I reached out here to see if anyone had a similar problem.


#9

I totally understand the volunteer nature of these forums and only made the point that just saying look at the source puts people ( like me ) off. As when you search for this issue in google all you get are very old examples that either don’t work or don’t shed any light on a potential way to understand what the issue could be ( so that a proper report can be filed )

the function I provide is complete in that if you put it into any java processing project and put in a file that meets the spec ( 15 layers that is over 1gb ) it should do the same thing. I removed the loop to get to the core of the issue and to make the example as clear as I could.

I know my particular case is more esoteric than most ( using processing-core in java with ImageIO plugins to read psd files ). While looking for solutions to this it would seem that reading in psd files is a very common feature request that one would think would get attention as the goal of processing.org would appear to be to enable artists like myself to use code.

Say what you will about open source but it still exists in a world where closed source software is what people use and to ignore it only makes it harder for there to be crossover. Adobe publish the psd spec and given that twelvemonkeys have produced a series of plugins that read/write not only psd but many other formats it would seem that if the processing community wants to court people who want to use the tools they already know in new ways this would a good place to start. The number of posts in processing forums telling users of psd files to " just use xxx open source supported format " is the same as “read the source”. It assumes the person asking the question has the requisite knowledge to even understand the codebase ( which I don’t ) and that open source software can’t or won’t play nice with the commercial software in common use.

I code to experiment with ways to do my artwork. That said I constantly come back to processing ( once or twice a year ) to see if its gotten to a point where things like this don’t happen. If behind the scenes it is acting as a wrapper for java; then anything I can do in pure java I ought to be able to do in processing. So there must be some bigger ( or smaller ) issue.

Digging into codebases that were written by people who are expert ( or at least true programmers ) doesn’t shed light. I have filed bug reports on github where I could really explain issues to the people who make the project but this kind of thing is beyond my ability.


#10

It seems to me that the actual conversion of the buffered image to a PImage is not the problem, it is more likely that there are less images to be read than reported by reader.getNumImages(true) or some of the images are null.

I have modified the code which should be self explanatory. Obviously I can’t test the code so there might be the odd typo :wink:

public PImage[] bufferedImagePSDtoPImage(PImage[] PImageLayers, String fileDir) throws IOException {

  File file = new File(" path to psd file  ");

  try ( 
    ImageInputStream input = ImageIO.createImageInputStream(file) // Close stream in finally block to avoid resource leaks
    ) {
    // Get the reader
    Iterator<ImageReader> readers = ImageIO.getImageReaders(input);

    if (!readers.hasNext()) {
      throw new IllegalArgumentException("No reader for: " + file);
    }

    ImageReader reader = readers.next();

    try {

      reader.setInput(input);

      int numImages = reader.getNumImages(true); // in my test this = 15
      System.out.print("reader.getnumimages = " + numImages + "\n");

      // Create a list to hold the PImages as we can't be certain of how many
      // we actually get
      ArrayList<PImage> layerList = new ArrayList<PImage>();
      PImage[] layers;
      ImageReadParam param = reader.getDefaultReadParam();

      for (int i = 0; i < numImages; i++) {
        // Convert all non-null buffered images to a PImage and add to list
        BufferedImage bi = reader.read(i, param);
        if (bi != null) {
          layerList.add(new PImage(bi));
        }
      }
      // Convert the list to an array
      layers = layerList.toArray(new PImage[layersList.size()]);

      // Optionally, read thumbnails, meta data, etc...
      int numThumbs = reader.getNumThumbnails(0);

      // ...
    } 
    finally {
      // Dispose reader in finally block to avoid memory leaks
      reader.dispose();
    }
  }

  return layers;
}

#11

Thank you very much, I will have a look. Appreciate the effort.


#12

While I understand the barrier here, also remember that everyone working with or on Processing has been where you are! And while it might be impenetrable now, source code does soon becomes a very handy reference.

I have no idea why the Processing community would court the Adobe community any more than the reverse. But one thing I think is important to remember is that no software, or tool in general, is free. There’s always a balance of investment of time and money. And that balance with FLOSS tools is usually skewed towards time! :smile: Still, in my experience, you’ll often get more genuine help and support in an open source community than a closed source one.