Printing with AppleScript + Processing/Java

For one of the recent project, I have to write an application that generate QR code and send the generated image/file for printing.

Java printing API
Since I used processing as the development platform, I tried Java Printing API. The original plan was:

  1. Use the XZing library for code generation (https://code.google.com/p/zxing/)
  2. Using the ecoder class in the core library, a bitArray will be returned, basically it is a 1d array recording 0 & 1s, so it could be easily translated to PImage using the pixel access class.
  3. Draw the generated QRCode image to the canvas or an offscreen PGraphics.
  4. Save the image file and send the file to print.

The constrain for using Java printing API was the default PDF output library comes with Processing can only produce images that in 72dpi, and it is difficult to utilize the print options of printers (e.g. fit to page, media size…etc).

Thus despite of the initial success, this method was abandoned.

Apple script and printing
The good news is that for this project we are planning to use Mac OS X platform. After fighting with CUPS printing server back in Ubuntu time, I am planning to use BASH script to accomplish this.

Bash + Java
Before doing anything further, the first thing to test is whether Java can trigger and execute a bash script, then write a bash script that will actually print a file.

I knew that if you type “open ~/Desktop” in OS X terminal, a Finder window will actually pop up showing the content on the Desktop folder, thus I wrote a script like this.

#!/bin/bash
open Desktop

and saved the above text in openDesktop.sh, to test it I have to first make it executable

chmod +X openDesktop.sh

Then in Processing I simply put the following lines and ran it. (Reference: http://pic.dhe.ibm.com/infocenter/iseries/v6r1m0/index.jsp?topic=/rzaha/jvlngex1.htm)

try
      {
          theProcess = Runtime.getRuntime().exec("java com.ibm.as400.system.Hello");
      }
      catch(IOException e)
      {
         System.err.println("Error on exec() method");
         e.printStackTrace();  
      }

And it worked!

Print script
The next step is to find references for writing bash script that will actually print in OS X, and luckily I found some useful references

http://www.cups.org/documentation.php/options.html

Basically you can simply write a bash script like the following for printing

#!/bin/bash
ls -d PrinterName -o landscape -o fit-to-page path_to_file

In order to find the printer name, you can run the following command in terminal

lpstat -p -d

It worked like a charm until I tried with another printer (Hiti P510L)

Setting the media size
No matter how I changed the image size the printer was simply not printing. It kept showing “unsupported paper size” error. The reason for not trying this option in the beginning was that I’ve already set the default options through CUPS web interface (localhost:631), by combining this with the “-o fit-to-page” options, it should automatically convert and print. However it wasn’t the case.

Out of desperation, I tried listing and specifying the size and orientation in the bash script.

To list the supported media size, use the following command

lpoptions -p printer -l

In the actual bash script I wrote the following

lp -d printerName -o portriat -o fit-to-page -o media=6x4 filename

And it worked!

Problem solved!

Advertisements

ProcessingJS on iPad

In 21CLHK workshop, 2 participants only had iPads and one school is running iPad 1:1 instead of laptop. I suggested processingjs and sketchpad.cc as an alternative but it didn’t work out. After some tinkering I found that Chrome on IPad with the “request desktop site” function works! See the picture below.

20130128-065840.jpg

Happy programming!

21CLHK Creative Code Recap

This is a summary of the “Creative Code” workshop held in 21CLHK 2013. Thank you everyone for joining this workshop and I hope the examples can inspire you and your students!

1. Why art? Why media art?

Image

2. Dr. Nichole Pinkard’s experience in DYN project
Image

3. Different form of media arts

    • Film/TV
    • Interactive/Digital music
    • Interactive installation
    • Biotech Art
    • Robotic art
    • Network Art

4. An example of how cultural studies, traditional skill (writing), computer programming, interaction, graphics and exhibition design work together in a media art piece.

No Longer Right by Chris Cheung and XEX group (Interactive installation, 2011)
Image

5. Example 2 Massa di Voice by Golan Levin and Zach Lieberman
This example illustrated how an interactive art piece can work with live performance and requires some important “traditional” skills that we afraid it will be lost in this digital age (e.g. face to face interaction).
Image

6. Media art as IDL (InterDisciplinary Learning)
In everyday situation, we rarely encounter problem that is focused in only one field of knowledge, why do we still separate learning in different subjects in school most of the time?
Media arts as an IDL can:

    • Narrow the gap between effort and rewards.
    • Resemble some characteristics of game based learning with emphasis on in-depth research.
    • Emphasize on human interaction and expression.

7.Some media art platform that allows student to explore and learn programming in a more graphical/intuitive way. They also falls into the generative arts field.

7. Hands-on workshop on Processing

What can you do with Processing?
Image

Please refer to this page for the program we tried in the workshop.

8. Physical computing platform

Physical computing bridges the digital/virtual world that usually happens on the screen into the real world. Arduino is a very good platform that works with Processing.

Other useful resources/related materials

Introduction to Processing (21CLHK 2013)

Download and install Processing from here (www.processing.org/download/).

Pixelate patch

Screen Shot 2013-01-26 at 10.52.02 AM

// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com

// Example 16-7: Video pixelation

import processing.video.*;

// Size of each cell in the grid, ratio of window size to video size

int videoScale = 20;

// Number of columns and rows in our system

int cols, rows;

// Variable to hold onto Capture object
Capture video;
void setup() {
 size(640,480);

 // Initialize columns and rows
 cols = width/videoScale;
 rows = height/videoScale;
 video = new Capture(this,cols,rows,30);
 video.start(); 
 rectMode(CENTER);
 ellipseMode(CENTER);
}
void draw() {
 // Read image from the camera
 if (video.available()) {
 video.read();
 }
 video.loadPixels();

 // Begin loop for columns
 for (int i = 0; i < cols; i++) {
 // Begin loop for rows
 for (int j = 0; j < rows; j++) {

 // Where are we, pixel-wise?
 int x = i*videoScale;
 int y = j*videoScale;
 // Looking up the appropriate color in the pixel array
 color c = video.pixels[i + j*video.width];
 fill(c);
 stroke(0);
 //rect(x,y,videoScale,videoScale);
 ellipse(x, y, videoScale,videoScale);
 /*
 if (x%(videoScale*2)==0){
   ellipse(x, y, videoScale,videoScale); 
   }else{
    rect(x,y,videoScale,videoScale); 
  }
 */
  }
 }
}

Multithreaded Email class in Processing

Based on Daniel Shiffman’s Email code, I’ve modified it and changed it to a multithreaded version for sending email in Processing Sketch.

This example allows you to click and add an email in the stack and you can attach a file with it.
You will need to include a folder called “Code” with smtp.jar, pop3.jar, mailapi.jar, imap.jar and activation.jar in your sketch folder. This could be downloaded from Dan’s Example as well.

http://www.shiffman.net/2007/11/13/e-mail-processing/


Email_multithreaded.pde

// Daniel Shiffman
// http://www.shiffman.net

// Example functions that send mail (smtp)
// You can also do imap, but that's not included here

// A function to check a mail account

//Multithread version modified by Hamlet Lin@2012

import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

Thread tt;
EmailSender emailSender;
String printFolder;
PFont sysFont;
void setup(){
printFolder=dataPath("")+"\\";
emailSender=new EmailSender();
tt=new Thread(emailSender);
tt.start();
size(400, 400);
sysFont=createFont("arial", 12);
textFont(sysFont, 12);
}

void draw(){
fill(255);
textAlign(CENTER);
textFont(sysFont);
background (color(frameCount%255, frameCount%512, frameCount%786));
text(emailSender.sendingEmail+"", width/2, height/2);
}

void mouseReleased(){
emailSender.addMail("asad@example.com", "fileNameInDataPath");
}

class EmailSender implements Runnable {
ArrayList emailAddresses;
ArrayList fileNames;
boolean sendingEmail=false;

public EmailSender() {
emailAddresses=new ArrayList();
fileNames=new ArrayList();
}
void run(){
while (1!=0){
//println("mail left: "+emailLeft);
if (emailAddresses.size()>0){
sendingEmail=true;
//println((String)emailAddresses.get(0));
sendMail((String)emailAddresses.get(0), (String)fileNames.get(0));
emailAddresses.remove(0);
fileNames.remove(0);
}else{
sendingEmail=false;
}
}
}

void addMail(){
emailAddresses.add("");
fileNames.add("");
// println("emailLeft: "+emailLeft);
}
void addMail(String _reciever, String _filename){
emailAddresses.add(_reciever);
fileNames.add(_filename);
// println("emailLeft: "+emailLeft);
}

// A function to send mail
void sendMail(String _reciever, String _fileName) {
// Create a session
String host="smtp.gmail.com";
Properties props=new Properties();

// SMTP Session
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth", "true");
// We need TTLS, which gmail requires
props.put("mail.smtp.starttls.enable","true");

// Create a session
Session session = Session.getDefaultInstance(props, new Auth());
DataSource source = new FileDataSource(printFolder+_fileName);

try
{
MimeMessage msg=new MimeMessage(session);
msg.setFrom(new InternetAddress("", ""));
msg.addRecipient(Message.RecipientType.BCC,new InternetAddress(_reciever));
msg.setSubject("Email with Processing");
BodyPart messageBodyPart = new MimeBodyPart();
// Fill the message
messageBodyPart.setText("Email sent with Processing");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
// Part two is attachment
messageBodyPart = new MimeBodyPart();
// DataSource source = new FileDataSource(dataPath(_fileName));
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(_fileName);
multipart.addBodyPart(messageBodyPart);
msg.setContent(multipart);
msg.setSentDate(new Date());
Transport.send(msg);
println("Mail sent!");
}
catch(Exception e)
{
e.printStackTrace();
}

}

}

void stop() {
super.stop();
}

Auth.pde

// Daniel Shiffman
// http://www.shiffman.net

// Simple Authenticator
// Careful, this is terribly unsecure!!

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

public class Auth extends Authenticator {

public Auth() {
super();
}

public PasswordAuthentication getPasswordAuthentication() {
String username, password;
username = "asfaf@gmail.com";
password = "password";
System.out.println("authenticating. . ");
return new PasswordAuthentication(username, password);
}
}