Skip to content

Instantly share code, notes, and snippets.

@daan
Last active September 27, 2020 04:57
Show Gist options
  • Save daan/8ff33a92ed4572fd953151de3181591e to your computer and use it in GitHub Desktop.
Save daan/8ff33a92ed4572fd953151de3181591e to your computer and use it in GitHub Desktop.
Super simple streaming video (mjpeg) in processing over an oscP5 tcp link.
/*
a simple jpeg encoder / decoder class
based on java standard libraries.
USAGE:
byte[] b = compressJpg(img,0.5);
PImage imgCompressed = decompressImage(b);
0.0 100% compression
1.0 0% compression
*/
import java.awt.image.BufferedImage;
import javax.imageio.plugins.jpeg.*;
import javax.imageio.*;
import javax.imageio.stream.*;
import java.util.Iterator;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.awt.image.BufferedImage;
byte[] compressJpg(PImage img, float compressionQuality)
{
byte[] compressed;
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpegParams.setCompressionQuality(1f);
// copy image into a buffered image
BufferedImage out = new BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_RGB);
for (int i=0; i<img.pixels.length; i++) {
out.setRGB(i % img.width, i/img.width, img.pixels[i]);
}
try {
// prepare a byte array stream to receive the jpg data
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ImageOutputStream buffer2 = ImageIO.createImageOutputStream(buffer);
Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer = iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(compressionQuality);
writer.setOutput(buffer2);
writer.write(null, new IIOImage(out,null,null),iwp);
writer.dispose();
buffer.flush();
byte[] bytesOut = buffer.toByteArray();
buffer.close();
return bytesOut;
}
catch (Exception e) {
System.out.println(e);
}
return null;
}
/*
i suppose this should work with any image
*/
PImage decompressImage(byte[] compressedImage) {
try {
// make a buffered image.
ByteArrayInputStream bufferIn = new ByteArrayInputStream(compressedImage);
BufferedImage in = ImageIO.read(bufferIn);
// prepare a processing image
PImage imageOut = new PImage( in.getWidth(null), in.getHeight(null));
imageOut.loadPixels();
// copy pixels
for (int x=0; x< in.getWidth(null); x++ ) {
for (int y=0; y< in.getHeight(null); y++ ) {
int rgb = in.getRGB(x, y);
imageOut.pixels[y*in.getWidth(null)+x] = rgb;
}
}
return imageOut;
}
catch (Exception e) {
System.out.println(e);
}
return null;
}
/*
streaming video between two processing sketches.
* no audio
* mjpeg ( frame by frame compression )
* over a tcp link ( osc )
* use the jpeg sketch for encoding/decoding
*/
import oscP5.*;
import netP5.*;
OscP5 client;
PImage imgIn;
void oscEvent(OscMessage msg) {
if( ! msg.checkAddrPattern("/video") ) return;
if( ! msg.checkTypetag("b") ) return;
byte[] b = msg.get(0).bytesValue();
// uncompress
imgIn = decompressImage(b);
}
void setup() {
size(320, 240);
client = new OscP5(this, "127.0.0.1", 12000, OscP5.TCP);
// client sends a message to connect to the server.
client.send("/new", new Object[] {new Integer(1)});
}
void draw() {
if (imgIn == null) return;
image(imgIn, 0, 0);
}
/*
streaming video between two processing sketches.
* no audio
* mjpeg ( frame by frame compression )
* over a tcp link ( osc )
* use the jpeg sketch for encoding/decoding
*/
import processing.video.*;
import oscP5.*;
import netP5.*;
OscP5 server;
Capture cam;
PImage imgOut;
void sendFrame(PImage img) {
TcpServer s = server.tcpServer();
if( s == null ) return; // should not happen
if( s.size() == 0) return; // no connected clients
// we send the frame to the first client only
TcpClient c = s.getClients()[0];
byte[] bimg = compressJpg(img, 0.7);
OscMessage msg= new OscMessage("/video");
msg.add(bimg);
server.send(msg, c);
}
/*
void oscEvent(OscMessage msg) {
println("received package");
}
*/
void setup() {
size(320, 240);
server = new OscP5(this, 12000, OscP5.TCP);
cam = new Capture(this, 320, 240);
cam.start();
}
void draw() {
if (cam.available() == true) {
cam.read();
imgOut = cam.copy();
sendFrame(imgOut);
}
if(imgOut == null) return;
image(imgOut, 0, 0);
}
@SableRaf
Copy link

SableRaf commented Jul 9, 2016

I tried running this but I am getting a “No library found for com.sun.image.codec.jpeg”. Searching for an answer, I found this StackOverflow thread discussing the use of "sun" classes: http://stackoverflow.com/questions/1906673/import-com-sun-image-codec-jpeg

@daan
Copy link
Author

daan commented Jul 10, 2016

thanks. it is fixed now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment