ヘッダーをスキップ
Oracle Application Server MapViewerユーザーズ・ガイド
10g(10.1.3.1.0)
B40016-01
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

C カスタム・イメージ・レンダラの作成および登録

この付録では、イメージ・テーマで使用するためのカスタム・イメージ・レンダラの実装および登録方法について説明します。(イメージ・テーマについては、2.3.5項を参照してください。)

OracleAS MapViewerでサポートされていない画像形式のイメージ・テーマを指定したmapリクエストを作成する場合、最初にその形式に対応したカスタム・イメージ・レンダラを実装し、登録する必要があります。たとえば、3.1.6項例3-6のECW形式はOracleAS MapViewerでサポートされていません。したがって、この例を機能させるには、最初にECW形式の画像に対応したイメージ・レンダラを実装し、登録する必要があります。

oracle.sdovis.CustomImageRendererインタフェースは、Oracle Application Server環境の$ORACLE_HOME/lbs/libディレクトリに格納された、sdovis.jarパッケージで定義されています。OC4Jのスタンドアロン・インストールを実行した場合、sdovis.jar$MAPVIEWER/web/WEB-INF/libにアンパックされます。このインタフェースのソース・コードを次に示します。

/**
 * An interface for a custom image painter that supports user-defined image
 * formats. An implementation of this interface can be registered with
 * OracleAS MapViewer to support a custom image format.
 */
public interface CustomImageRenderer
{
  /**
   * The method is called by OracleAS MapViewer to find out the image format
   * supported by this renderer. <br>
   * This format string must match the one specified in a custom image renderer
   * element defined in the configuration file (mapViewerConfig.xml).
   */
  public String  getSupportedFormat() ;

  /**
   * Renders the given images. OracleAS MapViewer calls this method
   * to tell the implementor the images to render, the current map
   * window in user space, and the MBR (in the same user space) for each
   * image.
   * <br>
   * The implementation should not retain any reference to the parameters
   * permanently.
   * @param g2  the graphics context to draw the images onto.
   * @param images  an array of image data stored in byte array.
   * @param mbrs an array of double[4] arrays containing one MBR for each
   *        image in the images array.
   * @param dataWindow the data space window covered by the current map.
   * @param deviceView the device size and offset.
   * @param at  the AffineTransform using which you can transform a point
   *            in the user data space to the device coordinate space. You can
   *            ignore this parameter if you opt to do the transformation
   *            yourself based on the dataWindow and deviceView information.
   * @param scaleImage a flag passed from OracleAS MapViewer to indicate whether
   *             the images should be scaled to fit the current device window.
   *             If it is set to false, render the image as-is without
   *             scaling it.
   */
  public void   renderImages(Graphics2D g2, byte[][] images, double[][] mbrs,
                             Rectangle2D dataWindow, Rectangle2D deviceView,
                             AffineTransform at, boolean scaleImage) ;
}

このインタフェースを実行した後、OracleAS MapViewerのCLASSPATH定義に含まれるディレクトリ($MAPVIEWER/web/WEB-INF/libディレクトリなど)に、実装クラスを格納する必要があります。実際のレンダリングの実行にネイティブ・ライブラリを使用する場合、これらのライブラリの他の必要なファイル(.dllファイルおよび.soファイルなど)が、OracleAS MapViewerが動作するJava Virtual Machine(JVM)で使用できることを確認する必要があります。

カスタム実装クラスおよび必要なライブラリをOracleAS MapViewerのCLASSPATHに格納した後、構成ファイルmapViewerConfig.xmlでクラスをOracleAS MapViewerに登録する必要があります(1.5.2項を参照)。このファイルの次の部分を適宜検査および編集します。このファイルは、まだサポートしていない特定の画像形式が出現した場合にロードするクラスを、OracleAS MapViewerに通知します。

  <!-- ****************************************************************** -->
  <!-- ******************** Custom Image Renderers ********************** -->
  <!-- ****************************************************************** -->
  <!-- Uncomment and add as many custom image renderers as needed here,
       each in its own  <custom_image_renderer> element. The "image_format"
       attribute specifies the format of images that are to be custom
       rendered using the class with the full name specified in "impl_class".
       You are responsible for placing the implementation classes in the
       OracleAS MapViewer classpath.
  -->
  <!--
  <custom_image_renderer image_format="ECW"
                         impl_class="com.my_corp.image.ECWRenderer"/>
  -->

この例では、イメージ・テーマの<jdbc_image_query>要素によってロードされるECW形式の画像データについてレンダリングを実行するために、OracleAS MapViewerによってcom.my_corp.image.ECWRendererクラスがロードされます。

