Aumentare la risoluzione e ridurre le dimensioni di un'immagine in Java


Quando l'ho chiesto per la prima volta, ho incluso quante più informazioni possibili, dal momento che non so mai cosa aiuterà qualcuno se può dare a m una soluzione, ma dalle risposte, sembra che non abbia chiarito il mio punto.

Lascio il testo originale in basso e accorcio questo. Spero che questo sia chiaro.

Sto lavorando con immagini restituite a me da un altro programma. Posso ottenere un'immagine che è, ad esempio, 8x10 a 72 DPI o la stessa immagine a 16x20, anche a 72 DPI.

Sto lavorando in Java. Quello che mi piacerebbe fare è prendere l'immagine 16x20 e ridimensionarla. Se possibile, mi piacerebbe cambiare il file in modo che invece di essere 16x20 a 72 DPI, sia 8x10 a 144 DPI.

So che è ancora lo stesso numero di pixel, ma gli spettatori diranno quanto è grande un'immagine e qual è il DPI e anche alcuni aprono un'immagine alla sua dimensione completa, quindi preferirei che trattassero il 16x20 come un'immagine più piccola con una risoluzione più alta.

Posso farlo in Java? Perderò qualche dato? Come potrei farlo - posso semplicemente cambiare i metadati nel file png o jpg?

-----(domanda originale qui sotto)-----

Ho visto alcune domande che si avvicinano a questo, ma questo è un po ' diverso.

So che puoi diminuire la risoluzione dell'immagine con un'immagine in Java (anche qui ). Tutte le ricerche che ho fatto si sono preoccupate di ridurre la risoluzione di un'immagine.

Ho il problema opposto. Sto lavorando con un'immagine che sto tornando in 72DPI. Il vantaggio è che posso aumentare la dimensione dell'immagine, così ho potuto fare la dimensione 100%, 200%, 400% e così via. Tutte le immagini sono a 72DPI, quindi se uso il 200% per lo zoom, quindi apro l'immagine in un visualizzatore e le faccio le stesse dimensioni dell'immagine al 100%, vedo una risoluzione migliore.

Per chiarezza - Sto ricevendo un'immagine da qualcun altro, potrebbe essere generata da un PDF o un'immagine, ma sono dato l'immagine da un altro programma. Non importa quello che ho fai, questa immagine è a 72DPI. Non posso cambiarlo, ma posso specificare la dimensione a 200% e torna ancora a 72DPI, solo due volte più grande e con più dettagli.

Non sono un esperto di grafica e questa è la prima volta che faccio una programmazione che utilizza la grafica. L'output potrebbe essere jpg o png, quindi il formato non è così importante. (Probabilmente potrei anche usare altri formati se necessario.)

Diciamo che l'immagine originale è una foto - 8" x 10" e a 72 DPI. Se chiedo uno zoom del 200%, io ottieni un'immagine 16" x 20 " a 72 DPI.

Posso, all'interno di Java, modificare l'immagine da 16" x 20" 72 DPI più grande in un'immagine da 144 DPI che è 8" x 10" senza perdere dati? In altre parole, raddoppia il DPI, ma taglia la dimensione a metà?

E, soprattutto, posso farlo senza perdere la risoluzione? (Penserei che si possa fare.)

Author: Community, 2012-12-20

2 answers

No, se prendi un'immagine 8x10 72dpi e chiedi uno zoom del 200% otterrai un 16x20 a 36 dpi. Non è possibile aumentare magicamente la risoluzione dell'immagine.

Ciò che conta è il numero totale di pixel nell'immagine. Il DPI dichiarato è proprio quello che il DPI sarà in una dimensione specifica. Prendi la tua immagine 8x10 a 72dpi. Ha 576x720 pixel. Se ingrandisci al 200% hai ancora lo stesso numero di pixel, ma ora saranno distribuiti su due volte le dimensioni lineari, il che significa che i singoli pixel saranno più grande. Alcuni software tenteranno di aumentare la risoluzione interpolando i pixel, cioè creando nuovi pixel facendo la media dei vicini più vicini. Questo può dare l'impressione di una risoluzione più alta, ma l'immagine non contiene più dati. Ha sempre l'effetto di ammorbidire l'immagine, in particolare eventuali spigoli vivi o linee.

Se riduci la dimensione di un'immagine senza ricampionare, aumenti la risoluzione stampata o visualizzata, ma l'immagine diventa più piccola. Per la stessa immagine, aumentando il DPI a 144 ridurrà la dimensione dell'immagine a 4x5.

 4
Author: Jim Garrison, 2012-12-20 18:04:45

Questo è complicato perché, come così tanto in Java, non puoi semplicemente accedere a qualcosa in modo semplice. Java non tiene traccia dei DPI, ma utilizza punti per millimetro. Inoltre, un'altra parte che è confusa è che non è possibile modificare questo tipo di informazioni in un'immagine o in un BufferedImage. È possibile modificare queste informazioni solo quando si sta scrivendo un BufferedImage tramite un ImageWriter.

Sono stato in grado di farlo. Come ho detto, potrei specificare lo zoom sull'immagine che era ritornato da me. Non importa quale livello di zoom, l'uscita era 72 DPI. Il mio obiettivo era 300DPI. Ho specificato un livello di zoom del 400%. Quindi, su un'immagine larga 8 "di 72 DPI, che mi ha restituito un'immagine da 32" di 72 DPI. Tutto quello che dovevo fare era specificare un DPI di 288 (72 x 4) per sovrascrivere il 72 DPI predefinito con cui avevo a che fare e poi quando è stato scritto, l'immagine aveva lo stesso numero di pixel, ma era considerata fatta a 288 DPI piuttosto che a 72 DPI.

Ecco un frammento di codice:

//Assunto c'è già un ImageWriter iw

ImageWriteParam writeParam = writer.getDefaultWriteParam();
ImageTypeSpecifier typeSpecifier =
       ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) {
    continue;
}

// Imposta parametri e informazioni

int DPI = 72 * scaling/100;
double dotsPerMilli = 1.0 * DPI / 10 / 2.54;
double checkDots = 1.0 * 144 / 10 / 2.54;
System.out.println("Dots per inch: " + DPI + ", DotsPerMilli: " + dotsPerMilli + ",
    CheckDots = " + checkDots);
IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
horiz.setAttribute("value", Double.toString(dotsPerMilli));
IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
vert.setAttribute("value", Double.toString(dotsPerMilli));
IIOMetadataNode dim = new IIOMetadataNode("Dimension");
dim.appendChild(horiz);
dim.appendChild(vert);
root.appendChild(dim);
metadata.mergeTree("javax_imageio_1.0", root);

/ / Da qui, basta scrivere il file usando un ImageOutputStream

final ImageOutputStream stream = ImageIO.createImageOutputStream(outFile);
System.out.println("Output file: " + outFile);
try {
    writer.setOutput(ImageIO.createImageOutputStream(outFile));
    writer.write(metadata, new IIOImage(image_to_save, null, metadata),
    writeParam);
} catch (Exception e) {
    System.out.println("Caught exception " + e + " when trying to write out
        file.");
    System.exit(0);
} finally {
    stream.close();
}
 1
Author: Tango, 2012-12-27 07:11:33