2015-09-23 12 views
0

Я пытаюсь экспортировать PNG quicklook продукта ALOS AVNIR-2 с помощью java API-интерфейсов BEAM. На следующем рисунке показан предварительный просмотр RGB для prduct, как он отображается в GUI луча.ALOS Satellite Product to PNG conversion issue (отсутствует вращение)

ALOS Satellite product quicklook, rotated according to its geocoding information.

Как вы можете видеть, изображение не в вертикальном положении, из-за его геокодирования. Я разработал очень простую java-программу для экспорта quicklook продукта.

public static void main(String[] args) { 

    String[] rgbBandNames = new String[3]; 
    rgbBandNames[0] = "radiance_3"; 
    rgbBandNames[1] = "radiance_2"; 
    rgbBandNames[2] = "radiance_1"; 

    try { 
    //Product inputProduct = ProductIO.readProduct(args[0]); 
     Product inputProduct = ProductIO.readProduct("C:\\nfsdata\\VOL-ALAV2A152763430-O1B2R_U"); 

     Band[] produtBands = inputProduct.getBands(); 
     Band[] rgbBands = new Band[3]; 

     int n = 0; 
     for (Band band : produtBands) { 
      if (band.getName().equals(rgbBandNames[0])) { 
       rgbBands[0] = band; 
      } else if (band.getName().equals(rgbBandNames[1])) { 
       rgbBands[1] = band; 
      } else if (band.getName().equals(rgbBandNames[2])) { 
       rgbBands[2] = band; 
      } 

      n = n + 1; 
     } 

     ImageInfo outImageInfo = ProductUtils.createImageInfo(rgbBands, true, ProgressMonitor.NULL); 
     BufferedImage outImage = ProductUtils.createRgbImage(rgbBands, outImageInfo, ProgressMonitor.NULL); 

     ImageIO.write(outImage, "PNG", new File(inputProduct.getName() + ".png")); 


    } catch (IOException e) { 
     System.err.println("Error: " + e.getMessage()); 
    } 
} 

Программа работает, но каждый PNG-образ, который я получаю от него, представляет собой вертикальное изображение PNG, как показано ниже.

ALOS Satellite product quicklook, upright.

Теперь я знаю, что это не возможно, чтобы иметь ГЕОКОДИРОВАНИЮ информацию внутри PNG изображения. Мне нужно только воспроизвести один и тот же «поворот» изображения. Любая идея?

ответ

1

Мне удалось решить мою проблему. Другими словами, мне удалось: извлечь quicklook из продукта ALOS AV2 O1B2R_U, повернутого в соответствии с информацией о геокодировании продукта (см. Изображение ниже).

ALOS Satellite product quicklook, rotated according to its geocoding information.

Причина этого заключается в том, что продукты АЛОС AV2 O1B2R_U есть вращение геокодирования уже применяется к растру. Как следствие, для того, чтобы успешно экспортировать quicklook, ротация должна быть получена из собственного растра и применена к выходному изображению. В будущем, я хотел бы напомнить и поделиться своим решением с сообществом. Это мой основной класс:

import com.bc.ceres.core.ProgressMonitor; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.Point; 
import java.awt.geom.AffineTransform; 
import java.awt.image.AffineTransformOp; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import org.esa.beam.framework.dataio.ProductIO; 
import org.esa.beam.framework.datamodel.Band; 
import org.esa.beam.framework.datamodel.ImageInfo; 
import org.esa.beam.framework.datamodel.MapGeoCoding; 
import org.esa.beam.framework.datamodel.Product; 
import org.esa.beam.util.ProductUtils; 

public static void main(String[] args) throws IOException { 

    String inputProductPath = "path\to\input\product"; 
    String outputProductPath = "path\to\output\image"; 

    // Read the source product. 
    Product inputProduct = ProductIO.readProduct(inputProductPath); 

    // Extract the RGB bands. 
    String[] bandNames = new String[3]; 
    Band[] bandData = new Band[3]; 

    bandNames[0] = "radiance_3"; 
    bandNames[1] = "radiance_2"; 
    bandNames[2] = "radiance_1"; 

    for (Band band : inputProduct.getBands()) { 

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

      if (band.getName().equalsIgnoreCase(bandNames[ i ])) { 
       bandData[ i ] = band; 
      } 
     } 
    } 

    // Generate quicklook image. 
    ImageInfo outImageInfo = ProductUtils.createImageInfo(bandData, true, ProgressMonitor.NULL); 
    BufferedImage outImage = ProductUtils.createRgbImage(bandData, outImageInfo, ProgressMonitor.NULL); 
    outImage = resize(outImage, WIDTH, 1200); 

    // Extract the orientation. 
    double orientation; 
    if (inputProduct.getGeoCoding() != null) { 
     orientation = -((MapGeoCoding) inputProduct.getGeoCoding()).getMapInfo().getOrientation(); 
    } else { 
     orientation = 0.0; 
    } 
    outImage = rotate(outImage, orientation); 

    // Write image. 
    ImageIO.write(outImage, "PNG", new File(outputProductPath)); 
} 

