Хочу поделиться с ХабраЛюдьми одной АйТишной историей, что произошла со мной в Новогодние праздники. Одним из моих новогодних подарков стала цифровая фоторамка от DICOM(вполне приличная, кстати, вещь). Содержит она в себе 128 МБ встроенной памяти и удобный интерфейс для заливки фоток — ака флэшка. Но вот ни задача — в домашнем архиве на компе фотки хранятся полноразмерные, а вот на флешке они ужимаются до малых размеров и показываются умиленному пользователю. Надо как то бороться с расточительством — сжимать каждую фотку ручками дело хлопотное!
Тут, хочу отметить что сам я виндой не особо пользуюсь — Линукс, как то привычней… И вот там бы взять imagemagick, да bash, да написать бы скрипт… Кстати, только сегодня был пост на хабре на эту тему. Да только вот ситуация в винде повергла меня в раздумья.
Конечно, наверняка есть специфический софт, но душа программиста требует системного подхода) Вобщем, мне стало интересно, как такие задачи можно решить в Винде. Юзать виндовый shell сразу отказался(не спрашивайте почему). Решил написать прожку на Java. Собственно это и было сделано — на вход подается папка, в ней рекурсивно ищутся все файлы с нужным расширением, для них высчитывается нужно ли их ужимать и собственно происходит масштабирование.
Привожу код(в Java я новичок, так что не ругайте, но конструктивная критика очень интересна):
Тут, хочу отметить что сам я виндой не особо пользуюсь — Линукс, как то привычней… И вот там бы взять imagemagick, да bash, да написать бы скрипт… Кстати, только сегодня был пост на хабре на эту тему. Да только вот ситуация в винде повергла меня в раздумья.
Конечно, наверняка есть специфический софт, но душа программиста требует системного подхода) Вобщем, мне стало интересно, как такие задачи можно решить в Винде. Юзать виндовый shell сразу отказался(не спрашивайте почему). Решил написать прожку на Java. Собственно это и было сделано — на вход подается папка, в ней рекурсивно ищутся все файлы с нужным расширением, для них высчитывается нужно ли их ужимать и собственно происходит масштабирование.
Привожу код(в Java я новичок, так что не ругайте, но конструктивная критика очень интересна):
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import javax.swing.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
public class ImageConverter {
static int MAX_WIDTH = 480;
static int MAX_HEIGHT = 360;
public static void main(String[] args) {
String indir = "";
if(args.length > 0){
indir = args[0];
}else{
System.out.println("Usage: imageconv path [maxwidth] [maxheight]");
return;
}
if(args.length > 2){
MAX_WIDTH = Integer.parseInt(args[1]);
MAX_HEIGHT = Integer.parseInt(args[2]);
}
System.out.println("Input directory: " + indir);
LinkedList<File> files = getTree(new File(indir));
if(files.size() == 0){
JOptionPane.showMessageDialog(null, "Nothing to process",
"Image Convert Error",JOptionPane.ERROR_MESSAGE);
return;
}
int startSize = 0, endSize = 0;
int res = JOptionPane.showConfirmDialog(null, "Will process " + files.size() + " files on drive " + indir,
"Image Convert",JOptionPane.OK_CANCEL_OPTION);
if(res == JOptionPane.CANCEL_OPTION) return;
for(File original: files){
startSize += original.length();
System.out.print("Will process " + original.getName() + "...");
try{
if(resize(original, original)){
System.out.println("Done!");
}else{
System.out.println("No conversion.");
}
}catch(Exception e){
System.out.println(" Error: " + e.getMessage());
}
}
for(File result: files){
endSize += result.length();
}
System.out.println("Result is: start size " + startSize + ", end size is "
+ endSize);
System.out.println("Comperession is " + (100.0*(startSize - endSize) / startSize) + "%.");
return;
}
public static LinkedList<File> getTree(File dir){
LinkedList<File> result = new LinkedList<File>();
if(dir.isFile()){
String fname = dir.getName();
String extension = fname;
if(fname.length()>3)
extension = fname.substring(fname.length() - 3).toLowerCase();
if("jpg".equals(extension)){
result.add(dir);
}
return result;
}
File[] children = dir.listFiles();
if(children == null) return result;
for(File s: children){
result.addAll(getTree(s));
}
return result;
}
public static boolean resize(File originalFile, File resizedFile) throws IOException {
ImageIcon ii = new ImageIcon(originalFile.getCanonicalPath());
Image i = ii.getImage();
Image resizedImage = null;
int newWidth = i.getWidth(null);
int newHeight = i.getHeight(null);
double aspectW = 1.0 * newWidth / ImageConverter.MAX_WIDTH;
double aspectH = 1.0 * newHeight / ImageConverter.MAX_HEIGHT;
System.out.println("AspectW: " + aspectW + "; AspectH: " + aspectH);
if(aspectW > 1.0 || aspectH > 1.0){
if(aspectW >= aspectH){ // resize by width
newHeight = new Double(newHeight / aspectW).intValue();
newWidth = ImageConverter.MAX_WIDTH;
}else{//resize by height
newWidth = new Double(newWidth / aspectH).intValue();
newHeight = ImageConverter.MAX_HEIGHT;
}
resizedImage = i.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
Image temp = new ImageIcon(resizedImage).getImage();
BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null), temp.getHeight(null),
BufferedImage.TYPE_INT_RGB);
Graphics g = bufferedImage.createGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null));
g.drawImage(temp, 0, 0, null);
g.dispose();
FileOutputStream out = new FileOutputStream(resizedFile);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufferedImage);
param.setQuality(1.0f, true);
encoder.setJPEGEncodeParam(param);
encoder.encode(bufferedImage);
return true;
}else{///nothing to do
return false;
}
}
}
* This source code was highlighted with Source Code Highlighter.
Но как эту прогу запускать? Писать пользоветльский интерфейс для такой задачи было бы опять же расточительно. ПодумавПогуглив решил встроить эту прогу в контекстное меню для устройств. Однако хочется еще видеть отладочную печать(не столько для отладки, а сколько для понимания что процесс движется). Решил сделать так — cmd-файл, как обертка для проги(все таки заюзал виндовый shell). Итак, делаем из класса jar файл, кладем его в C:/Program Files/imgconv/imgconv.jar, делаем cmd файл ConvertImages.cmd:
java -jar "C:\Program Files\imgconv\imgconv.jar" %1
pause
(Естественно исполняемый файл java должен быть доступен через переменную PATH)
Теперь осталось добавить элемент меню. Делаем так:
- Открываем реестр в HKEY_CLASSES_ROOT\Drive\shell\
- Создаем раздел Image Converter(Это и будет именем элемента меню)
- В нем создаем раздел command
- Устанавливаем в нем значение по умолчанию C:\Program Files\imgconv\ConvertImages.cmd %1
- Проверяем
Получилось очень даже удобно — запускаем, проверяем то ли мы хотим ресайзить, жмем ок и медитируем на процесс.
P.S.Данный опус не является советом, руководством или чем-либо еще в том же духе. Просто рассказ о том как имея свободное время я пытался придумать нестандартное решение стандартной проблемы)
P.P.S. Всех с Новым Годом!