View Javadoc

1   /**
2    * Copyright 2008 WebPhotos
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sf.webphotos.tools;
17  
18  import com.sun.image.codec.jpeg.JPEGCodec;
19  import com.sun.image.codec.jpeg.JPEGImageEncoder;
20  import java.awt.*;
21  import java.awt.image.BufferedImage;
22  import java.io.File;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.util.Iterator;
26  import javax.imageio.ImageIO;
27  import javax.imageio.ImageReader;
28  import javax.imageio.stream.ImageInputStream;
29  import javax.swing.ImageIcon;
30  import net.sf.webphotos.BancoImagem;
31  import net.sf.webphotos.util.Util;
32  import org.apache.commons.configuration.Configuration;
33  
34  /**
35   * Molda diferentes tamanhos de dimensão para as imagens. Controla os tamanhos
36   * máximos de cada thumb e redimensiona o tamanho das fotos originais baseado
37   * nesses valores máximos.
38   */
39  public final class Thumbnail {
40  
41      // tam máximo de cada thumb
42      private static int t1, t2, t3, t4;
43      // marca d´agua e texto aplicado ao thumbnail 4
44      private static String marcadagua, mdTeste;
45      private static String texto;
46      private static int mdPosicao, mdMargem, mdTransparencia;
47      private static String txFamilia;
48      private static int txTamanho, txPosicao, txMargem, txEstilo;
49      private static Color txCorFrente, txCorFundo;
50  
51      /**
52       * Busca no arquivo de configuração, classe
53       * {@link net.sf.webphotos.util.Config Config}, os tamnahos dos 4 thumbs e
54       * seta esses valores nas variáveis desta classe. Testa se o usuário setou
55       * valores de marca d'água e texto para o thumb4, caso afirmativo, busca os
56       * valores necessários no arquivo de configuração.
57       */
58      private static void inicializar() {
59  
60          // le as configurações do usuário
61          Configuration c = Util.getConfig();
62  
63          // tamanhos de thumbnails
64          t1 = c.getInt("thumbnail1");
65          t2 = c.getInt("thumbnail2");
66          t3 = c.getInt("thumbnail3");
67          t4 = c.getInt("thumbnail4");
68  
69          // usuario setou marca d'agua para thumbnail 4 ?
70          // TODO: melhorar teste para captação destes parametros
71          try {
72              marcadagua = c.getString("marcadagua");
73              mdPosicao = c.getInt("marcadagua.posicao");
74              mdMargem = c.getInt("marcadagua.margem");
75              mdTransparencia = c.getInt("marcadagua.transparencia");
76              mdTeste = c.getString("marcadagua.teste");
77          } catch (Exception ex) {
78              ex.printStackTrace(Util.err);
79          }
80  
81          // usuário setou texto para o thumbnail 4 ?
82          try {
83              texto = c.getString("texto");
84              txPosicao = c.getInt("texto.posicao");
85              txMargem = c.getInt("texto.margem");
86              txTamanho = c.getInt("texto.tamanho");
87              txEstilo = c.getInt("texto.estilo");
88              txFamilia = c.getString("texto.familia");
89  
90              String[] aux = c.getStringArray("texto.corFrente");
91              txCorFrente = new Color(Integer.parseInt(aux[0]), Integer.parseInt(aux[1]), Integer.parseInt(aux[2]));
92              aux = c.getStringArray("texto.corFundo");
93              txCorFundo = new Color(Integer.parseInt(aux[0]), Integer.parseInt(aux[1]), Integer.parseInt(aux[2]));
94          } catch (Exception ex) {
95              ex.printStackTrace(Util.err);
96          }
97  
98      }
99  
100     /**
101      * Cria thumbs para as imagens. Testa se já existem valores setados para o
102      * thumb, se não existir chama o método
103      * {@link net.sf.webphotos.Thumbnail#inicializar() inicializar} para setar
104      * seus valores. Abre o arquivo de imagem passado como parâmetro e checa se
105      * é uma foto válida. Obtém o tamanho original da imagem, checa se está no
106      * formato paisagem ou retrato e utiliza o método
107      * {@link java.awt.Image#getScaledInstance(int,int,int) getScaledInstance}
108      * para calcular os thumbs. Ao final, salva as imagens.
109      *
110      * @param caminhoCompletoImagem Caminho da imagem.
111      */
112     public static void makeThumbs(String caminhoCompletoImagem) {
113 
114         String diretorio, arquivo;
115         if (t1 == 0) {
116             inicializar();
117         }
118 
119         try {
120             File f = new File(caminhoCompletoImagem);
121             if (!f.isFile() || !f.canRead()) {
122                 Util.err.println("[Thumbnail.makeThumbs]/ERRO: Erro no caminho do arquivo " + caminhoCompletoImagem + " incorreto");
123                 return;
124             }
125 
126             // Foto em alta corrompida 
127             if (getFormatName(f) == null) {
128                 Util.err.println("[Thumbnail.makeThumbs]/ERRO: Foto Corrompida");
129                 return;
130             } else {
131                 Util.out.println("[Thumbnail.makeThumbs]/INFO: Foto Ok!");
132             }
133 
134             diretorio = f.getParent();
135             arquivo = f.getName();
136 
137             ImageIcon ii = new ImageIcon(f.getCanonicalPath());
138             Image i = ii.getImage();
139 
140             Image tumb1, tumb2, tumb3, tumb4;
141 
142             // obtém o tamanho da imagem original
143             int iWidth = i.getWidth(null);
144             int iHeight = i.getHeight(null);
145             //int w, h;
146 
147             if (iWidth > iHeight) {
148                 tumb1 = i.getScaledInstance(t1, (t1 * iHeight) / iWidth, Image.SCALE_SMOOTH);
149                 tumb2 = i.getScaledInstance(t2, (t2 * iHeight) / iWidth, Image.SCALE_SMOOTH);
150                 tumb3 = i.getScaledInstance(t3, (t3 * iHeight) / iWidth, Image.SCALE_SMOOTH);
151                 tumb4 = i.getScaledInstance(t4, (t4 * iHeight) / iWidth, Image.SCALE_SMOOTH);
152                 //w = t4;
153                 //h = (t4 * iHeight) / iWidth;
154             } else {
155                 tumb1 = i.getScaledInstance((t1 * iWidth) / iHeight, t1, Image.SCALE_SMOOTH);
156                 tumb2 = i.getScaledInstance((t2 * iWidth) / iHeight, t2, Image.SCALE_SMOOTH);
157                 tumb3 = i.getScaledInstance((t3 * iWidth) / iHeight, t3, Image.SCALE_SMOOTH);
158                 tumb4 = i.getScaledInstance((t4 * iWidth) / iHeight, t4, Image.SCALE_SMOOTH);
159                 //w = (t4 * iWidth) / iHeight;
160                 //h = t4;
161             }
162 
163             tumb4 = estampar(tumb4);
164 
165             Util.log("Salvando Imagens");
166 
167             save(tumb1, diretorio + File.separator + "_a" + arquivo);
168             save(tumb2, diretorio + File.separator + "_b" + arquivo);
169             save(tumb3, diretorio + File.separator + "_c" + arquivo);
170             save(tumb4, diretorio + File.separator + "_d" + arquivo);
171 
172         } catch (Exception e) {
173             Util.err.println("[Thumbnail.makeThumbs]/ERRO: Inesperado - " + e.getMessage());
174             e.printStackTrace(Util.err);
175         }
176     }
177 
178     private static Image estampar(Image im) {
179         try {
180             Image temp = new ImageIcon(im).getImage();
181 
182             BufferedImage buf = new BufferedImage(temp.getWidth(null),
183                     temp.getHeight(null),
184                     BufferedImage.TYPE_INT_RGB);
185 
186             Graphics2D g2 = (Graphics2D) buf.getGraphics();
187 
188             g2.drawImage(temp, 0, 0, null);
189             g2.setBackground(Color.BLUE);
190 
191             Dimension dimensaoFoto = new Dimension(im.getWidth(null), im.getHeight(null));
192 
193             // aplicar texto
194             if (texto != null) {
195                 Util.out.println("aplicando texto " + texto);
196 
197                 Font fonte = new Font(txFamilia, txEstilo, txTamanho);
198                 g2.setFont(fonte);
199                 FontMetrics fm = g2.getFontMetrics(fonte);
200                 Dimension dimensaoTexto = new Dimension(fm.stringWidth(texto), fm.getHeight());
201                 Point posTexto = calculaPosicao(dimensaoFoto, dimensaoTexto, txMargem, txPosicao);
202 
203                 g2.setPaint(txCorFundo);
204                 g2.drawString(texto, (int) posTexto.getX() + 1, (int) posTexto.getY() + 1 + fm.getHeight());
205                 g2.setPaint(txCorFrente);
206                 g2.drawString(texto, (int) posTexto.getX(), (int) posTexto.getY() + fm.getHeight());
207             }
208 
209             // aplicar marca d´agua
210             if (marcadagua != null) {
211                 Image marca = new ImageIcon(marcadagua).getImage();
212                 int rule = AlphaComposite.SRC_OVER;
213                 float alpha = (float) mdTransparencia / 100;
214                 Point pos = calculaPosicao(dimensaoFoto,
215                         new Dimension(marca.getWidth(null), marca.getHeight(null)),
216                         mdMargem, mdPosicao);
217 
218                 g2.setComposite(AlphaComposite.getInstance(rule, alpha));
219                 g2.drawImage(marca, (int) pos.getX(), (int) pos.getY(), null);
220             }
221 
222             g2.dispose();
223             //return (Image) buf;
224             return Toolkit.getDefaultToolkit().createImage(buf.getSource());
225         } catch (Exception e) {
226             return im;
227         }
228     }
229 
230     private static boolean save(Image thumbnail, String nmArquivo) {
231         try {
232             // This code ensures that all the
233             // pixels in the image are loaded.
234             Image temp = new ImageIcon(thumbnail).getImage();
235 
236             // Create the buffered image.
237             BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null),
238                     temp.getHeight(null), BufferedImage.TYPE_INT_RGB);
239 
240             // Copy image to buffered image.
241             Graphics g = bufferedImage.createGraphics();
242 
243             // Clear background and paint the image.
244             g.setColor(Color.white);
245             g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null));
246             g.drawImage(temp, 0, 0, null);
247             g.dispose();
248 
249             // write the jpeg to a file
250             File file = new File(nmArquivo);
251             // Recria o arquivo se existir
252             if (file.exists()) {
253                 Util.out.println("Redefinindo a Imagem: " + nmArquivo);
254                 file.delete();
255                 file = new File(nmArquivo);
256             }
257             FileOutputStream out = new FileOutputStream(file);
258 
259             // encodes image as a JPEG data stream
260             JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
261             com.sun.image.codec.jpeg.JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufferedImage);
262 
263             // writeParam = new JPEGImageWriteParam(null);
264             // writeParam.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
265             //writeParam.setProgressiveMode(JPEGImageWriteParam.MODE_DEFAULT);
266             param.setQuality(1.0f, true);
267             encoder.setJPEGEncodeParam(param);
268             encoder.encode(bufferedImage);
269             return true;
270         } catch (IOException ioex) {
271             ioex.printStackTrace(Util.err);
272             return false;
273         }
274     }
275 
276     private static Point calculaPosicao(Dimension dimensaoExt,
277             Dimension dimensaoInt, int margem, int posicao) {
278         int x = 0, y = 0;
279         // Posição da marca d'agua
280         // 1---2---3 y1
281         // 4---5---6 y2
282         // 7---8---9 y3
283         // x1  x2  x3
284         int x1 = margem;
285         int x2 = (int) ((float) (dimensaoExt.width - dimensaoInt.width) / 2);
286         int x3 = dimensaoExt.width - dimensaoInt.width - margem;
287 
288         int y1 = margem;
289         int y2 = (int) ((float) (dimensaoExt.height - dimensaoInt.height) / 2);
290         int y3 = dimensaoExt.height - dimensaoInt.height - margem;
291 
292         if (posicao == 1) {
293             x = x1;
294             y = y1;
295         } else if (posicao == 2) {
296             x = x2;
297             y = y1;
298         } else if (posicao == 3) {
299             x = x3;
300             y = y1;
301         } else if (posicao == 4) {
302             x = x1;
303             y = y2;
304         } else if (posicao == 5) {
305             x = x2;
306             y = y2;
307         } else if (posicao == 6) {
308             x = x3;
309             y = y2;
310         } else if (posicao == 7) {
311             x = x1;
312             y = y3;
313         } else if (posicao == 8) {
314             x = x2;
315             y = y3;
316         } else if (posicao == 9) {
317             x = x3;
318             y = y3;
319         }
320 
321         return new Point(x, y);
322     }
323 
324     /**
325      * Returns the format of the image in the file 'f'. Returns null if the
326      * format is not known.
327      *
328      * @param f An java.io.File
329      * @return An String containing the type of Image or NULL
330      */
331     private static String getFormatInFile(File f) {
332         return getFormatName(f);
333     }
334 
335     // Returns the format of the image in the input stream 'is'.
336     // Returns null if the format is not known.
337     private static String getFormatFromStream(java.io.InputStream is) {
338         return getFormatName(is);
339     }
340 
341     // Returns the format name of the image in the object 'o'.
342     // 'o' can be either a File or InputStream object.
343     // Returns null if the format is not known.
344     private static String getFormatName(Object o) {
345         try {
346             // Create an image input stream on the image
347             ImageInputStream iis = ImageIO.createImageInputStream(o);
348 
349             // Find all image readers that recognize the image format
350             Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
351             if (!iter.hasNext()) {
352                 // No readers found
353                 return null;
354             }
355 
356             // Use the first reader
357             ImageReader reader = iter.next();
358 
359             // Close stream
360             iis.close();
361 
362             // Return the format name
363             return reader.getFormatName();
364         } catch (Exception e) {
365             // The image could not be read
366             return null;
367         }
368     }
369 
370     /**
371      * Faz um load no arquivo de configuração e chama o método
372      * {@link net.sf.webphotos.Thumbnail#makeThumbs(String) makeThumbs} para
373      * fazer thumbs de uma foto específica.
374      *
375      * @param args args do método main.
376      */
377     public static void main(String[] args) {
378         makeThumbs("c:/temp/167.jpg");
379         makeThumbs("d:/bancoImagem/81/312.jpg");
380         makeThumbs("d:/bancoImagem/81/313.jpg");
381         makeThumbs("d:/bancoImagem/81/314.jpg");
382         makeThumbs("d:/bancoImagem/81/315.jpg");
383         makeThumbs("D:/bancoImagem/460/2072.jpg");
384         executaLote();
385     }
386 
387     /**
388      * Abre uma conexão com o banco de dados através da classe BancoImagem,
389      * busca um lote de imagens e faz thumbs para todas as fotos. Não possui
390      * utilizações.
391      */
392     public static void executaLote() {
393         net.sf.webphotos.BancoImagem db = net.sf.webphotos.BancoImagem.getBancoImagem();
394 
395         try {
396             db.configure("jdbc:mysql://localhost/test", "com.mysql.jdbc.Driver");
397             BancoImagem.login();
398             java.sql.Connection conn = BancoImagem.getConnection();
399             java.sql.Statement st = conn.createStatement();
400             java.sql.ResultSet rs = st.executeQuery("select * from fotos");
401 
402             int albumID, fotoID;
403             String caminho;
404 
405             while (rs.next()) {
406                 albumID = rs.getInt("albumID");
407                 fotoID = rs.getInt("fotoID");
408                 caminho = "d:/bancoImagem/" + albumID + "/" + fotoID + ".jpg";
409                 makeThumbs(caminho);
410                 Util.out.println(caminho);
411             }
412 
413             rs.close();
414             st.close();
415             conn.close();
416 
417         } catch (Exception e) {
418             e.printStackTrace(Util.err);
419         }
420     }
421 }