После того, как угол поворота QuickLook был извлечен из продукта источника (см код выше), то он должен быть применен к выходному изображению (BufferedImage). В приведенном выше коде используются две простые функции манипуляции изображениями: изменение размера (...) и поворот (...), см. Ниже их определение.

/** 
* Resizes the image {@code tgtImage} by setting one of its dimensions 
* (width or height, specified via {@code tgtDimension}) to {@code tgtSize} 
* and dynamically calculating the other one in order to preserve the aspect 
* ratio. 
* 
* @param tgtImage The image to be resized. 
* @param tgtDimension The selected dimension: {@code ImageUtil.WIDTH} or 
* {@code ImageUtil.WIDTH}. 
* @param tgtSize The new value for the selected dimension. 
* 
* @return The resized image. 
*/ 
public static BufferedImage resize(BufferedImage tgtImage, short tgtDimension, int tgtSize) { 

    int newWidth = 0, newHeight = 0; 

    if (HEIGHT == tgtDimension) { 
     newHeight = tgtSize; 
     newWidth = (tgtImage.getWidth() * tgtSize)/tgtImage.getHeight(); 
    } else { 
     newHeight = (tgtImage.getHeight() * tgtSize)/tgtImage.getWidth(); 
     newWidth = tgtSize; 
    } 

    Image tmp = tgtImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH); 
    BufferedImage outImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGemoticon; 

    Graphics2D g2d = outImage.createGraphics(); 
    g2d.drawImage(tmp, 0, 0, null); 
    g2d.dispose(); 

    return outImage; 
} 

/** 
* Rotates the image {@code tgtImage} by {@code tgtAngle} degrees clockwise. 
* 
* @param tgtImage The image to be rotated. 
* @param tgtAngle The rotation angle (expressed in degrees). 
* 
* @return The resized image. 
*/ 
public static BufferedImage rotate(BufferedImage tgtImage, double tgtAngle) { 

    int w = tgtImage.getWidth(); 
    int h = tgtImage.getHeight(); 

    AffineTransform t = new AffineTransform(); 
    t.setToRotation(Math.toRadians(tgtAngle), w/2d, h/2d); 

    Point[] points = { 
     new Point(0, 0), 
     new Point(w, 0), 
     new Point(w, h), 
     new Point(0, h) 
    }; 

    // Transform to destination rectangle. 
    t.transform(points, 0, points, 0, 4); 

    // Get destination rectangle bounding box 
    Point min = new Point(points[0]); 
    Point max = new Point(points[0]); 
    for (int i = 1, n = points.length; i < n; i++) { 
     Point p = points[ i ]; 
     double pX = p.getX(), pY = p.getY(); 

     // Update min/max x 
     if (pX < min.getX()) { 
      min.setLocation(pX, min.getY()); 
     } 
     if (pX > max.getX()) { 
      max.setLocation(pX, max.getY()); 
     } 

     // Update min/max y 
     if (pY < min.getY()) { 
      min.setLocation(min.getX(), pY); 
     } 
     if (pY > max.getY()) { 
      max.setLocation(max.getX(), pY); 
     } 
    } 

    // Determine new width, height 
    w = (int) (max.getX() - min.getX()); 
    h = (int) (max.getY() - min.getY()); 

    // Determine required translation 
    double tx = min.getX(); 
    double ty = min.getY(); 

    // Append required translation 
    AffineTransform translation = new AffineTransform(); 
    translation.translate(-tx, -ty); 
    t.preConcatenate(translation); 

    AffineTransformOp op = new AffineTransformOp(t, null); 
    BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGemoticon; 
    op.filter(tgtImage, outImage); 

    return outImage; 
}