例C-1は、oracle.sdovis.CustomImageRendererインタフェースの実装例です。この例では、ECW画像形式に対応したカスタム・レンダラを実装します。この例は、実例を示すことのみを目的としており、表示したコードは、システム環境によっては最適でないか間違っている可能性があるので注意してください。この実装ではECW Java SDKが使用され、ECW Java SDKでは付属のネイティブCライブラリが使用されます。OracleAS MapViewerでネイティブな動的ライブラリを検索できるようにするには、OracleAS MapViewerが含まれるOC4Jインスタンスを起動する際に、コマンドライン・オプション-Djava.library.pathを使用する必要があります。

例C-1 ECW画像形式に対応したカスタム・イメージ・レンダラ

package com.my_corp.image;
import java.io.*;
import java.util.Random;
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;

import oracle.sdovis.CustomImageRenderer;
import com.ermapper.ecw.JNCSFile; // from ECW Java SDK

public class ECWRenderer implements CustomImageRenderer
{
  String tempDir = null;
  Random random = null;

  public ECWRenderer()
  {
    tempDir = System.getProperty("java.io.tmpdir");
    random = new Random(System.currentTimeMillis());
  }

  public String  getSupportedFormat()
  {
    return "ECW";
  }

  public void   renderImages(Graphics2D g2, byte[][] images,
                             double[][] mbrs,
                             Rectangle2D dataWindow,
                             Rectangle2D deviceView,
                             AffineTransform at)
  {
    // Taking the easy way here; you should try to stitch the images
    // together here.
    for(int i=0; i<images.length; i++)
    {
      String tempFile = writeECWToFile(images[i]);
      paintECWFile(tempFile, g2, mbrs[i], dataWindow, deviceView,at);
    }
  }

  private String writeECWToFile(byte[] image)
  {
    long l = Math.abs(random.nextLong());
    String file = tempDir + "ecw"+l+".ecw";
    try{
      FileOutputStream fos = new FileOutputStream(file);
      fos.write(image);
      fos.close();
      return file;
    }catch(Exception e)
    {
      System.err.println("cannot write ecw bytes to temp file: "+file);
      return null;
    }
  }

  private void  paintECWFile(String fileName, Graphics2D g,
                             double[] mbr,
                             Rectangle2D dataWindow,
                             Rectangle2D deviceView,
                             AffineTransform at)
  {
    JNCSFile ecwFile = null;
    boolean bErrorOnOpen = false;
    BufferedImage ecwImage = null;
    String errorMessage = null;

    try {
      double dFileAspect, dWindowAspect;
      double dWorldTLX, dWorldTLY, dWorldBRX, dWorldBRY;
      int bandlist[];
      int width = (int)deviceView.getWidth(),
          height = (int)deviceView.getHeight();
      int line, pRGBArray[] = null;

      ecwFile = new JNCSFile(fileName, false);

      // Work out the correct aspect for the setView call.
      dFileAspect = (double)ecwFile.width/(double)ecwFile.height;
      dWindowAspect = deviceView.getWidth()/deviceView.getHeight();

      if (dFileAspect > dWindowAspect) {
        height =(int)((double)width/dFileAspect);
      } else {
        width = (int)((double)height*dFileAspect);
      }

      // Create an image of the ecw file.
      ecwImage = new BufferedImage(width, height,
                                   BufferedImage.TYPE_INT_RGB);
      pRGBArray = new int[width];

      // Set up the view parameters for the ecw file.
      bandlist = new int[ecwFile.numBands];
      for (int i=0; i< ecwFile.numBands; i++) {
        bandlist[i] = i;
      }
      dWorldTLX = ecwFile.originX;
      dWorldTLY = ecwFile.originY;
      dWorldBRX = ecwFile.originX +
                  (double)(ecwFile.width-1)*ecwFile.cellIncrementX;
      dWorldBRY = ecwFile.originY +
                  (double)(ecwFile.height-1)*ecwFile.cellIncrementY;

      dWorldTLX = Math.max(dWorldTLX, dataWindow.getMinX());
      dWorldTLY = Math.max(dWorldTLY, dataWindow.getMinY());
      dWorldBRX = Math.min(dWorldBRX, dataWindow.getMaxX());
      dWorldBRY = Math.min(dWorldBRY, dataWindow.getMaxY());

      // Set the view.
      ecwFile.setView(ecwFile.numBands, bandlist, dWorldTLX,
                      dWorldTLY, dWorldBRX, dWorldBRY, width, height);

      // Read the scan lines.
      for (line=0; line < height; line++) {
        ecwFile.readLineRGBA(pRGBArray);
        ecwImage.setRGB(0, line, width, 1, pRGBArray, 0, width);
      }

    } catch(Exception e) {
      e.printStackTrace(System.err);
      bErrorOnOpen = true;
      errorMessage = e.getMessage();
      g.drawString(errorMessage, 0, 50);
    }

    // Draw the image (unscaled) to the graphics context.
    if (!bErrorOnOpen) {
      g.drawImage(ecwImage, 0, 0, null);
    }

  }
}