Un
problema molto comune ai programmatori Java consiste nel salvare un oggetto
Image (o ImageProducer) in un formato di interscambio per altre applicazioni.
In
questo articolo vedremo come è semplice effettuare questa operazione
utilizzando le classi messe a disposizione dal package JPM di ACME (reperibile
al sito http://www.acme.com/java).
Il package
ACME
Il package
ACME viene distribuito con i sorgenti commentati in formato Javadoc e comprende
numerose classi:
Package
Acme.Crypto: implementa i principali algoritmi di crittografia
Package
Acme.JPM
Acme.JPM.Decoders:
istanzia un oggetto Image a partire da un file in formato GIF o JPG.
Acme.JPM.Encoders:
salva un oggeto Image in formato GIF o JPG.
Acme.JPM.Filter:
effettua operazioni di filtro su oggetti di tipo Image o ImageProducer
(smoothing, flip, gamma correction, ecc…).
Package
Acme.Nnrpd: realizza un demone NNRP multi-threaded
Acme.Serve:
insieme di classi utili per realizzare CGI in tecnologia servlet
Acme.Widgets:
classi di interfaccia grafica che realizzano le principali dialog per la
comunicazione con gli utenti (OkDialog, YesNoBox, YesNoCancelBox, ecc…).
Nel presente
articolo ci limiteremo a vedere come funzionano le classi presenti nel
package Acme.JPM.Encoders. Considerazioni analoghe varranno anche per i
package Decoders e Filters.
Scrivere
un oggetto Image su file
Utilizzare
le classi ACME per scrivere un oggetto Image su file è molto semplice.
Le operazioni da eseguire sono le seguenti:
1
try{
2
DataOutputStream dos = new DataOutputStream(new FileOutputStream( new File("snapshot.gif")));
3
Acme.Jpm.encoders.ImageEncoder ie = new Acme.Jpm.encoders.GifEncoder(myImage,
dos );
4
ie.encode();
5
} catch (Exception ee) {
6
System.out.println(ee.toString());
7
}
Vale
un analogo discorso per i formati Jpeg e Ppm. Le classi che realizzano
la codifica, infatti, sono estensioni della classe astratta ImageEncoder
e come tali sono state specializzate in relazione al formato di codifica..
Sostituendo la riga 3 con le seguenti si ottiene rispettivamente la codifica
in formato Jpeg e Ppm.
Acme.Jpm.encoders.ImageEncoder
ie = new Acme.Jpm.encoders.JpegEncoder(myImage, dos );
Acme.Jpm.encoders.ImageEncoder
ie = new Acme.Jpm.encoders.PpmEncoder(myImage, dos );
Se
l'oggetto Image non è pronto subito?
Osservando
i costruttori delle classi ACME che realizzano la codifica si nota che
accettano in ingresso oggetti di tipo ImageProducer. Oggetti di questo
tipo sono molto utili nel caso in cui l'immagine non è subito pronta
per essere salvata su file (ad esempio potrebbe essere in fase di scaricamento
dalla Rete). In questo caso cercando di codificare un oggetto Image (quando
ancora non è "pronto" per essere codificato) si otterrebbe un file
grafico distorto (l'immagine non sarebbe quella voluta). E' necessario
che l'encoder abbia a disposizione un sistema per capire quando l'immagine
è pronta per essere salvata su file. Questo meccanismo può
essere realizzato in Java attraverso oggetti di tipo ImageProducer.
ImageProducer
prod = myObject.getProducer();
Acme.JPM.Encoders.ImageEncoder
ie = new Acme.JPM.Encoders.GifEncoder( prod, out );
ie.encode();
Un esempio
Nel seguente
esempio viene mostrato come può essere utilizzato l'encoder ACME
per salvare un'immagine scaricata dalla rete utilizzando un oggetto di
tipo ImageProducer.
//
ToGif - dump out an image URL as GIF
//
//
Given a URL as argument, it fetches the file and writes it onto stdout
//
in the GIF image file format.
//
//
Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
//
//
Redistribution and use in source and binary forms, with or without
//
modification, are permitted provided that the following conditions
//
are met:
//
1. Redistributions of source code must retain the above copyright
//
notice, this list of conditions and the following disclaimer.
//
2. Redistributions in binary form must reproduce the above copyright
//
notice, this list of conditions and the following disclaimer in the
//
documentation and/or other materials provided with the distribution.
//
//
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
//
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
//
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
//
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
//
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
//
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
//
SUCH DAMAGE.
//
//
Visit the ACME Labs Java page for up-to-date versions of this and other
//
fine Java utilities: http://www.acme.com/java/
import
java.net.*;
import
java.io.*;
import
java.util.*;
import
java.awt.*;
import
java.awt.image.*;
public
class ToGif extends Acme.Application{
static final String progName = "ToGif";
// Old-style main() routine. Calls compatibility routine for newMain().
public static void main( String[] args ){
(new ToGif()).compat( args );
}
public int newMain( String[] args ){
int argc = args.length;
if ( argc != 1 ){
usage();
return -1;
}
dump( args[0] );
return 0;
}
private void usage(){
err.println( "usage: " + progName + " URL" );
}
//
Got to make one of these even if we don't use it, cause it loads
//
in some necessary native methods.
private
Toolkit tk = new Acme.JPM.StubToolkit();
private
void dump( String urlStr ){
try{
URL url = new URL( urlStr );
URLConnection uc = url.openConnection();
uc.connect();
// Got to open a stream to get around Java NullPointerException bug.
InputStream f = uc.getInputStream();
String mimeType = uc.getContentType();
// Java prints (not throws!) a ClassNotFoundException if you try
// a getContent on text.html or audio/basic (or no doubt many
// other types).
if ( ! mimeType.startsWith( "image/" ) )
err.println( progName + ": " + urlStr + " is not an image" );
else{
Object content = uc.getContent();
if ( ! ( content instanceof ImageProducer ) )
err.println(progName + ": " + urlStr +" is not a known image type" );
else{
ImageProducer prod = (ImageProducer) content;
Acme.JPM.Encoders.ImageEncoder ie = new Acme.JPM.Encoders.GifEncoder( prod,
out );
ie.encode();
}
}
// Done with unnecessary stream.
f.close();
}
catch ( Exception e ){
err.println( progName + ": " + e );
}
}
}
|