Playing with the Gimp server: my notebook
In the following post, I'll show how the Gimp can be used as a server that will read and execute some statements in the scheme programming language. The scheme script will be used to downlad, resize and filter an image from the web.
Starting the Gimp Server
Go in menuFilters
→Script-Fu
→Start Server
The original image
The script
Here is the scheme script:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;load an image of Baraba McClintock (1983 Nobel Laureate) who discovered the transposons | |
(define img (car (file-uri-load | |
RUN-NONINTERACTIVE | |
"BarbaraMcClintock" | |
"http://upload.wikimedia.org/wikipedia/commons/f/f6/Barbara_McClintock_at_C.S.H._1947.jpg" | |
) )) | |
;;get the layer for this image | |
(define layer (car (gimp-image-get-active-layer img ) )) | |
;;scale the image so its' width is 400px | |
(gimp-image-scale img 400 (* 400 (/ (car (gimp-image-height img)) (car (gimp-image-width img)) ) ) ) | |
;;call the filter Oilify | |
(plug-in-oilify RUN-NONINTERACTIVE img layer 7 1) | |
;;save this image as /tmp/mcclintock.png | |
(file-png-save-defaults RUN-NONINTERACTIVE img layer "/tmp/mcclintock.png" "BarbaraMcClintock") | |
;;end |
The java client
The following java client will send the previous scheme script to the gimp server. The simple protocol used by GIMP is described on this page.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.BufferedReader; | |
import java.io.FileReader; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.io.OutputStream; | |
import java.io.Reader; | |
import java.io.StringReader; | |
import java.net.Socket; | |
public class GimpClient | |
{ | |
private String host="localhost"; | |
private int port=10008; | |
private void run(Reader r) throws Exception | |
{ | |
StringBuilder schemeScriptBuilder=new StringBuilder(); | |
int c; | |
while((c=r.read())!=-1) schemeScriptBuilder.append((char)c); | |
String schemeScript=schemeScriptBuilder.toString(); | |
if(schemeScript.length()>Short.MAX_VALUE) throw new IOException("Script is too large ("+schemeScript.length()+")"); | |
byte input[]=schemeScript.getBytes(); | |
OutputStream out=null; | |
InputStream in=null; | |
Socket socket=null; | |
try | |
{ | |
socket= new Socket(this.host,this.port); | |
//socket.setSoTimeout(10*1000); | |
out=socket.getOutputStream(); | |
in=socket.getInputStream(); | |
out.write('G'); | |
short queryLength=(short)input.length; | |
out.write(queryLength/256); | |
out.write(queryLength%256); | |
out.write(input); | |
out.flush(); | |
int G=in.read(); | |
if(G!='G') throw new IOException("Expected first byte as G"); | |
int code=in.read(); | |
if(code!=0) throw new IOException("Error code:"+code); | |
int contentLength= in.read()*255 + in.read(); | |
byte array[]=new byte[contentLength]; | |
int nRead=0; | |
int n=0; | |
while((n=in.read(array, nRead, array.length-nRead))>0) | |
{ | |
nRead+=n; | |
} | |
if(nRead!=contentLength) throw new IOException("expected "+contentLength+" but got "+nRead+" bytes"); | |
System.out.println(new String(array)); | |
} | |
catch(Exception err) | |
{ | |
throw new IOException(err); | |
} | |
finally | |
{ | |
if(in!=null) in.close(); | |
if(out!=null) out.close(); | |
if(socket!=null) socket.close(); | |
} | |
} | |
public static void main(String[] args) | |
{ | |
try { | |
GimpClient app=new GimpClient(); | |
String script=null; | |
int optind=0; | |
while(optind<args.length) | |
{ | |
if(args[optind].equals("-h")) | |
{ | |
System.out.println("Pierre Lindenbaum."); | |
System.out.println("Options:"); | |
System.out.println(" -H <host> default:"+app.host); | |
System.out.println(" -P <port> default:"+app.port); | |
System.out.println(" -e 'script' (optional)"); | |
System.out.println("<stdin|files>"); | |
return; | |
} | |
else if(args[optind].equals("-H")) | |
{ | |
app.host=args[++optind]; | |
} | |
else if(args[optind].equals("-P")) | |
{ | |
app.port=Integer.parseInt(args[++optind]); | |
} | |
else if(args[optind].equals("-e")) | |
{ | |
script=args[++optind]; | |
} | |
else if(args[optind].equals("--")) | |
{ | |
optind++; | |
break; | |
} | |
else if(args[optind].startsWith("-")) | |
{ | |
System.err.println("Unnown option: "+args[optind]); | |
return; | |
} | |
else | |
{ | |
break; | |
} | |
++optind; | |
} | |
if(script!=null && optind!=args.length) | |
{ | |
System.err.println("Illegal number of arguments"); | |
return; | |
} | |
if(script!=null) | |
{ | |
StringReader r=new StringReader(script); | |
app.run(r); | |
r.close(); | |
} | |
else if(optind==args.length) | |
{ | |
app.run(new InputStreamReader(System.in)); | |
} | |
else | |
{ | |
while(optind< args.length) | |
{ | |
String inputName=args[optind++]; | |
FileReader in=new FileReader(inputName); | |
app.run(in); | |
in.close(); | |
} | |
} | |
} | |
catch (Exception err) | |
{ | |
err.printStackTrace(); | |
} | |
} | |
} |
>javac GimpClient.java
>java GimpClient input.scm
Success
>java GimpClient input.scm
Success
The result
That's it,
Pierre