private final WritableRaster createDCMraster() {
   WritableRaster wr;
   DirectColorModel dcm = (DirectColorModel) model;
   boolean hasAlpha = model.hasAlpha();
   int[] bandMasks = new int[3 + (hasAlpha ? 1 : 0)];
   bandMasks[0] = dcm.getRedMask();
   bandMasks[1] = dcm.getGreenMask();
   bandMasks[2] = dcm.getBlueMask();
   if (hasAlpha) {
     bandMasks[3] = dcm.getAlphaMask();
   }
   DataBufferInt db = new DataBufferInt(intPixels, width * height);
   wr = Raster.createPackedRaster(db, width, height, width, bandMasks, null);
   return wr;
 }
  // 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 static void main(String args[]) {
    ColorModel cm =
        new ColorModel(32) {
          public int getAlpha(int pixel) {
            return 255;
          }

          public int getBlue(int pixel) {
            return 255;
          }

          public int getGreen(int pixel) {
            return 255;
          }

          public int getRed(int pixel) {
            return 255;
          }
        };

    cm.hasAlpha();
    cm.isAlphaPremultiplied();
    cm.getTransferType();
    cm.getPixelSize();
    cm.getComponentSize();
    cm.getComponentSize();
    cm.getTransparency();
    cm.getNumComponents();
    cm.getNumColorComponents();
    cm.getRed(20);
    cm.getGreen(20);
    cm.getBlue(20);
    cm.getAlpha(20);
    cm.getRGB(20);
    cm.isAlphaPremultiplied();
    cm.isAlphaPremultiplied();

    cm = ColorModel.getRGBdefault();
  }
  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);
        }
    }
  }
  /**
   * {@collect.stats} Rescales the source BufferedImage. If the color model in the source image is
   * not the same as that in the destination image, the pixels will be converted in the destination.
   * If the destination image is null, a BufferedImage will be created with the source ColorModel.
   * An IllegalArgumentException may be thrown if the number of scaling factors/offsets in this
   * object does not meet the restrictions stated in the class comments above, or if the source
   * image has an IndexColorModel.
   *
   * @param src the <code>BufferedImage</code> to be filtered
   * @param dst the destination for the filtering operation or <code>null</code>
   * @return the filtered <code>BufferedImage</code>.
   * @throws IllegalArgumentException if the <code>ColorModel</code> of <code>src</code> is an
   *     <code>IndexColorModel</code>, or if the number of scaling factors and offsets in this
   *     <code>RescaleOp</code> do not meet the requirements stated in the class comments.
   */
  public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
    ColorModel srcCM = src.getColorModel();
    ColorModel dstCM;
    int numBands = srcCM.getNumColorComponents();

    if (srcCM instanceof IndexColorModel) {
      throw new IllegalArgumentException("Rescaling cannot be " + "performed on an indexed image");
    }
    if (length != 1 && length != numBands && length != srcCM.getNumComponents()) {
      throw new IllegalArgumentException(
          "Number of scaling constants "
              + "does not equal the number of"
              + " of color or color/alpha "
              + " components");
    }

    boolean needToConvert = false;

    // Include alpha
    if (length > numBands && srcCM.hasAlpha()) {
      length = numBands + 1;
    }

    int width = src.getWidth();
    int height = src.getHeight();

    if (dst == null) {
      dst = createCompatibleDestImage(src, null);
      dstCM = srcCM;
    } else {
      if (width != dst.getWidth()) {
        throw new IllegalArgumentException(
            "Src width (" + width + ") not equal to dst width (" + dst.getWidth() + ")");
      }
      if (height != dst.getHeight()) {
        throw new IllegalArgumentException(
            "Src height (" + height + ") not equal to dst height (" + dst.getHeight() + ")");
      }

      dstCM = dst.getColorModel();
      if (srcCM.getColorSpace().getType() != dstCM.getColorSpace().getType()) {
        needToConvert = true;
        dst = createCompatibleDestImage(src, null);
      }
    }

    BufferedImage origDst = dst;

    //
    // Try to use a native BI rescale operation first
    //
    if (ImagingLib.filter(this, src, dst) == null) {
      //
      // Native BI rescale failed - convert to rasters
      //
      WritableRaster srcRaster = src.getRaster();
      WritableRaster dstRaster = dst.getRaster();

      if (srcCM.hasAlpha()) {
        if (numBands - 1 == length || length == 1) {
          int minx = srcRaster.getMinX();
          int miny = srcRaster.getMinY();
          int[] bands = new int[numBands - 1];
          for (int i = 0; i < numBands - 1; i++) {
            bands[i] = i;
          }
          srcRaster =
              srcRaster.createWritableChild(
                  minx, miny, srcRaster.getWidth(), srcRaster.getHeight(), minx, miny, bands);
        }
      }
      if (dstCM.hasAlpha()) {
        int dstNumBands = dstRaster.getNumBands();
        if (dstNumBands - 1 == length || length == 1) {
          int minx = dstRaster.getMinX();
          int miny = dstRaster.getMinY();
          int[] bands = new int[numBands - 1];
          for (int i = 0; i < numBands - 1; i++) {
            bands[i] = i;
          }
          dstRaster =
              dstRaster.createWritableChild(
                  minx, miny, dstRaster.getWidth(), dstRaster.getHeight(), minx, miny, bands);
        }
      }

      //
      // Call the raster filter method
      //
      filter(srcRaster, dstRaster);
    }

    if (needToConvert) {
      // ColorModels are not the same
      ColorConvertOp ccop = new ColorConvertOp(hints);
      ccop.filter(dst, origDst);
    }

    return origDst;
  }