How to fix ClassCastException error in Processing?

Hi!

I’m working on a project that involves two PCs that simultaneously share and exchange the webcam source and send it, modified, to the other PC.

The script I’m relying on I found at https://github.com/torb-xyz/processing-experiments, merging CamNetClient, CamNetServer and JPEGEncode.

With some scripts it seems to work. Instead, in the script below it gives me the following error:

ClassCastException: class sun.java2d.SunGraphics2D cannot be cast to class java.awt.image.BufferedImage (sun.java2d.SunGraphics2D and java.awt.image.BufferedImage are in module java.desktop of loader 'bootstrap')

Here is the script:

SCRIPT

import processing.net.*;
import processing.video.*;

Client client;
Capture cam;
JPGEncoder jpg;

int state=0;
float scale=1.0;

PGraphics img; 

Server server;
JPGEncoder jpg1;
PImage img1;

final int TIMEOUT_MILLI = 1 * 3000;


void setup() {
  noCursor();
  imageMode(CENTER);
  size(1920,1080);
  background(255);
  img=createGraphics(640, 480);
  jpg = new JPGEncoder();
  jpg1 = new JPGEncoder();
  // Start a server at port 5204
  server = new Server(this, 5204);  

  img1 = createImage(100, 100, RGB);
  println("Starting server");

  cam = new Capture(this, Capture.list()[0]);
  cam.start();

  String server = "127.0.0.1";
  client = new Client(this, server, 5203); 
  
  println("Starting client");
}

void draw() {
  
  checkForIncomingImage();
  image(img1, 1100, 100);

if (cam.available()) {
    println("Cam available. Going to read");
    cam.read();
    try {
      println("Getting image to memory");
      
      background(0);
      
  img.beginDraw();
  img.image(cam,0,0); 
  img.endDraw();

img.loadPixels(); 
  
  for (int x = 0; x < img.width; x++) { 
    for (int y = 0; y < img.height; y++) {
      int loc = x+y*img.width;
      float r = red(img.pixels[loc]); 
      float g = green(img.pixels[loc]);
      float b = blue(img.pixels[loc]);
      float d = dist(mouseX, mouseY, x, y); 
     
      float factor = map(d, 0, 200, 2, 0); 
      img.pixels[loc] = color(r*factor, g*factor, b*factor);
      
    }
  }
  img.updatePixels();

  translate(width/2,height/2);
  scale(scale);
  image(img,160,100);

      println("Encoding");
      byte[] jpgBytes = jpg.encode(img, 0.1F);   //img

      println("Writing file length to server: " + jpgBytes.length);
      // Taken from: https://processing.org/discourse/beta/num_1192330628.html
      client.write(jpgBytes.length / 256);
      client.write(jpgBytes.length % 256);

      println("Writing jpg bytes to server");
      client.write(jpgBytes);
    } catch (IOException e) {
      // Ignore failure to encode
      println("IOException");
    }
  }
}

void mousePressed(){
  state=(state+1)%2;  //Change state to either 0 or 1
  scale= state==0 ? 1.0 : 3.0;
  surface.setTitle("State:"+state+" scale:"+scale);
}

void checkForIncomingImage() {
  Client nextClient = server.available();

  if (nextClient != null && nextClient.available() >= 2) {
    println("More than two bytes available. Trying to get length.");

    // Taken from: https://processing.org/discourse/beta/num_1192330628.html
    int imageByteLength = nextClient.read()*256 + nextClient.read();

    println("Length is " + imageByteLength + ". Waiting for whole image.");
    int startMilli = millis();
    while (true) {
      // Wait for the image...

      // Abort if timeout has run out
      if ((millis() - startMilli) > TIMEOUT_MILLI) {
        println("Timeout.");
        nextClient.clear();
        break;
      }

      // Load it if finished
      if (nextClient.available() >= imageByteLength) {
        println("Enough in buffer, reading in...");
        byte[] jpgBytes = new byte[imageByteLength];
        nextClient.readBytes(jpgBytes);
        nextClient.clear();
        try {
          img1 = jpg.decode(jpgBytes);
        } 
        catch (IOException e) {
          println("IOException in reading jpgbytes");
        } 
        catch (NullPointerException e) {
          println("NullPointerException in reading jpgbytes");
        } 
        catch (ArrayIndexOutOfBoundsException e) {
          println("ArrayIndexOutOfBoundsException in reading jpgbytes");
        }
        finally {
          break;
        }
      }
    }
  }
}

JPGEncoder SCRIPT:

import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.ImageWriteParam;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import javax.imageio.IIOImage;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;

public class JPGEncoder {

  byte[] encode(PImage img, float compression) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
    ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
    ImageWriteParam param = writer.getDefaultWriteParam();
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    param.setCompressionQuality(compression);

    // ImageIO.write((BufferedImage) img.getNative(), "jpg", baos);
    writer.setOutput(new MemoryCacheImageOutputStream(baos));

    writer.write(null, new IIOImage((BufferedImage) img.getNative(), null, null), param);

    return baos.toByteArray();
  }

  byte[] encode(PImage img) throws IOException {
    return encode(img, 0.5F);
  }

  PImage decode(byte[] imgbytes) throws IOException, NullPointerException {
    BufferedImage imgbuf = ImageIO.read(new ByteArrayInputStream(imgbytes));
    PImage img = new PImage(imgbuf.getWidth(), imgbuf.getHeight(), RGB);
    imgbuf.getRGB(0, 0, img.width, img.height, img.pixels, 0, img.width);
    img.updatePixels();

    return img; 
  }

}

Could you give me some suggestions on how to solve the error?
Thanks in advance

HI @michele_rinaldi,

which version of processing you’re using ?
Would you please try to set the P2D renderer on your test environment and try it again ?

size(1920,1080,P2D);

img=createGraphics(640, 480,P2D);

Cheers
— mnse