View Full Version : [java]ColorModel CMYK
Non vi do tregua...
Devo ottenere una conversione da rgb a cmyk e so che devo passare per questa operazione:
ICC_ColorSpace iccp = new ICC_ColorSpace(ICC_Profile.getInstance(ICC_Profile.icSigCmykData)); (o almeno credo :D )
reperita dal seguente sito:
http://java.sun.com/products/java-media/jai/forDevelopers/jaifaq.html
Ma non so come ottenere il ColorModel.
Arigrazie
(se avete altre soluzioni ripeto non esitate a postarle)
Io proverei con un java.awt.image.ComponentColorModel
ComponentColorModel(ColorSpace colorSpace, boolean hasAlpha, boolean isAlphaPremultiplied, int transparency, int transferType)
gli passi il tuo ICC_color space, gli altri parametri li ricavi dall'immagine da convertire (dovrebbe esserci un metodo in BufferedImage per ognuno) e poi via, alla bersagliera.
Dici che non può funzionare?
che mal di testa ragazzi :eek: ... evviva i tempi ristretti!!!!!!!
Mo vedo che riesco a tirarne fuori, grazie ancora, se trovo la soluzione posto anche quella (:
ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.TYPE_CMYK),bits, false, false, 1, DataBuffer.TYPE_BYTE);
ecco come dovrebbe essere fatto,
dico dovrebbe perchè il risultato è:
java.lang.IllegalArgumentException: Unknown color space
at java.awt.color.ColorSpace.getInstance(ColorSpace.java:329)
at Image.immagini.ris.main(ris.java:36)
Exception in thread "main"
mannaggia la miseriaccia!!!!!!!!
il problema è il ColoSpace.TYPE_CMYK perchè se lo setto a ColoSpace.CS_GRAY il risultato è una immagine a scala di grigio!
Non riesci a passargli il color space di prima?
ICC_ColorSpace iccp = new ICC_ColorSpace(ICC_Profile.getInstance(ICC_Profile.icSigCmykData));
In pratica dovresti (credo) usare un costruttore del JRE standard passandogli un "colorspace" di JAI...me so' spiegato bbene no? :D
MADOOOOONNA non ci posso credere, ho cambiato il codice in
ICC_ColorSpace iccp = new ICC_ColorSpace(ICC_Profile.getInstance(ICC_Profile.icSigCmykData));
ColorModel colorModel = new ComponentColorModel(iccp ,bits, true, false, 1, DataBuffer.TYPE_BYTE);
e pensa un pò?!?!?!?!?!?!?!?!?!?!
non funziona lo stesso... stesso errore :mad:
try {
BufferedInputStream inBuffer = new BufferedInputStream(
new FileInputStream("Z:\\Software Downloads\\JAICMM\\CMYK.pf"));
ICC_Profile cmykProfile = ICC_Profile.getInstance(inBuffer);
ICC_ColorSpace cmykColorSpace = new ICC_ColorSpace(cmykProfile);
} catch(IOException e) {
System.out.println(e);
}
Qui la costruzione dell'ICC_ColorSpace non sembra generare errori.
Ho usato il metodo getInstace(InputStream) passandogli come stream un flusso diretto ad uno dei profili ICC scaricati dal sito di Sun.
mi manderesti i profili?
oppure il link da dove scaricarli
Grazie
http://java.sun.com/products/java-media/jai/downloads/download-1_1_2.html
scorri la pagina verso il basso, c'è il pacchetto JAICMM
Grazie ancora, l'ho scaricato e implementato!
Ora non mi completa il file tiff UAAAAAAAAAAAAAAAAH.
Bella idea comunque. Grazie ancora per l'aiuto
Qui mi viene una cosa di questo tipo:
try {
BufferedInputStream inBuffer = new BufferedInputStream(
new FileInputStream("Z:\\Software Downloads\\JAICMM\\CMYK.pf"));
ICC_Profile cmykProfile = ICC_Profile.getInstance(inBuffer);
ICC_ColorSpace cmykColorSpace = new ICC_ColorSpace(cmykProfile);
BufferedImage image = ImageIO.read(new File("z:\\marmotta.jpg"));
ColorConvertOp cmykConversion = new ColorConvertOp(
image.getColorModel().getColorSpace(),
cmykColorSpace,
null);
BufferedImage convertedImage = cmykConversion.filter(image, null);
} catch(IOException e) {
System.out.println(e);
}
Senza usare JAI (i profili funzionano anche con il JRE standard, 1.4 o sup.) e senza ColorModel.
si ma io ho a che fare con delle tiff e non delle jpeg...
ora provo poi ti faccio sapere
public class ris{
public static void main(String args[]) throws IOException{
final int XRES_TAG = 282;
final int YRES_TAG = 283;
int[] resolution = { 304, 1};
String input = "C:/a/01.tif";
String output = "C:/a/nuovo.tiff";
FileSeekableStream stream = new FileSeekableStream(input);
//RenderedImage image1 =(RenderedImage) JAI.create("stream",stream);
RenderedOp image3 = JAI.create("stream",stream);
image3.getAsBufferedImage();
TIFFField xRes = new TIFFField(XRES_TAG, TIFFField.TIFF_SRATIONAL, 1, new int[][] { resolution });
TIFFField yRes = new TIFFField(YRES_TAG, TIFFField.TIFF_SRATIONAL, 1, new int[][] { resolution });
TIFFEncodeParam tep = new TIFFEncodeParam();
tep.setExtraFields(new TIFFField[] { xRes, yRes});
OutputStream out = new SeekableOutputStream(new RandomAccessFile(output,"rw"));
tep.setCompression(TIFFEncodeParam.COMPRESSION_NONE);
//ICC_ColorSpace iccp = new ICC_ColorSpace(ICC_Profile.getInstance(ICC_Profile.icSigCmyData));
BufferedInputStream inBuffer = new BufferedInputStream(new FileInputStream("C:/profili/CMYK.pf"));
ICC_Profile cmykProfile = ICC_Profile.getInstance(inBuffer);
ICC_ColorSpace cmykColorSpace = new ICC_ColorSpace(cmykProfile);
ColorConvertOp cmykConversion = new ColorConvertOp(image3.getColorModel().getColorSpace(),cmykColorSpace, null);
BufferedImage convertedImage = cmykConversion.filter(image3.getAsBufferedImage(), null);
ImageEncoder encoder = ImageCodec.createImageEncoder("TIFF",out, tep);
encoder.encode((RenderedImage)convertedImage);
out.close();
}
}
Questo è quanto. La conversione è effettuata e anche se photoshop dice che è in cmyk io dico di no.
Questo perchè l'immagine che viene fuori e molto più scura dell'originale e se si va con il contagocce a vedere la gamma dei colori, cambiano soltanto i valori di c m e y ma mai di k! (anche sul nero).
Andando per tentativi proverei allora a far creare all'engine Java un Buffer compatibile prima di copiargli sopra i dati convertiti.
BufferedInputStream inBuffer = new BufferedInputStream(
new FileInputStream("Z:\\Software Downloads\\JAICMM\\CMYK.pf"));
ICC_Profile cmykProfile = ICC_Profile.getInstance(inBuffer);
ICC_ColorSpace cmykColorSpace = new ICC_ColorSpace(cmykProfile);
BufferedImage image = ImageIO.read(new File("z:\\marmotta.jpg"));
ColorConvertOp cmykConversion = new ColorConvertOp(
image.getColorModel().getColorSpace(),
cmykColorSpace,
null);
ComponentColorModel colorModel = new ComponentColorModel(
cmykColorSpace,
false,
image.isAlphaPremultiplied(),
image.getTransparency(),
image.getRaster().getDataBuffer().getDataType());
BufferedImage convertedImage = cmykConversion.createCompatibleDestImage(image, colorModel);
cmykConversion.filter(image, convertedImage);
Ok... provo domani che oggi sono finito!!!
Grazie.. poi ti faccio sapere :cool:
Purtroppo il risultato è lo stesso. Avevo già provato ma dall'alto della mia ignoranza ero sicuro di aver toppato qualcosa!
Comunque a me da errore con il metodo getTransparency()... dove lo hai trovato?
BufferedInputStream inBuffer = new BufferedInputStream(new FileInputStream("C:/profile/CMYK.pf"));
ICC_Profile cmykProfile = ICC_Profile.getInstance(inBuffer);
ICC_ColorSpace cmykColorSpace = new ICC_ColorSpace(cmykProfile);
ColorConvertOp cmykConversion = new ColorConvertOp(image3.getColorModel().getColorSpace(),cmykColorSpace, null);
ComponentColorModel colorModel = new ComponentColorModel(cmykColorSpace,true,image3.getAsBufferedImage().isAlphaPremultiplied(),1,image3.getAsBufferedImage().getRaster().getDataBuffer().getDataType());
BufferedImage comp = cmykConversion.createCompatibleDestImage(image3.getAsBufferedImage(), colorModel);
BufferedImage convertedImage = cmykConversion.filter(image3.getAsBufferedImage(), comp);
ImageEncoder encoder = ImageCodec.createImageEncoder("TIFF",out, tep);
encoder.encode((RenderedImage)convertedImage);
out.close();
riskio di gettare la spugna...
comunque grazie PGI sei stato un grande (:
Calma e gesso.
Allora, c'è una svista (colpa mia) proprio su quel getTransparency() che è disponibile solo su Java 1.5.
getTransparency() restituisce un intero che può avere il valore
Transparency.OPAQUE, se l'immagine non ha un canale Alpha (es. BMP)
Transparency.BITMASK se l'immagine ha 1 bit di trasparenza (es. GIF)
Transparency.TRANSLUCENT se l'immagine ha più di 1 bit di trasparenza (es. PNG)
Prima dell'1.5 c'è lo stesso metodo per il ColorModel:
bufferedImage.getColorModel().getTransparency().
La calma c'è... il gesso me lo sono sniffato!
Ho provato a fare la conversione di una semplice jpg:
BufferedInputStream inBuffer = new BufferedInputStream(
new FileInputStream("C:/profili/CMYK.pf"));
ICC_Profile cmykProfile = ICC_Profile.getInstance(inBuffer);
ICC_ColorSpace cmykColorSpace = new ICC_ColorSpace(cmykProfile);
BufferedImage image = ImageIO.read(new File("C:/a/01.jpg"));
ColorConvertOp cmykConversion = new ColorConvertOp(
image.getColorModel().getColorSpace(),
cmykColorSpace,
null);
BufferedImage convertedImage = cmykConversion.filter(image, null);
File f = new File("C:/a/nuovo.jpg");
ImageIO.write(convertedImage, "JPEG", f);
E l'immagine creata non esiste!!! Ditemelo che devo sbattere la capoccia su uno spigolo!
Più che non esistere non viene visualizzata.
Il problema sta nell'operazione di conversione!
Se voglio salvare l'immagine così come l'ho aperta posso farlo, quella convertita invece la salva ma con qualche errore interno che non la fa visualizzare.
Ecco un nuovo modo di convertire i colori ma che generano un errore:
The specified ColorModel is incompatible with the image SampleModel
Il modo è:
public class Converting_1{
public static void main (String args[]) throws IOException {
BufferedInputStream inBuffer = new BufferedInputStream(
new FileInputStream("C:/profili/CMYK.pf"));
ICC_Profile cmykProfile = ICC_Profile.getInstance(inBuffer);
ColorSpace cmykColorSpace = new ICC_ColorSpace(cmykProfile);
RenderedOp image = JAI.create("fileload", "C:/a/01.jpg");
ParameterBlock pb = new ParameterBlock();
ColorModel colorModel = new ComponentColorModel(cmykColorSpace,
true,
image.getAsBufferedImage().isAlphaPremultiplied(),
image.getColorModel().getTransparency(),
image.getAsBufferedImage().getRaster().getDataBuffer().getDataType());
pb.addSource(image).add(colorModel);
RenderedOp dst = JAI.create("ColorConvert", pb);
JAI.create("filestore", dst, "C:/a/001.jpg", "JPEG", null);
}
}
Dovrebbe funzionare però!!!
Boh magari a qualcuno è utile (:
Alla fine ho provato la conversione di un jpg in rgb in un tiff cmyk.
L'immagine viene più scura, però (stando a "The Gimp") i valori "nero" non sono tutti uguali.
quel jai.create è deprecato.
rilancio con un esempio ai posteri.
try {
BufferedInputStream inBuffer = new BufferedInputStream(
new FileInputStream("Z:\\Software Downloads\\JAICMM\\CMYK.pf"));
ICC_Profile cmykProfile = ICC_Profile.getInstance(inBuffer);
ICC_ColorSpace cmykColorSpace = new ICC_ColorSpace(cmykProfile);
BufferedImage image = ImageIO.read(new File("z:\\marmotta.jpg"));
ColorConvertOp cmykConversion = new ColorConvertOp(
image.getColorModel().getColorSpace(),
cmykColorSpace,
null);
ComponentColorModel colorModel = new ComponentColorModel(
cmykColorSpace,
false,
image.isAlphaPremultiplied(),
image.getTransparency(),
image.getRaster().getDataBuffer().getDataType());
BufferedImage convertedImage = cmykConversion.createCompatibleDestImage(image, colorModel);
cmykConversion.filter(image, convertedImage);
FileStoreDescriptor.create(
convertedImage,
"z:\\immagine.tiff",
"tiff",
null,
null,
null);
} catch(IOException e) {
System.out.println(e);
}
Ok... allora posso abbassare la testa.
Il problema è che il nero, con questa conversione, viene perso per strada.
Mi è stato detto di implementare l'inverso di uno di questi algoritmi:
/* Adobe PhotoShop algorithm */
cyan = Math.min(255, cyan + black);
magenta = Math.min(255, magenta + black);
yellow = Math.min(255, yellow + black);
rgb[0] = 255 - cyan;
rgb[1] = 255 - magenta;
rgb[2] = 255 - yellow;
/* GNU Ghostscript algorithm */
int colors = 255 - black;
rgb[0] = colors * (255 - cyan)/255;
rgb[1] = colors * (255 - magenta)/255;
rgb[2] = colors * (255 - yellow)/255;
Sembrerebbe una kakkiata ma io non ho la più pallida idea di come fare
:huh:
In via del tutto teorica (bello concreto come al solito eh? :D ), una volta ottenuto un Buffer cmyk con il "creare compatible dest" potresi "pigliare" il suo Raster ed impostare i valori c,m,y e k dei pixel.
In via pratica, la mia marmotta "pixel-per-pixel" mi viene grigio chiaro chiaro.
try {
BufferedInputStream inBuffer = new BufferedInputStream(
new FileInputStream("Z:\\Software Downloads\\JAICMM\\CMYK.pf"));
ICC_Profile cmykProfile = ICC_Profile.getInstance(inBuffer);
ICC_ColorSpace cmykColorSpace = new ICC_ColorSpace(cmykProfile);
final BufferedImage image = ImageIO.read(new File("z:\\marmotta.jpg"));
final ColorConvertOp cmykConversion = new ColorConvertOp(
image.getColorModel().getColorSpace(),
cmykColorSpace,
null);
ComponentColorModel colorModel = new ComponentColorModel(
cmykColorSpace,
false,
image.isAlphaPremultiplied(),
image.getTransparency(),
image.getRaster().getDataBuffer().getDataType());
convertedImage = cmykConversion.createCompatibleDestImage(image, colorModel);
WritableRaster raster = convertedImage.getRaster();
for(int i = 0; i < convertedImage.getWidth(); i++) {
for(int j = 0; j < convertedImage.getHeight(); j++) {
int rgb = image.getRGB(i, j);
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = rgb & 0xff;
/* conversione semplice rgb cmyk
K=255-(max(R,G,B));
C=((255-R)-K)/(255-K);
M=((255-G)-K)/(255-K);
Y=((255-B)-K)/(255-K);*/
int k = r > g ? r : g;
k = k > b ? k : b;
k = 255 - k;
int div = 255 - k;
int c = div != 0 ? ((255 -r)-k) / div : 0;
int m = div != 0 ? ((255-g)-k) / div : 0;
int y = div != 0 ? ((255-b)-k) / div : 0;
raster.setPixel(i, j, new int[] {c,m,y,k});
}
}
convertedImage.setData(raster);
Spero che sia perchè ho trovato la formula sbagliata della conversione. Comunque stò raschiando il fondo del barile
Giuro che se non dovessi sfondare come programmatore il tuo avvenire è proiettato verso la comicità!!!
La marmotta pixel per pixel è stata l'apoteosi.
Ancora rido!
Grazie mille ancora
Domanda:
Ma ci deve mettere molto?
Ti diro, se cerco di visualizzare l'immagine cmyk in un'etichetta, attraverso un ImageIcon, ci mette 6000 anni, se devo salvarla e basta lo fa in un paio di secondi.
Il ciclo sui pixel invece è piuttosto rapido
Al posto del tuo algoritmo ho utilizzato questo:
int k = r > g ? r : g;
k = k > b ? k : b;
k = (255-k);
int c = r != 0 ? ((255-r)-k) : 255;
int m = g != 0 ? ((255-g)-k) : 255;
int y = b != 0 ? ((255-b)-k) : 255;
e magicamente la marmotta prende colore (:
Ora il problema riguarda solo l'algoritmo di conversione.
Infatti con questo viene fuori un'immagine più che buona ma sempre un pò sbiadita!
Purtroppo non me lo poso permettere. Conosci/ete un sito dove reperire altri algoritmi di conversione (o algoritmi veri e propri)?
Mi ci sono molto ( e sottolineo molto) avvicinato con questo:
int k = r < g ? r : g;
k = k < b ? k : b;
int div = (255-k);
int c = div!=0 ? (255 - (255*r)/div) : 0;
c = c < 0 ? 0 : c;
int m = div!=0 ? (255 - (255*g)/div) : 0;
m = m < 0 ? 0 : m;
int y = div!=0 ? (255 - (255*b)/div) : 0;
y = y < 0 ? 0 : y;
k = r > g ? r : g;
k = k > b ? k : b;
k = 255-k;
Però il bianco è troppo lucente!
(sono fiero perchè l'ho scritto io :D )
Prova a vedere se qui si capisce qualcosa
http://research.microsoft.com/~hollasch/cgindex/color/cmyk.html
Dovrebbe essere una spiegazione sul formato cmyk
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.