2013-11-19 5 views
3

Я использую этот фрагмент кода для рисования изображения в графический компонент. Она должна размер изображения до максимального доступного пространства, если оно достаточно велико:BufferedImage getScaledInstance изменяет яркость изображения

// getWidth() = component width, image.getWidth() = image width 
    double w = getWidth() * 1.0/image.getWidth(); 
    double h = getHeight() * 1.0/image.getHeight(); 
    if (w < 1 || h < 1) { 
     double d = Math.min(Math.min(w, h), 1); 
     g.drawImage(bi.getScaledInstance((int) (d * image.getWidth()), (int) (d * image.getHeight()), Image.SCALE_REPLICATE), 0, 0, null); 
    } else { 
     g.drawImage(bi, 0, 0, null); 
    } 

код работает, то изображение становится правильно масштабируется. Но, к сожалению, когда изображение масштабируется, яркость изображений изменяется также и на графике!

У кого-нибудь есть идея, откуда это могло произойти? Я прикрепил масштабированную (первую) и не масштабированную версию экрана.

Я надеюсь, что кто-то может мне помочь!

Cheers! Sebastian

image scaled with <code>getScaledInstance</code> without <code>getScaledInstance</code>

ответ

5

Это, как представляется, проблема с Image.getScaledInstance (а также может быть связано с серой масштабируемые изображения). Я попробовал несколько других советов, но имел тот же результат.

Вместо этого я использовал свой собственный алгоритм масштабирования (который я украл из Интернета), который использует разделяй и властвуй подход, который обычно дает лучшие результаты ...

Итак, оригинал ONTOP, Image#getScaledInstance слева , пользовательский масштабируются по правому

enter image description here

нб: Это использует некоторые из моего личного кода библиотеки, поэтому он не может быть полностью подходит для вас, но это представляет основу ...

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.RenderingHints; 
import java.awt.Transparency; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class ImageScaleTest { 

    public static void main(String[] args) { 
     new ImageScaleTest(); 
    } 

    public ImageScaleTest() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public static enum RenderQuality { 

     High, 
     Medium, 
     Low 
    } 

    public class TestPane extends JPanel { 

     private BufferedImage original; 
     private BufferedImage scaled2; 
     private Image scaled; 

     public TestPane() { 
      try { 
       original = ImageIO.read(new File("/path/to/image")); 
       scaled = original.getScaledInstance(original.getWidth()/2, original.getHeight()/2, Image.SCALE_DEFAULT); 
       scaled2 = getScaledInstance(original, 0.5d, RenderQuality.High); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(400, 600); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      g2d.drawImage(original, 0, 0, this); 
      g2d.drawImage(scaled, 0, original.getHeight(), this); 
      g2d.drawImage(scaled2, scaled.getWidth(this), original.getHeight(), this); 
      g2d.dispose(); 
     } 
    } 

    public static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, RenderQuality quality) { 

     BufferedImage imgBuffer = null; 

     if (quality == RenderQuality.High) { 

//   System.out.println("Scale high quality..."); 
      imgBuffer = getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true); 

     } else if (quality == RenderQuality.Medium) { 

      imgBuffer = getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_BILINEAR, false); 

     } else { 

//   System.out.println("Scale low quality..."); 
      imgBuffer = getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR, false); 

     } 

     return imgBuffer; 

    } 

    protected static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint, boolean bHighQuality) { 

     BufferedImage imgScale = img; 

     int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor); 
     int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor); 

     if (dScaleFactor <= 1.0d) { 

      imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint, bHighQuality); 

     } else { 

      imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, hint, bHighQuality); 

     } 

     return imgScale; 

    } 

    protected static BufferedImage getScaledDownInstance(BufferedImage img, 
      int targetWidth, 
      int targetHeight, 
      Object hint, 
      boolean higherQuality) { 

     int type = (img.getTransparency() == Transparency.OPAQUE) 
       ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; 

     BufferedImage ret = (BufferedImage) img; 

     if (targetHeight > 0 || targetWidth > 0) { 
      int w, h; 
      if (higherQuality) { 
       // Use multi-step technique: start with original size, then 
       // scale down in multiple passes with drawImage() 
       // until the target size is reached 
       w = img.getWidth(); 
       h = img.getHeight(); 
      } else { 
       // Use one-step technique: scale directly from original 
       // size to target size with a single drawImage() call 
       w = targetWidth; 
       h = targetHeight; 
      } 

      do { 
       if (higherQuality && w > targetWidth) { 
        w /= 2; 
        if (w < targetWidth) { 
         w = targetWidth; 
        } 
       } 

       if (higherQuality && h > targetHeight) { 
        h /= 2; 
        if (h < targetHeight) { 
         h = targetHeight; 
        } 
       } 

       BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type); 
       Graphics2D g2 = tmp.createGraphics(); 
       g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); 
       g2.drawImage(ret, 0, 0, w, h, null); 
       g2.dispose(); 

       ret = tmp; 
      } while (w != targetWidth || h != targetHeight); 
     } else { 
      ret = new BufferedImage(1, 1, type); 
     } 
     return ret; 
    } 

    protected static BufferedImage getScaledUpInstance(BufferedImage img, 
      int targetWidth, 
      int targetHeight, 
      Object hint, 
      boolean higherQuality) { 

     int type = BufferedImage.TYPE_INT_ARGB; 

     BufferedImage ret = (BufferedImage) img; 
     int w, h; 
     if (higherQuality) { 
      // Use multi-step technique: start with original size, then 
      // scale down in multiple passes with drawImage() 
      // until the target size is reached 
      w = img.getWidth(); 
      h = img.getHeight(); 
     } else { 
      // Use one-step technique: scale directly from original 
      // size to target size with a single drawImage() call 
      w = targetWidth; 
      h = targetHeight; 
     } 

     do { 
      if (higherQuality && w < targetWidth) { 
       w *= 2; 
       if (w > targetWidth) { 
        w = targetWidth; 
       } 
      } 

      if (higherQuality && h < targetHeight) { 
       h *= 2; 
       if (h > targetHeight) { 
        h = targetHeight; 
       } 
      } 

      BufferedImage tmp = new BufferedImage(w, h, type); 
      Graphics2D g2 = tmp.createGraphics(); 
      g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); 
      g2.drawImage(ret, 0, 0, w, h, null); 
      g2.dispose(); 

      ret = tmp; 
      tmp = null; 
     } while (w != targetWidth || h != targetHeight); 
     return ret; 
    } 
} 

мая, также, как и для взглянуть на The Perils of Image.getScaledInstance()

PS- Я сделал быстрый бит поиска, и это, кажется, ошибка (или функция) в API

+1

+1 для опасности; «AffineTransformOp», обозначенный [здесь] (http://stackoverflow.com/a/4216635/230513), является альтернативой. – trashgod

+0

Спасибо! Я буду использовать эту реализацию! – Sebastian

Смежные вопросы