Compress pictures to the right size in Windows

    I want to share with HabraPeople one IT quiet story that happened to me on New Year's 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 a flash drive. But this is not a task - in the home archive on a computer the photos are stored full-sized, but on the USB flash drive they are compressed to a small size and shown to a touched user. We must somehow deal with wastefulness - squeezing every photo with pens is a troublesome thing!

    Here, I want to note that I don’t really use Windows myself - Linux, as it’s more familiar ... And there I would take an imagemagick, yes bash, and write a script ... By the way, there was a post on this topic only today . But the situation in Windows has thrown me into thought.

    Of course, surely there is specific software, but the soul of a programmer requires a systematic approach) In general, I was wondering how such problems can be solved in Windows. I immediately refused to use the Windows shell (do not ask why). I decided to write progku in Java. Actually, this was done - a folder is fed to the input, all files with the desired extension are recursively searched for, whether they need to be compressed and calculated to scale them.
    I bring the code (I'm new to Java, so do not scold, but the constructive criticism is very interesting): But how to run this program? Writing a user interface for such a task would again be wasteful. Having thought

    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 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 getTree(File dir){
        LinkedList result = new LinkedList();
        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.


    Googling decided to embed this program in the context menu for devices. However, I also want to see debug printing (not so much for debugging, but rather for understanding that the process is moving). I decided to do so - cmd-file, as a wrapper for the program (still screw shell screwed). So, we make the file from the jar class, put it in C: / Program Files / imgconv / imgconv.jar, make the cmd file ConvertImages.cmd: (Naturally, the java executable must be accessible via the PATH variable) Now we need to add a menu item. We do this:
    java -jar "C:\Program Files\imgconv\imgconv.jar" %1
    pause



    • Open the registry in HKEY_CLASSES_ROOT \ Drive \ shell \
    • Create an Image Converter section (This will be the name of the menu item)
    • In it we create the command section
    • Set the default value in it C: \ Program Files \ imgconv \ ConvertImages.cmd% 1
    • Check

    It turned out to be very convenient - we start it, check whether we want to resize, click ok and meditate on the process.
    PS This opus is not advice, guidance or anything else in the same vein. 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 everyone!

    Also popular now: