Вы можете использовать следующий код, чтобы обрезать subimage из образа.


import java.awt.*;

import java.awt.event.*;

import java.awt.image.*;

import java.io.*;

import javax.imageio.ImageIO;

import javax.swing.*;

import javax.swing.event.MouseInputAdapter;

 

public class Cropping extends JPanel

{

    BufferedImage image;

    Dimension size;

    Rectangle clip;

    boolean showClip;

 

    public Cropping(BufferedImage image)

    {

        this.image = image;

        size = new Dimension(image.getWidth(), image.getHeight());

        showClip = false;

    }

 

    protected void paintComponent(Graphics g)

    {

        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D)g;

        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

                            RenderingHints.VALUE_ANTIALIAS_ON);

        int x = (getWidth() - size.width)/2;

        int y = (getHeight() - size.height)/2;

        g2.drawImage(image, x, y, this);

        if(showClip)

        {

            if(clip == null)

                createClip();

            g2.setPaint(Color.red);

            g2.draw(clip);

        }

    }

 

    public void setClip(int x, int y)

    {

        // keep clip within raster

        int x0 = (getWidth() - size.width)/2;

        int y0 = (getHeight() - size.height)/2;

        if(x < x0 || x + clip.width  > x0 + size.width ||

           y < y0 || y + clip.height > y0 + size.height)

            return;

        clip.setLocation(x, y);

        repaint();

    }

 

    public Dimension getPreferredSize()

    {

        return size;

    }

 

    private void createClip()

    {

        clip = new Rectangle(140140);

        clip.x = (getWidth() - clip.width)/2;

        clip.y = (getHeight() - clip.height)/2;

    }

 

    private void clipImage()

    {

        BufferedImage clipped = null;

        try

        {

            int w = clip.width;

            int h = clip.height;

            int x0 = (getWidth()  - size.width)/2;

            int y0 = (getHeight() - size.height)/2;

            int x = clip.x - x0;

            int y = clip.y - y0;

            clipped = image.getSubimage(x, y, w, h);

        }

        catch(RasterFormatException rfe)

        {

            System.out.println("raster format error: " + rfe.getMessage());

            return;

        }

        JLabel label = new JLabel(new ImageIcon(clipped));

        JOptionPane.showMessageDialog(this, label, "clipped image",

                                      JOptionPane.PLAIN_MESSAGE);

    }

 

    private JPanel getUIPanel()

    {

        final JCheckBox clipBox = new JCheckBox("show clip", showClip);

        clipBox.addActionListener(new ActionListener()

        {

            public void actionPerformed(ActionEvent e)

            {

                showClip = clipBox.isSelected();

                repaint();

            }

        });

        JButton clip = new JButton("clip image");

        clip.addActionListener(new ActionListener()

        {

            public void actionPerformed(ActionEvent e)

            {

                clipImage();

            }

        });

        JPanel panel = new JPanel();

        panel.add(clipBox);

        panel.add(clip);

        return panel;

    }

 

    public static void main(String[] argsthrows IOException

    {

        File file = new File("images/cougar.jpg");

        Cropping test = new Cropping(ImageIO.read(file));

        ClipMover mover = new ClipMover(test);

        test.addMouseListener(mover);

        test.addMouseMotionListener(mover);

        JFrame f = new JFrame();

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.getContentPane().add(new JScrollPane(test));

        f.getContentPane().add(test.getUIPanel()"South");

        f.setSize(400,400);

        f.setLocation(200,200);

        f.setVisible(true);

    }

}

 

class ClipMover extends MouseInputAdapter

{

    Cropping cropping;

    Point offset;

    boolean dragging;

 

    public ClipMover(Cropping c)

    {

        cropping = c;

        offset = new Point();

        dragging = false;

    }

 

    public void mousePressed(MouseEvent e)

    {

        Point p = e.getPoint();

        if(cropping.clip.contains(p))

        {

            offset.x = p.x - cropping.clip.x;

            offset.y = p.y - cropping.clip.y;

            dragging = true;

        }

    }

 

    public void mouseReleased(MouseEvent e)

    {

        dragging = false;

    }

 

    public void mouseDragged(MouseEvent e)

    {

        if(dragging)

        {

            int x = e.getX() - offset.x;

            int y = e.getY() - offset.y;

            cropping.setClip(x, y);

        }

    }

}


Следующий метод Java принимает BufferedImage объекта и возвращает ее увеличенную версию. Параметр N определяет расширения фактор.

Чтобы увеличить изображение на целое число N фактора, мы будем реплицировать пикселей, что каждый пиксел исходного изображения становится NxN блока идентичны пикселей в результирующем изображении.


    public static BufferedImage enlarge(BufferedImage image, int n) {

        

        int w = n * image.getWidth();

        int h = n * image.getHeight();

        

        BufferedImage enlargedImage =

                new BufferedImage(w, h, image.getType());

        

        for (int y=0; y < h; ++y)

            for (int x=0; x < w; ++x)

                enlargedImage.setRGB(x, y, image.getRGB(x/n, y/n));

        

        return enlargedImage;

    }

PixelGrabber класс имеющихся в java.awt.Image packate могут быть использованы для доступа пикселов изображения объекта. PixelGrabber класса могут приобрести данные пикселей, синхронно или асинхронно. Он может сохранить значения пикселов в указанном пользователем массив или создать подходящие сам массив.

В следующем примере показано, как использовать класс PixelGrabber получить данные из пиксел изображения объекта.


import java.awt.Image;

import java.awt.Toolkit;

import java.awt.image.PixelGrabber;



public class PixelGrabberTest {

    

    public PixelGrabberTest() {

    }

    

    public static void processImage(String inFile, String outFile) {

        

        Image image = Toolkit.getDefaultToolkit().getImage(inFile);

        

        try {

            

            PixelGrabber grabber = 

                    new PixelGrabber(image, 00, -1, -1false);

            

            if (grabber.grabPixels()) {

                int width = grabber.getWidth();

                int height = grabber.getHeight();

                

                if (isGreyscaleImage(grabber)) {

                    byte[] data = (byte[]) grabber.getPixels();

                    

                    // Process greyscale image ...

                    

                }

                else {

                    int[] data = (int[]) grabber.getPixels();

                    

                    // Process Color image

                    

                }

            }

        }

        catch (InterruptedException e1) {

            e1.printStackTrace();

        }

    }

    

    public static final boolean isGreyscaleImage(PixelGrabber pg) {

        return pg.getPixels() instanceof byte[];

    }

    

    public static void main(String args[]) {

        

        if (args.length > 1) {

            processImage(args[0], args[1]);

            System.exit(0);

        else {

            System.err.println(

                    "usage: java PixelGrabberTest <infile> <outfile>");

            

            System.exit(2);

        }

          

    }

}

Следующий метод Java принимает BufferedImage объекта и возвращает его сократилась версии. Параметр N определяет сокращение фактора.

Чтобы уменьшить изображение на целое N фактора, мы будем образцу каждого го пикселя по горизонтали и вертикали, и игнорировать другие.


    public static BufferedImage enlarge(BufferedImage image, int n) {

        

        int w = image.getWidth() / n;

        int h = image.getHeight() / n;

        

        BufferedImage shrunkImage =

                new BufferedImage(w, h, image.getType());

        

        for (int y=0; y < h; ++y)

            for (int x=0; x < w; ++x)

                shrunkImage.setRGB(x, y, image.getRGB(x*n, y*n));

        

        return shrunkImage;

    }

Эта подсказка содержит простой декодер PNG исходного кода в Java.


import java.awt.Graphics;

import java.awt.Insets;

import java.awt.image.BufferedImage;

import java.awt.image.ColorModel;

import java.awt.image.DataBuffer;

import java.awt.image.DataBufferByte;

import java.awt.image.IndexColorModel;

import java.awt.image.Raster;

import java.awt.image.WritableRaster;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.DataInputStream;

import java.io.EOFException;

import java.io.IOException;

import java.io.InputStream;

import java.io.UnsupportedEncodingException;

import java.util.zip.CRC32;

import java.util.zip.InflaterInputStream;



import javax.swing.JFrame;



public class PNGDecoder {

  public static void main(String[] argsthrows Exception {

    String name = "logo.png";

    if (args.length > 0)

      name = args[0];

    InputStream in = PNGDecoder.class.getResourceAsStream(name);

    final BufferedImage image = PNGDecoder.decode(in);

    in.close();



    JFrame f = new JFrame() {

      public void paint(Graphics g) {

        Insets insets = getInsets();

        g.drawImage(image, insets.left, insets.top, null);

      }

    };

    f.setVisible(true);

    Insets insets = f.getInsets();

    f.setSize(image.getWidth() + insets.left + insets.right, image

        .getHeight()

        + insets.top + insets.bottom);

  }



  public static BufferedImage decode(InputStream inthrows IOException {

    DataInputStream dataIn = new DataInputStream(in);

    readSignature(dataIn);

    PNGData chunks = readChunks(dataIn);



    long widthLong = chunks.getWidth();

    long heightLong = chunks.getHeight();

    if (widthLong > Integer.MAX_VALUE || heightLong > Integer.MAX_VALUE)

      throw new IOException("That image is too wide or tall.");

    int width = (intwidthLong;

    int height = (intheightLong;



    ColorModel cm = chunks.getColorModel();

    WritableRaster raster = chunks.getRaster();



    BufferedImage image = new BufferedImage(cm, raster, false, null);



    return image;

  }



  protected static void readSignature(DataInputStream inthrows IOException {

    long signature = in.readLong();

    if (signature != 0x89504e470d0a1a0aL)

      throw new IOException("PNG signature not found!");

  }



  protected static PNGData readChunks(DataInputStream inthrows IOException {

    PNGData chunks = new PNGData();



    boolean trucking = true;

    while (trucking) {

      try {

        // Read the length.

        int length = in.readInt();

        if (length < 0)

          throw new IOException("Sorry, that file is too long.");

        // Read the type.

        byte[] typeBytes = new byte[4];

        in.readFully(typeBytes);

        // Read the data.

        byte[] data = new byte[length];

        in.readFully(data);

        // Read the CRC.

        long crc = in.readInt() 0x00000000ffffffffL// Make it

        // unsigned.

        if (verifyCRC(typeBytes, data, crc== false)

          throw new IOException("That file appears to be corrupted.");



        PNGChunk chunk = new PNGChunk(typeBytes, data);

        chunks.add(chunk);

      catch (EOFException eofe) {

        trucking = false;

      }

    }

    return chunks;

  }



  protected static boolean verifyCRC(byte[] typeBytes, byte[] data, long crc) {

    CRC32 crc32 = new CRC32();

    crc32.update(typeBytes);

    crc32.update(data);

    long calculated = crc32.getValue();

    return (calculated == crc);

  }

}



class PNGData {

  private int mNumberOfChunks;



  private PNGChunk[] mChunks;



  public PNGData() {

    mNumberOfChunks = 0;

    mChunks = new PNGChunk[10];

  }



  public void add(PNGChunk chunk) {

    mChunks[mNumberOfChunks++= chunk;

    if (mNumberOfChunks >= mChunks.length) {

      PNGChunk[] largerArray = new PNGChunk[mChunks.length + 10];

      System.arraycopy(mChunks, 0, largerArray, 0, mChunks.length);

      mChunks = largerArray;

    }

  }



  public long getWidth() {

    return getChunk("IHDR").getUnsignedInt(0);

  }



  public long getHeight() {    return getChunk("IHDR").getUnsignedInt(4);

  }



  public short getBitsPerPixel() {

    return getChunk("IHDR").getUnsignedByte(8);

  }



  public short getColorType() {

    return getChunk("IHDR").getUnsignedByte(9);

  }



  public short getCompression() {

    return getChunk("IHDR").getUnsignedByte(10);

  }



  public short getFilter() {

    return getChunk("IHDR").getUnsignedByte(11);

  }



  public short getInterlace() {

    return getChunk("IHDR").getUnsignedByte(12);

  }



  public ColorModel getColorModel() {

    short colorType = getColorType();

    int bitsPerPixel = getBitsPerPixel();



    if (colorType == 3) {

      byte[] paletteData = getChunk("PLTE").getData();

      int paletteLength = paletteData.length / 3;

      return new IndexColorModel(bitsPerPixel, paletteLength,

          paletteData, 0false);

    }

    System.out.println("Unsupported color type: " + colorType);

    return null;

  }



  public WritableRaster getRaster() {

    int width = (intgetWidth();

    int height = (intgetHeight();

    int bitsPerPixel = getBitsPerPixel();

    short colorType = getColorType();



    if (colorType == 3) {

      byte[] imageData = getImageData();

      DataBuffer db = new DataBufferByte(imageData, imageData.length);

      WritableRaster raster = Raster.createPackedRaster(db, width,

          height, bitsPerPixel, null);

      return raster;

    else

      System.out.println("Unsupported color type!");

    return null;

  }



  public byte[] getImageData() {

    try {

      ByteArrayOutputStream out = new ByteArrayOutputStream();

      // Write all the IDAT data into the array.

      for (int i = 0; i < mNumberOfChunks; i++) {

        PNGChunk chunk = mChunks[i];

        if (chunk.getTypeString().equals("IDAT")) {

          out.write(chunk.getData());

        }

      }

      out.flush();

      // Now deflate the data.

      InflaterInputStream in = new InflaterInputStream(

          new ByteArrayInputStream(out.toByteArray()));

      ByteArrayOutputStream inflatedOut = new ByteArrayOutputStream();

      int readLength;

      byte[] block = new byte[8192];

      while ((readLength = in.read(block)) != -1)

        inflatedOut.write(block, 0, readLength);

      inflatedOut.flush();

      byte[] imageData = inflatedOut.toByteArray();

      // Compute the real length.

      int width = (intgetWidth();

      int height = (intgetHeight();

      int bitsPerPixel = getBitsPerPixel();

      int length = width * height * bitsPerPixel / 8;



      byte[] prunedData = new byte[length];



      // We can only deal with non-interlaced images.

      if (getInterlace() == 0) {

        int index = 0;

        for (int i = 0; i < length; i++) {

          if ((i * / bitsPerPixel% width == 0) {

            index++; // Skip the filter byte.

          }

          prunedData[i= imageData[index++];

        }

      else

        System.out.println("Couldn't undo interlacing.");



      return prunedData;

    catch (IOException ioe) {

    }

    return null;

  }



  public PNGChunk getChunk(String type) {

    for (int i = 0; i < mNumberOfChunks; i++)

      if (mChunks[i].getTypeString().equals(type))

        return mChunks[i];

    return null;

  }

}



class PNGChunk {

  private byte[] mType;



  private byte[] mData;



  public PNGChunk(byte[] type, byte[] data) {

    mType = type;

    mData = data;

  }



  public String getTypeString() {

    try {

      return new String(mType, "UTF8");

    catch (UnsupportedEncodingException uee) {

      return "";

    }

  }



  public byte[] getData() {

    return mData;

  }



  public long getUnsignedInt(int offset) {

    long value = 0;

    for (int i = 0; i < 4; i++)

      value += (mData[offset + i0xff<< ((- i8);

    return value;

  }



  public short getUnsignedByte(int offset) {

    return (short) (mData[offset0x00ff);

  }

}

Иногда изображений, полученных с Вашей цифровой камерой, не может быть точно, что вы хотите. Например, вы можете стирать их или конкретизировать их. Или вы можете скрасить им или тон их вниз. Java.awt.Image пакет содержит утилиты для принятия такого рода изменения в цифровых изображений. Использование этих утилит, можно добиться одних и тех же последствий, что вы найдете в High-End коммерческих пакетов изображений.

В этот совет, вы будете использовать ConvolveOp, класс в java.awt.Image пакет, чтобы изменить цифровое изображение. ConvolveOp реализующий свертки от источника к приемнику. Вы можете думать о свертке операция, которая заменяет каждый пиксель изображения в сочетании с некоторыми из оригинального пикселя и его соседей. Вы задаете комбинацию с помощью массива из поплавков. Поплавки кратных точек. Из этого массива вы создаете экземпляр ядра, и использовать его например для выполнения свертки.

Например, если массив состоит из трех по три массива следующим образом:

a b c
d e f
g h i

Тогда в результате свертки заменяющий в центре пикселя с суммой:

  • a times the value of the pixel above and to the left of center
  • b times the value of the pixel above the center
  • c times the pixel above and to the right of the center
  • and so on

Другими словами, вы умножения значения пиксела значение в ядре при соответствующем положении, и добавить их. Если сумма записей в массив 1, то полученное изображение будет иметь тот же динамический диапазон, что и исходное изображение.

Вот более конкретные. Рассмотрим следующие три по три массива:

0   0.2   0
0.2  0.2  0.2
0   0.2   0

Этот массив соответствует замене каждого пикселя при средней его стоимости вместе с пикселей вправо, влево, выше, и ниже. Эффект заключается в размытости картинки немного.

Теперь рассмотрим следующие три по три массива. Он соответствует личности операции. Применение его в качестве части ничего свертки изменения. Иными словами, он заменяет каждый пиксель со своим предыдущим значением.

0 0 0
0 1 0
0 0 0

Однако, если 1 в предыдущем массиве заменить 2, в результате изображение ярче и немного размытой. Замена с 1 .5 результатов в темных изображений.

Существует ничего магического три по три массива. Если вашей целью является выполнение свертки, которые симметричны относительно центра и которая зависит от центрального пиксела, необходимо квадратный массив с нечетной размерности. Пять на пять, семь по семь, и любой другой нечетной размерности массива будет работать так же, как три по три массива. Предыдущий пример может даже быть реализованы с помощью одного-By-один массив. Например, в следующий метод, вы создаете массив поплавков, содержащих один элемент. Затем вы можете создать новую поочередно по одной ядра объекта из этого элемента, и сдать объект в конструкторе ConvolveOp. Наконец, вы BufferedImageOp применить к исходному BufferedImage получить измененное изображение.


   private void setBrightnessFactor(float multiple) {

     float[] brightKernel = {multiple};

     BufferedImageOp bright

       new ConvolveOp(new Kernel(11, brightKernel));

     convolvedImage 

       = bright.filter(originalImage, null);

     repaint();



   }

Этот метод привел два требования. Одним из требований является то, что вам необходимо изменить paintComponent () для перерисовки новое изображение каждый раз он меняется.


   public void paintComponent(Graphics g) {

     g.drawImage(convolvedImage, 00this);

   }

Вторым требованием является то, что нужно сначала создать BufferedImage, к которым можно применить эти эффекты. В этом случае, читайте в test.jpg и создать изображение из него. Затем создайте BufferedImage с тем же размеры, как и исходное изображение. В качестве последнего шага, необходимо обратить изображение на BufferedImage.


   Image image = new ImageIcon("test.jpg").getImage();

   originalImage 

     new BufferedImage(image.getWidth(null),

       image.getHeight(null)

       BufferedImage.TYPE_INT_RGB);

   Graphics g = originalImage.createGraphics();

   g.drawImage(image, 00null);

   g.dispose();

Вместо одномерного ядра, вы также можете использовать три по три ядра на основе следующих версий setBrightnessFactor.


   private void setBrightnessFactor(float multiple) {

      float[] brightKernel = {0,    0,     0,

                              0, multiple, 0,

                              0,    0,     0};

      BufferedImageOp bright

        new ConvolveOp(new Kernel(33, brightKernel));

      convolvedImage 

        = bright.filter(originalImage, null);

      repaint();

   }

Вот пример программы, BrightnessChanger, что создает для просмотра изображений. Зритель включает ползунок, который можно использовать для управления яркостью, изменяя значения нескольких используются. Вам понадобится тестового изображения. В этом случае имя изображения установлен test.jpg. Изображение должно быть в каталоге, в котором Вы запускаете программу BrightnessChanger. Вы можете найти изображения весело образцом для использования.


    import javax.swing.JFrame;

    import javax.swing.JPanel;

    import javax.swing.ImageIcon;

    import javax.swing.JSlider;

    import javax.swing.event.ChangeListener;

    import javax.swing.event.ChangeEvent;

    import java.awt.Graphics;

    import java.awt.Image;

    import java.awt.BorderLayout;

    import java.awt.image.Kernel;

    import java.awt.image.ConvolveOp;

    import java.awt.image.BufferedImageOp;

    import java.awt.image.BufferedImage;



    public class BrightnessChanger extends JPanel {



       private BufferedImage originalImage;

       private BufferedImage convolvedImage;

       private JSlider slide = new JSlider(1,50,10);



       BrightnessChanger() {

         createBufferedImages();

         setUpJFrame();

       }



       private void createBufferedImages() {

         Image image

           new ImageIcon("test.jpg").getImage();

         originalImage

           new BufferedImage(image.getWidth(null),

             image.getHeight(null),

             BufferedImage.TYPE_INT_RGB);

         convolvedImage

           new BufferedImage(image.getWidth(null),

             image.getHeight(null),

             BufferedImage.TYPE_INT_RGB);

         Graphics g = originalImage.createGraphics();

         g.drawImage(image, 00null);

         g.dispose();

         setBrightnessFactor(1);

       }



       private void setUpJFrame() {

         JFrame myFrame = new JFrame("Image Brightness");

         myFrame.setSize(convolvedImage.getWidth(),

                         convolvedImage.getHeight());

         myFrame.getContentPane().setLayout(

           new BorderLayout());

         myFrame.getContentPane().add(

           this, BorderLayout.CENTER);

         slide.addChangeListener(

           new BrightnessListener());

         myFrame.getContentPane().add(

           slide,BorderLayout.SOUTH);

         myFrame.setDefaultCloseOperation(

           JFrame.EXIT_ON_CLOSE);

         myFrame.setVisible(true);

       }



       private void setBrightnessFactor(float multiple) {

         float[] brightKernel = {multiple};

         BufferedImageOp bright

           new ConvolveOp(

               new Kernel(11, brightKernel));

         bright.filter(originalImage, convolvedImage);

         repaint();



       }



        public void paintComponent(Graphics g) {

         g.drawImage(convolvedImage, 00this);

       }



       class BrightnessListener implements ChangeListener{

         public void stateChanged(

           ChangeEvent changeEvent) {

             setBrightnessFactor(

               (float)(slide.getValue())/10);

         }

       }



       public static void main(String[] args) {

           new BrightnessChanger();

         }



    }

java.awt.image

BrightnessChanger примером служит введением в свертках, а не как рекомендуемый способ управления яркостью изображения. В будущем Tech отзыв, вы увидите, как использовать некоторые элементы управления ориентирована на цвета и яркости.

В дополнение к использованию площади, нечетной массивы для ядра свертки, вам нужно использовать (по большей части) симметрична массивов. Следующий пример использует три-By-трех массивов, которые построены из трех компонентов:

0  0  0         0  1  0              1  0  1
IDENTITY  0  1  0   EDGE  1  0  1      CORNER  0  0  0
0  0  0         0  1  0              1  0  1

В результате массив построен из линейных комбинаций этих строительных блоков. Пока сумма записей не равна нулю, то нормализовать ядра путем деления этой суммы. Таким образом, вы получаете изображение, которое имеет такой же интенсивностью, как исходное изображение. Например, если вы добавите EDGE и личности вы получите следующее:

0  1  0
1  1  1
0  1  0

Сумма записей 5. Затем нормализации путем деления каждой записи от 5 до получим следующие "массив Blur":

0  0.2  0
.2  0.2 0.2
0  0.2  0

Вот код для создания этих ядер от параметров для кратных трех массивах базы.


   private Kernel getKernel(

     int corner, int edge, int identity) {

      float[] kernel = new float[9];

      int sum = corner * + edge * + identity;

      if (sum == 0sum = 1;

      for (int i = 0; i < 9; i++) {

        kernel[i(corner * CORNER[i]

          + edge * EDGE[i]

          + identity * IDENTITY[i]) / sum;

    }

    return new Kernel(33, kernel);

 }



After you have the kernel, you perform the convolution much as before.



   void convolveImage(Kernel kernel) {

      BufferedImageOp convolve

        new ConvolveOp(kernel);

      buffImage = convolve.filter(buffImage, null);

      repaint();

   }

Теперь давайте запустим программу тестирования, названный Размывание. При запуске Размывание, вам нужно ввести трех параметров командной строки. Они являются Int значений, соответствующих кратны углу, EDGE, и самобытность. Например, если ввести:

java Convolve 1 0 0

Вы должны увидеть несколько размытым изображением. Опять же, нужно изображение с именем test.jpg.


   import javax.swing.ImageIcon;

   import javax.swing.JFrame;

   import javax.swing.JPanel;

   import java.awt.image.BufferedImage;

   import java.awt.image.BufferedImageOp;

   import java.awt.image.ConvolveOp;

   import java.awt.image.Kernel;

   import java.awt.Image;

   import java.awt.Graphics;



   public class Convolve extends JPanel {

      private BufferedImage buffImage;



      private final float[] IDENTITY = {000,

                                        010,

                                        000};



      private final float[] EDGE = {010,

                                    101,

                                    010};



      private final float[] CORNER = {101,

                                      000,

                                      101};





      Convolve(int corner, int edge, int identity) {

        createBufferedImages();

        setUpJFrame();

        convolveImage(getKernel(corner, edge, identity));

      }



      private void createBufferedImages() {

        Image image 

          new ImageIcon("test.jpg").getImage();

        buffImage 

          new BufferedImage(image.getWidth(null),

            image.getHeight(null)

            BufferedImage.TYPE_INT_RGB);

        Graphics g = buffImage.createGraphics();

        g.drawImage(image, 00null);

        g.dispose();

      }



      private void setUpJFrame() {

        JFrame myFrame = new JFrame("Image Brightness");

        myFrame.setSize(buffImage.getWidth(),

          buffImage.getHeight());

        myFrame.getContentPane().add(this);

        myFrame.setDefaultCloseOperation(

          JFrame.EXIT_ON_CLOSE);

        myFrame.setVisible(true);

      }



      void convolveImage(Kernel kernel) {

        BufferedImageOp convolve

          new ConvolveOp(kernel);

        buffImage = convolve.filter(buffImage, null);

        repaint();



      }



      private Kernel getKernel(

        int corner, int edge, int identity) {

         float[] kernel = new float[9];

         int sum = corner * + edge * + identity;

         if (sum == 0sum = 1;

         for (int i = 0; i < 9; i++) {

           kernel[i(corner * CORNER[i]

             + edge * EDGE[i]

             + identity * IDENTITY[i]) / sum;

         }

        return new Kernel(33, kernel);

      }



      public void paintComponent(Graphics g) {

        g.drawImage(buffImage, 00this);

      }





      public static void main(String[] args) {

        if (args.length != 3) {

          System.out.println("Usage: java Convolve" +

                             " corner edge identity");

          System.out.println("where corner, edge, " +

                             "and identity are ints");

          System.exit(0);

        }

        int corner = Integer.parseInt(args[0]);

        int edge = Integer.parseInt(args[1]);

        int identity = Integer.parseInt(args[2]);

        new Convolve(corner, edge, identity);



      }



   }

java.awt.image

Попробуйте другой комбинации из трех параметров командной строки. Например, введите -1 -1 8 см. Основные контуры объектов. Это не может быть нормализована как сумма равна нулю. Или введите 0 -1 5 для острее ввиду исходное изображение. Вы можете легко расширить этот пример, чтобы пять на пять массивов и выше, с другой симметричной примитивов.

Для получения дополнительной информации об использовании ConvoleOp, см. главу 5: "Imaging" в Руководстве программиста Java 2D API.

Copyright (C) 2004-2005 Sun Microsystems, Inc
Все права защищены.

Следующий метод Java принимает массив BufferedImage объектов и возвращает среднее изображение, полученное из массива изображений.

Основное применение изображений усреднения удаления шума. Шума изображения, в основном нежелательных и проявляется в пиксели изображения. Это присуще и цифровых камер, и создается, в частности, под действием температуры и в условиях низкой освещенности, и часто видное место в длинных выдержках и фотографии, сделанные при высокой чувствительности ISO. Его эффект аналогичен Film Grain.

Когда изображение сцены неизменный развращены случайные шумы, последовательность этих образов может быть усредненная вместе с тем, чтобы снизить воздействие шума. Это работает, потому что шум возмущает пиксель уровни серого, и положительное возмущение данной величины, как правило, столь же вероятно, как и негативные возмущения и ту же величину. Следовательно, существует тенденция эти "ошибки" в пиксельных серый уровня компенсируют друг друга во все большей степени, так как количество усредненные изображения увеличивается.

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


    public static BufferedImage average(BufferedImage[] images) {

        

        int n = images.length;

        

        // Assuming that all images have the same dimensions

        int w = images[0].getWidth();

        int h = images[0].getHeight();

        

        

        BufferedImage average =

                new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);

        

        WritableRaster raster =

                average.getRaster().createCompatibleWritableRaster();

        

        for (int y=0; y < h; ++y)

            for (int x=0; x < w; ++x) {

                

                float sum = 0.0f;

            

                for (int i=0; i<n; ++i)

                    sum = sum + images[i].getRaster().getSample(x, y, 0);

            

                raster.setSample(x, y, 0, Math.round(sum/n));            

            }

        

        average.setData(raster);

        

        return average;

    }

Расчет среднего значения изображение записывается в следующий метод. Хотя пример написан для изображений в серой уровня, вы можете изменить метод для применения его в RGB изображения легко. Вам просто необходимо для вычисления среднего значения для каждого канала (красный, зеленый или синий канал). Вы можете получить значения пикселей по другим каналам, изменяя третий параметр getSample (X, Y, channelNo) метод класса растра.


    public static double meanValue(BufferedImage image) {

        

        Raster raster = image.getRaster();        

        double sum = 0.0;

        

        for (int y=0; y < image.getHeight(); ++y)

            for (int x=0; x < image.getWidth(); ++x)

                sum += raster.getSample(x,y,0);

        

        return sum / (image.getWidth() * image.getHeight());

    }