// This method returns true if the specified image has transparent pixels
  // Source: http://www.exampledepot.com/egs/java.awt.image/HasAlpha.html
  public static boolean hasAlpha(Image image) {
    // If buffered image, the color model is readily available
    if (image instanceof BufferedImage) {
      BufferedImage bimage = (BufferedImage) image;
      return bimage.getColorModel().hasAlpha();
    }

    // Use a pixel grabber to retrieve the image's color model;
    // grabbing a single pixel is usually sufficient
    PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
    try {
      pg.grabPixels();
    } catch (InterruptedException e) {
    }

    // Get the image's color model
    ColorModel cm = pg.getColorModel();
    return cm.hasAlpha();
  }
  public void write(BufferedImage image, AVList params) throws IOException {
    if (image == null) {
      String msg = Logging.getMessage("nullValue.ImageSource");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    if (0 == image.getWidth() || 0 == image.getHeight()) {
      String msg =
          Logging.getMessage("generic.InvalidImageSize", image.getWidth(), image.getHeight());
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    if (null == params || 0 == params.getValues().size()) {
      String reason = Logging.getMessage("nullValue.AVListIsNull");
      Logging.logger().finest(Logging.getMessage("GeotiffWriter.GeoKeysMissing", reason));
      params = new AVListImpl();
    } else {
      this.validateParameters(params, image.getWidth(), image.getHeight());
    }

    // how we proceed in part depends upon the image type...
    int type = image.getType();

    // handle CUSTOM type which comes from our GeoTiffreader (for now)
    if (BufferedImage.TYPE_CUSTOM == type) {
      int numColorComponents = 0, numComponents = 0, pixelSize = 0, dataType = 0, csType = 0;
      boolean hasAlpha = false;

      if (null != image.getColorModel()) {
        ColorModel cm = image.getColorModel();

        numColorComponents = cm.getNumColorComponents();
        numComponents = cm.getNumComponents();
        pixelSize = cm.getPixelSize();
        hasAlpha = cm.hasAlpha();

        ColorSpace cs = cm.getColorSpace();
        if (null != cs) csType = cs.getType();
      }

      if (null != image.getSampleModel()) {
        SampleModel sm = image.getSampleModel();
        dataType = sm.getDataType();
      }

      if (dataType == DataBuffer.TYPE_FLOAT && pixelSize == Float.SIZE && numComponents == 1) {
        type = BufferedImage_TYPE_ELEVATION_FLOAT32;
      } else if (dataType == DataBuffer.TYPE_SHORT
          && pixelSize == Short.SIZE
          && numComponents == 1) {
        type = BufferedImage_TYPE_ELEVATION_SHORT16;
      } else if (ColorSpace.CS_GRAY == csType && pixelSize == Byte.SIZE) {
        type = BufferedImage.TYPE_BYTE_GRAY;
      } else if (dataType == DataBuffer.TYPE_USHORT
          && ColorSpace.CS_GRAY == csType
          && pixelSize == Short.SIZE) {
        type = BufferedImage.TYPE_USHORT_GRAY;
      } else if (ColorSpace.TYPE_RGB == csType
          && pixelSize == 3 * Byte.SIZE
          && numColorComponents == 3) {
        type = BufferedImage.TYPE_3BYTE_BGR;
      } else if (ColorSpace.TYPE_RGB == csType
          && hasAlpha
          && pixelSize == 4 * Byte.SIZE
          && numComponents == 4) {
        type = BufferedImage.TYPE_4BYTE_ABGR;
      }
    }

    switch (type) {
      case BufferedImage.TYPE_3BYTE_BGR:
      case BufferedImage.TYPE_4BYTE_ABGR:
      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
      case BufferedImage.TYPE_INT_RGB:
      case BufferedImage.TYPE_INT_BGR:
      case BufferedImage.TYPE_INT_ARGB:
      case BufferedImage.TYPE_INT_ARGB_PRE:
        {
          this.writeColorImage(image, params);
        }
        break;

      case BufferedImage.TYPE_USHORT_GRAY:
      case BufferedImage.TYPE_BYTE_GRAY:
        {
          this.writeGrayscaleImage(image, params);
        }
        break;

      case BufferedImage_TYPE_ELEVATION_SHORT16:
      case BufferedImage_TYPE_ELEVATION_FLOAT32:
        {
          String msg = Logging.getMessage("GeotiffWriter.FeatureNotImplementedd", type);
          Logging.logger().severe(msg);
          throw new IllegalArgumentException(msg);
        }
        //            break;

      case BufferedImage.TYPE_CUSTOM:
      default:
        {
          ColorModel cm = image.getColorModel();
          SampleModel sm = image.getSampleModel();

          StringBuffer sb =
              new StringBuffer(Logging.getMessage("GeotiffWriter.UnsupportedType", type));

          sb.append("\n");
          sb.append("NumBands=").append(sm.getNumBands()).append("\n");
          sb.append("NumDataElements=").append(sm.getNumDataElements()).append("\n");
          sb.append("NumColorComponents=").append(cm.getNumColorComponents()).append("\n");
          sb.append("NumComponents=").append(cm.getNumComponents()).append("\n");
          sb.append("PixelSize=").append(cm.getPixelSize()).append("\n");
          sb.append("hasAlpha=").append(cm.hasAlpha());

          String msg = sb.toString();
          Logging.logger().severe(msg);
          throw new IllegalArgumentException(msg);
        }
    }
  }