📜 ⬆️ ⬇️

Compression of images for the desired size in Windows

I want to share with HabraLudi one IT history that happened to me during the New Year holidays. One of my New Year's gifts was a digital photo frame from DICOM (quite a decent thing, by the way). It contains 128 MB of internal memory and a convenient interface for uploading photos - aka flash drive. But no problem - in the home archive on a computer, the pictures are stored full-sized, but on a flash drive they are squeezed to small sizes and shown to the affectionate user. It is necessary to deal with waste as it is - to compress each photo with handles is troublesome!

Here, I want to note that I myself do not really use Windows - Linux, as it is more familiar ... And there I would take imagemagick, yes bash, but write a script ... By the way, only today there was a post on this topic . But only here the situation in the Windows plunged me into thought.

Of course, there is certainly a specific software, but the soul of a programmer requires a systematic approach) In general, I wondered how such problems can be solved in Windows. Windows shell refused immediately (do not ask why). I decided to write in Java. Actually, this was done - a folder is fed to the input, all files with the necessary extension are searched recursively in it, whether they are deducted to be compressed and scaled.
I cite the code (I'm new to Java, so do not scold, but constructive criticism is very interesting):
')
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 .
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 .
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 .


But how to run this program? Writing a user interface for such a task would again be wasteful. Having thought Googling decided to build this program into the context menu for devices. However, I still want to see the debug print (not so much for debugging, but for understanding that the process is moving). I decided to do so - cmd-file, as a wrapper for the program (all the same, I got the Windows shell). So, we make a file from the jar class, put it in C: / Program Files / imgconv / imgconv.jar, do cmd file ConvertImages.cmd:
java -jar "C:\Program Files\imgconv\imgconv.jar" %1
pause

(Naturally, the java executable must be accessible through the PATH variable)
Now it remains to add a menu item. We do this:

It turned out very conveniently - we start, check whether we want to resize, click OK and meditate on the process.
PS This opus is not a piece of advice, guidance or anything else. Just a story about how having free time I tried to come up with a non-standard solution to a standard problem)

PPS Happy New Year to all!

Source: https://habr.com/ru/post/48424/


All Articles