/**
   * Checks if the specified {@code SampleModel} is compatible with this {@code ColorModel}. If
   * {@code sm} is {@code null}, this method returns {@code false}.
   *
   * @param sm the specified {@code SampleModel}, or {@code null}
   * @return {@code true} if the specified {@code SampleModel} is compatible with this {@code
   *     ColorModel}; {@code false} otherwise.
   * @see SampleModel
   */
  public boolean isCompatibleSampleModel(SampleModel sm) {
    if (!(sm instanceof SinglePixelPackedSampleModel)) {
      return false;
    }

    // Must have the same number of components
    if (numComponents != sm.getNumBands()) {
      return false;
    }

    // Transfer type must be the same
    if (sm.getTransferType() != transferType) {
      return false;
    }

    SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm;
    // Now compare the specific masks
    int[] bitMasks = sppsm.getBitMasks();
    if (bitMasks.length != maskArray.length) {
      return false;
    }

    /* compare 'effective' masks only, i.e. only part of the mask
     * which fits the capacity of the transfer type.
     */
    int maxMask = (int) ((1L << DataBuffer.getDataTypeSize(transferType)) - 1);
    for (int i = 0; i < bitMasks.length; i++) {
      if ((maxMask & bitMasks[i]) != (maxMask & maskArray[i])) {
        return false;
      }
    }

    return true;
  }
Beispiel #2
0
 /**
  * Returns a width- and height-aligned image representation sharing data w/ {@link #image}.
  *
  * @param width
  * @param height
  * @return
  * @throws IllegalArgumentException if requested size exceeds image size
  */
 public BufferedImage getAlignedImage(int width, int height) throws IllegalArgumentException {
   if (width * height > image.getWidth() * image.getHeight()) {
     throw new IllegalArgumentException(
         "Requested size exceeds image size: "
             + width
             + "x"
             + height
             + " > "
             + image.getWidth()
             + "x"
             + image.getHeight());
   }
   if (width == image.getWidth() && height == image.getHeight()) {
     return image;
   } else {
     final ColorModel cm = image.getColorModel();
     final WritableRaster raster0 = image.getRaster();
     final DataBuffer dataBuffer = raster0.getDataBuffer();
     final SinglePixelPackedSampleModel sppsm0 =
         (SinglePixelPackedSampleModel) raster0.getSampleModel();
     final SinglePixelPackedSampleModel sppsm1 =
         new SinglePixelPackedSampleModel(
             dataBuffer.getDataType(),
             width,
             height,
             width /* scanLineStride */,
             sppsm0.getBitMasks());
     final WritableRaster raster1 = WritableRaster.createWritableRaster(sppsm1, dataBuffer, null);
     return new BufferedImage(cm, raster1, cm.isAlphaPremultiplied(), null);
   }
 }
Beispiel #3
0
  protected static void mult_INT_PACK_Data(WritableRaster wr) {
    // System.out.println("Multiply Int: " + wr);

    SinglePixelPackedSampleModel sppsm;
    sppsm = (SinglePixelPackedSampleModel) wr.getSampleModel();

    final int width = wr.getWidth();

    final int scanStride = sppsm.getScanlineStride();
    DataBufferInt db = (DataBufferInt) wr.getDataBuffer();
    final int base =
        (db.getOffset()
            + sppsm.getOffset(
                wr.getMinX() - wr.getSampleModelTranslateX(),
                wr.getMinY() - wr.getSampleModelTranslateY()));
    // Access the pixel data array
    final int pixels[] = db.getBankData()[0];
    for (int y = 0; y < wr.getHeight(); y++) {
      int sp = base + y * scanStride;
      final int end = sp + width;
      while (sp < end) {
        int pixel = pixels[sp];
        int a = pixel >>> 24;
        if ((a >= 0) && (a < 255)) {
          pixels[sp] =
              ((a << 24)
                  | ((((pixel & 0xFF0000) * a) >> 8) & 0xFF0000)
                  | ((((pixel & 0x00FF00) * a) >> 8) & 0x00FF00)
                  | ((((pixel & 0x0000FF) * a) >> 8) & 0x0000FF));
        }
        sp++;
      }
    }
  }
 /**
  * Encode the uncompressed source image stored in <code>srcImage</code> and output a YUV planar
  * image to the given destination buffer. See {@link #encodeYUV(byte[], int)} for more detail.
  *
  * @param srcImage a <code>BufferedImage</code> instance containing RGB or grayscale pixels to be
  *     encoded
  * @param dstBuf buffer that will receive the YUV planar image. Use {@link TJ#bufSizeYUV} to
  *     determine the appropriate size for this buffer based on the image width, height, and level
  *     of chrominance subsampling.
  * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
  */
 public void encodeYUV(BufferedImage srcImage, byte[] dstBuf, int flags) throws Exception {
   if (srcImage == null || dstBuf == null || flags < 0)
     throw new Exception("Invalid argument in encodeYUV()");
   int width = srcImage.getWidth();
   int height = srcImage.getHeight();
   int pixelFormat;
   boolean intPixels = false;
   if (byteOrder == null) byteOrder = ByteOrder.nativeOrder();
   switch (srcImage.getType()) {
     case BufferedImage.TYPE_3BYTE_BGR:
       pixelFormat = TJ.PF_BGR;
       break;
     case BufferedImage.TYPE_4BYTE_ABGR:
     case BufferedImage.TYPE_4BYTE_ABGR_PRE:
       pixelFormat = TJ.PF_XBGR;
       break;
     case BufferedImage.TYPE_BYTE_GRAY:
       pixelFormat = TJ.PF_GRAY;
       break;
     case BufferedImage.TYPE_INT_BGR:
       if (byteOrder == ByteOrder.BIG_ENDIAN) pixelFormat = TJ.PF_XBGR;
       else pixelFormat = TJ.PF_RGBX;
       intPixels = true;
       break;
     case BufferedImage.TYPE_INT_RGB:
     case BufferedImage.TYPE_INT_ARGB:
     case BufferedImage.TYPE_INT_ARGB_PRE:
       if (byteOrder == ByteOrder.BIG_ENDIAN) pixelFormat = TJ.PF_XRGB;
       else pixelFormat = TJ.PF_BGRX;
       intPixels = true;
       break;
     default:
       throw new Exception("Unsupported BufferedImage format");
   }
   WritableRaster wr = srcImage.getRaster();
   if (subsamp < 0) throw new Exception("Subsampling level not set");
   if (intPixels) {
     SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel) srcImage.getSampleModel();
     int pitch = sm.getScanlineStride();
     DataBufferInt db = (DataBufferInt) wr.getDataBuffer();
     int[] buf = db.getData();
     encodeYUV(buf, width, pitch, height, pixelFormat, dstBuf, subsamp, flags);
   } else {
     ComponentSampleModel sm = (ComponentSampleModel) srcImage.getSampleModel();
     int pixelSize = sm.getPixelStride();
     if (pixelSize != TJ.getPixelSize(pixelFormat))
       throw new Exception("Inconsistency between pixel format and pixel size in BufferedImage");
     int pitch = sm.getScanlineStride();
     DataBufferByte db = (DataBufferByte) wr.getDataBuffer();
     byte[] buf = db.getData();
     encodeYUV(buf, width, pitch, height, pixelFormat, dstBuf, subsamp, flags);
   }
   compressedSize = TJ.bufSizeYUV(width, height, subsamp);
 }
  private void writeSinglePixelPackedSampleModel(DataOutput out, SinglePixelPackedSampleModel model)
      throws IOException {

    int[] masks = model.getBitMasks();
    out.writeInt(masks.length);
    for (int i = 0; i < masks.length; i++) out.writeInt(masks[i]);

    out.writeInt(model.getDataType());
    out.writeInt(model.getWidth());
    out.writeInt(model.getHeight());
    out.writeInt(model.getScanlineStride());
  }
  /**
   * Constructs a IntegerComponentRaster with the given SampleModel, DataBuffer, and parent.
   * DataBuffer must be a DataBufferInt and SampleModel must be of type
   * SinglePixelPackedSampleModel. When translated into the base Raster's coordinate system, aRegion
   * must be contained by the base Raster. Origin is the coodinate in the new Raster's coordinate
   * system of the origin of the base Raster. (The base Raster is the Raster's ancestor which has no
   * parent.)
   *
   * <p>Note that this constructor should generally be called by other constructors or create
   * methods, it should not be used directly.
   *
   * @param sampleModel The SampleModel that specifies the layout.
   * @param dataBuffer The DataBufferInt that contains the image data.
   * @param aRegion The Rectangle that specifies the image area.
   * @param origin The Point that specifies the origin.
   * @param parent The parent (if any) of this raster.
   */
  public IntegerComponentRaster(
      SampleModel sampleModel,
      DataBuffer dataBuffer,
      Rectangle aRegion,
      Point origin,
      IntegerComponentRaster parent) {
    super(sampleModel, dataBuffer, aRegion, origin, parent);
    this.maxX = minX + width;
    this.maxY = minY + height;
    if (!(dataBuffer instanceof DataBufferInt)) {
      throw new RasterFormatException("IntegerComponentRasters must have" + "integer DataBuffers");
    }
    DataBufferInt dbi = (DataBufferInt) dataBuffer;
    if (dbi.getNumBanks() != 1) {
      throw new RasterFormatException(
          "DataBuffer for IntegerComponentRasters" + " must only have 1 bank.");
    }
    this.data = stealData(dbi, 0);

    if (sampleModel instanceof SinglePixelPackedSampleModel) {
      SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sampleModel;
      int[] boffsets = sppsm.getBitOffsets();
      boolean notByteBoundary = false;
      for (int i = 1; i < boffsets.length; i++) {
        if ((boffsets[i] % 8) != 0) {
          notByteBoundary = true;
        }
      }
      this.type =
          (notByteBoundary
              ? IntegerComponentRaster.TYPE_INT_PACKED_SAMPLES
              : IntegerComponentRaster.TYPE_INT_8BIT_SAMPLES);

      this.scanlineStride = sppsm.getScanlineStride();
      this.pixelStride = 1;
      this.dataOffsets = new int[1];
      this.dataOffsets[0] = dbi.getOffset();
      this.bandOffset = this.dataOffsets[0];
      int xOffset = aRegion.x - origin.x;
      int yOffset = aRegion.y - origin.y;
      dataOffsets[0] += xOffset + yOffset * scanlineStride;
      this.numDataElems = sppsm.getNumDataElements();
    } else {
      throw new RasterFormatException(
          "IntegerComponentRasters must have" + " SinglePixelPackedSampleModel");
    }

    verify();
  }
Beispiel #7
0
    public ZeroRecter_INT_PACK(WritableRaster wr) {
      super(wr);

      SinglePixelPackedSampleModel sppsm;
      sppsm = (SinglePixelPackedSampleModel) wr.getSampleModel();

      scanStride = sppsm.getScanlineStride();
      DataBufferInt db = (DataBufferInt) wr.getDataBuffer();
      x0 = wr.getMinY();
      y0 = wr.getMinX();
      base =
          (db.getOffset()
              + sppsm.getOffset(
                  x0 - wr.getSampleModelTranslateX(), y0 - wr.getSampleModelTranslateY()));

      pixels = db.getBankData()[0];
      if (wr.getWidth() > 10) zeros = new int[wr.getWidth()];
      else zeros = null;
    }
Beispiel #8
0
 private static void initImg(BufferedImage img, int pf, int flags) throws Exception {
   WritableRaster wr = img.getRaster();
   int imgType = img.getType();
   if (imgType == BufferedImage.TYPE_INT_RGB
       || imgType == BufferedImage.TYPE_INT_BGR
       || imgType == BufferedImage.TYPE_INT_ARGB
       || imgType == BufferedImage.TYPE_INT_ARGB_PRE) {
     SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel) img.getSampleModel();
     int pitch = sm.getScanlineStride();
     DataBufferInt db = (DataBufferInt) wr.getDataBuffer();
     int[] buf = db.getData();
     initIntBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
   } else {
     ComponentSampleModel sm = (ComponentSampleModel) img.getSampleModel();
     int pitch = sm.getScanlineStride();
     DataBufferByte db = (DataBufferByte) wr.getDataBuffer();
     byte[] buf = db.getData();
     initBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
   }
 }
Beispiel #9
0
  public static boolean is_INT_PACK_Data(SampleModel sm, boolean requireAlpha) {
    // Check ColorModel is of type DirectColorModel
    if (!(sm instanceof SinglePixelPackedSampleModel)) return false;

    // Check transfer type
    if (sm.getDataType() != DataBuffer.TYPE_INT) return false;

    SinglePixelPackedSampleModel sppsm;
    sppsm = (SinglePixelPackedSampleModel) sm;

    int[] masks = sppsm.getBitMasks();
    if (masks.length == 3) {
      if (requireAlpha) return false;
    } else if (masks.length != 4) return false;

    if (masks[0] != 0x00ff0000) return false;
    if (masks[1] != 0x0000ff00) return false;
    if (masks[2] != 0x000000ff) return false;
    return !((masks.length == 4) && (masks[3] != 0xff000000));
  }
Beispiel #10
0
  protected static void divide_INT_PACK_Data(WritableRaster wr) {
    // System.out.println("Divide Int");

    SinglePixelPackedSampleModel sppsm;
    sppsm = (SinglePixelPackedSampleModel) wr.getSampleModel();

    final int width = wr.getWidth();

    final int scanStride = sppsm.getScanlineStride();
    DataBufferInt db = (DataBufferInt) wr.getDataBuffer();
    final int base =
        (db.getOffset()
            + sppsm.getOffset(
                wr.getMinX() - wr.getSampleModelTranslateX(),
                wr.getMinY() - wr.getSampleModelTranslateY()));
    int pixel, a, aFP;
    // Access the pixel data array
    final int pixels[] = db.getBankData()[0];
    for (int y = 0; y < wr.getHeight(); y++) {
      int sp = base + y * scanStride;
      final int end = sp + width;
      while (sp < end) {
        pixel = pixels[sp];
        a = pixel >>> 24;
        if (a <= 0) {
          pixels[sp] = 0x00FFFFFF;
        } else if (a < 255) {
          aFP = (0x00FF0000 / a);
          pixels[sp] =
              ((a << 24)
                  | (((((pixel & 0xFF0000) >> 16) * aFP) & 0xFF0000))
                  | (((((pixel & 0x00FF00) >> 8) * aFP) & 0xFF0000) >> 8)
                  | (((((pixel & 0x0000FF)) * aFP) & 0xFF0000) >> 16));
        }
        sp++;
      }
    }
  }
  /**
   * Ipp filter.
   *
   * @param src the src.
   * @param dst the dst.
   * @param imageType the image type.
   * @return the int.
   */
  @SuppressWarnings("unused")
  private int ippFilter(Raster src, WritableRaster dst, int imageType) {
    int srcStride, dstStride;
    boolean skipChannel = false;
    int channels;
    int offsets[] = null;

    switch (imageType) {
      case BufferedImage.TYPE_INT_RGB:
      case BufferedImage.TYPE_INT_BGR:
        {
          channels = 4;
          srcStride = src.getWidth() * 4;
          dstStride = dst.getWidth() * 4;
          skipChannel = true;
          break;
        }

      case BufferedImage.TYPE_INT_ARGB:
      case BufferedImage.TYPE_INT_ARGB_PRE:
      case BufferedImage.TYPE_4BYTE_ABGR:
      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
        {
          channels = 4;
          srcStride = src.getWidth() * 4;
          dstStride = dst.getWidth() * 4;
          break;
        }

      case BufferedImage.TYPE_BYTE_GRAY:
      case BufferedImage.TYPE_BYTE_INDEXED:
        {
          channels = 1;
          srcStride = src.getWidth();
          dstStride = dst.getWidth();
          break;
        }

      case BufferedImage.TYPE_3BYTE_BGR:
        {
          channels = 3;
          srcStride = src.getWidth() * 3;
          dstStride = dst.getWidth() * 3;
          break;
        }

      case BufferedImage.TYPE_USHORT_GRAY: // TODO - could be done in
        // native code?
      case BufferedImage.TYPE_USHORT_565_RGB:
      case BufferedImage.TYPE_USHORT_555_RGB:
      case BufferedImage.TYPE_BYTE_BINARY:
        {
          return slowFilter(src, dst);
        }

      default:
        {
          SampleModel srcSM = src.getSampleModel();
          SampleModel dstSM = dst.getSampleModel();

          if (srcSM instanceof PixelInterleavedSampleModel
              && dstSM instanceof PixelInterleavedSampleModel) {
            // Check PixelInterleavedSampleModel
            if (srcSM.getDataType() != DataBuffer.TYPE_BYTE
                || dstSM.getDataType() != DataBuffer.TYPE_BYTE) {
              return slowFilter(src, dst);
            }

            channels = srcSM.getNumBands(); // Have IPP functions for 1,
            // 3 and 4 channels
            if (channels != 1 && channels != 3 && channels != 4) {
              return slowFilter(src, dst);
            }

            int dataTypeSize = DataBuffer.getDataTypeSize(srcSM.getDataType()) / 8;

            srcStride = ((ComponentSampleModel) srcSM).getScanlineStride() * dataTypeSize;
            dstStride = ((ComponentSampleModel) dstSM).getScanlineStride() * dataTypeSize;
          } else if (srcSM instanceof SinglePixelPackedSampleModel
              && dstSM instanceof SinglePixelPackedSampleModel) {
            // Check SinglePixelPackedSampleModel
            SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM;
            SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM;

            // No IPP function for this type
            if (sppsm1.getDataType() == DataBuffer.TYPE_USHORT) {
              return slowFilter(src, dst);
            }

            channels = sppsm1.getNumBands();
            // Have IPP functions for 1, 3 and 4 channels
            if (channels != 1 && channels != 3 && channels != 4) {
              return slowFilter(src, dst);
            }

            // Check compatibility of sample models
            if (sppsm1.getDataType() != sppsm2.getDataType()
                || !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets())
                || !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())) {
              return slowFilter(src, dst);
            }

            for (int i = 0; i < channels; i++) {
              if (sppsm1.getSampleSize(i) != 8) {
                return slowFilter(src, dst);
              }
            }

            if (channels == 3) {
              channels = 4;
            }

            int dataTypeSize = DataBuffer.getDataTypeSize(sppsm1.getDataType()) / 8;

            srcStride = sppsm1.getScanlineStride() * dataTypeSize;
            dstStride = sppsm2.getScanlineStride() * dataTypeSize;
          } else {
            return slowFilter(src, dst);
          }

          // Fill offsets if there's a child raster
          if (src.getParent() != null || dst.getParent() != null) {
            if (src.getSampleModelTranslateX() != 0
                || src.getSampleModelTranslateY() != 0
                || dst.getSampleModelTranslateX() != 0
                || dst.getSampleModelTranslateY() != 0) {
              offsets = new int[4];
              offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
              offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
              offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
              offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
            }
          }
        }
    }

    double m00 = at.getScaleX();
    double m01 = at.getShearX();
    double m02 = at.getTranslateX();
    double m10 = at.getShearY();
    double m11 = at.getScaleY();
    double m12 = at.getTranslateY();

    Object srcData, dstData;
    AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
    try {
      srcData = dbAccess.getData(src.getDataBuffer());
      dstData = dbAccess.getData(dst.getDataBuffer());
    } catch (IllegalArgumentException e) {
      return -1; // Unknown data buffer type
    }

    return ippAffineTransform(
        m00,
        m01,
        m02,
        m10,
        m11,
        m12,
        srcData,
        src.getWidth(),
        src.getHeight(),
        srcStride,
        dstData,
        dst.getWidth(),
        dst.getHeight(),
        dstStride,
        iType,
        channels,
        skipChannel,
        offsets);
  }
Beispiel #12
0
  private WritableRaster boxFilterV(
      Raster src, WritableRaster dest, int skipX, int skipY, int boxSz, int loc) {

    final int w = src.getWidth();
    final int h = src.getHeight();

    // Check if the raster is wide enough to do _any_ work
    if (w < (2 * skipX)) return dest;
    if (h < (2 * skipY) + boxSz) return dest;

    final SinglePixelPackedSampleModel srcSPPSM =
        (SinglePixelPackedSampleModel) src.getSampleModel();

    final SinglePixelPackedSampleModel dstSPPSM =
        (SinglePixelPackedSampleModel) dest.getSampleModel();

    // Stride is the distance between two consecutive column elements,
    // in the one-dimention dataBuffer
    final int srcScanStride = srcSPPSM.getScanlineStride();
    final int dstScanStride = dstSPPSM.getScanlineStride();

    // Access the integer buffer for each image.
    DataBufferInt srcDB = (DataBufferInt) src.getDataBuffer();
    DataBufferInt dstDB = (DataBufferInt) dest.getDataBuffer();

    // Offset defines where in the stack the real data begin
    final int srcOff =
        (srcDB.getOffset()
            + srcSPPSM.getOffset(
                src.getMinX() - src.getSampleModelTranslateX(),
                src.getMinY() - src.getSampleModelTranslateY()));
    final int dstOff =
        (dstDB.getOffset()
            + dstSPPSM.getOffset(
                dest.getMinX() - dest.getSampleModelTranslateX(),
                dest.getMinY() - dest.getSampleModelTranslateY()));

    // Access the pixel value array
    final int[] srcPixels = srcDB.getBankData()[0];
    final int[] destPixels = dstDB.getBankData()[0];

    final int[] buffer = new int[boxSz];
    int curr, prev;

    // Fixed point normalization factor (8.24)
    final int scale = (1 << 24) / boxSz;

    /*
     * System.out.println("Info: srcOff: " + srcOff +
     *                    " x: " + skipX +
     *                    " y: " + skipY +
     *                    " w: " + w +
     *                    " h: " + h +
     *                    " boxSz " + boxSz +
     *                    " srcStride: " + srcScanStride);
     */

    for (int x = skipX; x < (w - skipX); x++) {
      int sp = srcOff + x;
      int dp = dstOff + x;
      int colEnd = sp + (h - skipY) * srcScanStride;

      int k = 0;
      int sumA = 0;
      int sumR = 0;
      int sumG = 0;
      int sumB = 0;

      sp += skipY * srcScanStride;
      int end = sp + (boxSz * srcScanStride);

      while (sp < end) {
        curr = buffer[k] = srcPixels[sp];
        sumA += (curr >>> 24);
        sumR += (curr >> 16) & 0xFF;
        sumG += (curr >> 8) & 0xFF;
        sumB += (curr) & 0xFF;
        k++;
        sp += srcScanStride;
      }

      dp += (skipY + loc) * dstScanStride;
      prev =
          destPixels[dp] =
              (((sumA * scale) & 0xFF000000)
                  | (((sumR * scale) & 0xFF000000) >>> 8)
                  | (((sumG * scale) & 0xFF000000) >>> 16)
                  | (((sumB * scale) & 0xFF000000) >>> 24));
      dp += dstScanStride;
      k = 0;
      while (sp < colEnd) {
        curr = buffer[k];
        if (curr == srcPixels[sp]) {
          destPixels[dp] = prev;
        } else {
          sumA -= (curr >>> 24);
          sumR -= (curr >> 16) & 0xFF;
          sumG -= (curr >> 8) & 0xFF;
          sumB -= (curr) & 0xFF;

          curr = buffer[k] = srcPixels[sp];

          sumA += (curr >>> 24);
          sumR += (curr >> 16) & 0xFF;
          sumG += (curr >> 8) & 0xFF;
          sumB += (curr) & 0xFF;
          prev =
              destPixels[dp] =
                  (((sumA * scale) & 0xFF000000)
                      | (((sumR * scale) & 0xFF000000) >>> 8)
                      | (((sumG * scale) & 0xFF000000) >>> 16)
                      | (((sumB * scale) & 0xFF000000) >>> 24));
        }
        k = (k + 1) % boxSz;
        sp += srcScanStride;
        dp += dstScanStride;
      }
    }
    return dest;
  }
  public WritableRaster copyData(WritableRaster wr) {
    // Get my source.
    CachableRed src = (CachableRed) getSources().get(0);
    ColorModel srcCM = src.getColorModel();
    SampleModel srcSM = src.getSampleModel();

    // Fast case, SRGB source, INT Pack writable raster...
    if (srcIssRGB && Any2sRGBRed.is_INT_PACK_COMP(wr.getSampleModel())) {
      src.copyData(wr);
      if (srcCM.hasAlpha()) GraphicsUtil.coerceData(wr, srcCM, false);
      Any2sRGBRed.applyLut_INT(wr, sRGBToLsRGBLut);
      return wr;
    }

    if (srcCM == null) {
      // We don't really know much about this source, let's
      // guess based on the number of bands...

      float[][] matrix = null;
      switch (srcSM.getNumBands()) {
        case 1:
          matrix = new float[1][3];
          matrix[0][0] = 1; // Red
          matrix[0][1] = 1; // Grn
          matrix[0][2] = 1; // Blu
          break;
        case 2:
          matrix = new float[2][4];
          matrix[0][0] = 1; // Red
          matrix[0][1] = 1; // Grn
          matrix[0][2] = 1; // Blu
          matrix[1][3] = 1; // Alpha
          break;
        case 3:
          matrix = new float[3][3];
          matrix[0][0] = 1; // Red
          matrix[1][1] = 1; // Grn
          matrix[2][2] = 1; // Blu
          break;
        default:
          matrix = new float[srcSM.getNumBands()][4];
          matrix[0][0] = 1; // Red
          matrix[1][1] = 1; // Grn
          matrix[2][2] = 1; // Blu
          matrix[3][3] = 1; // Alpha
          break;
      }

      Raster srcRas = src.getData(wr.getBounds());
      BandCombineOp op = new BandCombineOp(matrix, null);
      op.filter(srcRas, wr);
    } else {
      ColorModel dstCM = getColorModel();
      BufferedImage dstBI;

      if (!dstCM.hasAlpha()) {
        // No alpha ao we don't have to work around the bug
        // in the color convert op.
        dstBI =
            new BufferedImage(
                dstCM, wr.createWritableTranslatedChild(0, 0), dstCM.isAlphaPremultiplied(), null);
      } else {
        // All this nonsense is to work around the fact that
        // the Color convert op doesn't properly copy the
        // Alpha from src to dst.
        SinglePixelPackedSampleModel dstSM;
        dstSM = (SinglePixelPackedSampleModel) wr.getSampleModel();
        int[] masks = dstSM.getBitMasks();
        SampleModel dstSMNoA =
            new SinglePixelPackedSampleModel(
                dstSM.getDataType(),
                dstSM.getWidth(),
                dstSM.getHeight(),
                dstSM.getScanlineStride(),
                new int[] {masks[0], masks[1], masks[2]});
        ColorModel dstCMNoA = GraphicsUtil.Linear_sRGB;

        WritableRaster dstWr;
        dstWr = Raster.createWritableRaster(dstSMNoA, wr.getDataBuffer(), new Point(0, 0));
        dstWr =
            dstWr.createWritableChild(
                wr.getMinX() - wr.getSampleModelTranslateX(),
                wr.getMinY() - wr.getSampleModelTranslateY(),
                wr.getWidth(),
                wr.getHeight(),
                0,
                0,
                null);

        dstBI = new BufferedImage(dstCMNoA, dstWr, false, null);
      }

      // Divide out alpha if we have it.  We need to do this since
      // the color convert may not be a linear operation which may
      // lead to out of range values.
      ColorModel srcBICM = srcCM;
      WritableRaster srcWr;
      if ((srcCM.hasAlpha() == true) && (srcCM.isAlphaPremultiplied() != false)) {
        Rectangle wrR = wr.getBounds();
        SampleModel sm = srcCM.createCompatibleSampleModel(wrR.width, wrR.height);

        srcWr = Raster.createWritableRaster(sm, new Point(wrR.x, wrR.y));
        src.copyData(srcWr);
        srcBICM = GraphicsUtil.coerceData(srcWr, srcCM, false);
      } else {
        Raster srcRas = src.getData(wr.getBounds());
        srcWr = GraphicsUtil.makeRasterWritable(srcRas);
      }

      BufferedImage srcBI;
      srcBI = new BufferedImage(srcBICM, srcWr.createWritableTranslatedChild(0, 0), false, null);

      /*
       * System.out.println("src: " + srcBI.getWidth() + "x" +
       *                    srcBI.getHeight());
       * System.out.println("dst: " + dstBI.getWidth() + "x" +
       *                    dstBI.getHeight());
       */

      ColorConvertOp op = new ColorConvertOp(null);
      op.filter(srcBI, dstBI);

      if (dstCM.hasAlpha())
        copyBand(
            srcWr, srcSM.getNumBands() - 1,
            wr, getSampleModel().getNumBands() - 1);
    }
    return wr;
  }
 /**
  * Decompress the JPEG source image associated with this decompressor instance and output a
  * decompressed image to the given <code>BufferedImage</code> instance.
  *
  * @param dstImage a <code>BufferedImage</code> instance that will receive the decompressed image
  * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
  */
 public void decompress(BufferedImage dstImage, int flags) throws Exception {
   if (dstImage == null || flags < 0) throw new Exception("Invalid argument in decompress()");
   int desiredWidth = dstImage.getWidth();
   int desiredHeight = dstImage.getHeight();
   int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
   int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
   if (scaledWidth != desiredWidth || scaledHeight != desiredHeight)
     throw new Exception(
         "BufferedImage dimensions do not match a scaled image size that TurboJPEG is capable of generating.");
   int pixelFormat;
   boolean intPixels = false;
   if (byteOrder == null) byteOrder = ByteOrder.nativeOrder();
   switch (dstImage.getType()) {
     case BufferedImage.TYPE_3BYTE_BGR:
       pixelFormat = TJ.PF_BGR;
       break;
     case BufferedImage.TYPE_4BYTE_ABGR:
     case BufferedImage.TYPE_4BYTE_ABGR_PRE:
       pixelFormat = TJ.PF_XBGR;
       break;
     case BufferedImage.TYPE_BYTE_GRAY:
       pixelFormat = TJ.PF_GRAY;
       break;
     case BufferedImage.TYPE_INT_BGR:
       if (byteOrder == ByteOrder.BIG_ENDIAN) pixelFormat = TJ.PF_XBGR;
       else pixelFormat = TJ.PF_RGBX;
       intPixels = true;
       break;
     case BufferedImage.TYPE_INT_RGB:
       if (byteOrder == ByteOrder.BIG_ENDIAN) pixelFormat = TJ.PF_XRGB;
       else pixelFormat = TJ.PF_BGRX;
       intPixels = true;
       break;
     case BufferedImage.TYPE_INT_ARGB:
     case BufferedImage.TYPE_INT_ARGB_PRE:
       if (byteOrder == ByteOrder.BIG_ENDIAN) pixelFormat = TJ.PF_ARGB;
       else pixelFormat = TJ.PF_BGRA;
       intPixels = true;
       break;
     default:
       throw new Exception("Unsupported BufferedImage format");
   }
   WritableRaster wr = dstImage.getRaster();
   if (intPixels) {
     SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel) dstImage.getSampleModel();
     int stride = sm.getScanlineStride();
     DataBufferInt db = (DataBufferInt) wr.getDataBuffer();
     int[] buf = db.getData();
     if (jpegBuf == null) throw new Exception(NO_ASSOC_ERROR);
     decompress(jpegBuf, jpegBufSize, buf, scaledWidth, stride, scaledHeight, pixelFormat, flags);
   } else {
     ComponentSampleModel sm = (ComponentSampleModel) dstImage.getSampleModel();
     int pixelSize = sm.getPixelStride();
     if (pixelSize != TJ.getPixelSize(pixelFormat))
       throw new Exception("Inconsistency between pixel format and pixel size in BufferedImage");
     int pitch = sm.getScanlineStride();
     DataBufferByte db = (DataBufferByte) wr.getDataBuffer();
     byte[] buf = db.getData();
     decompress(buf, scaledWidth, pitch, scaledHeight, pixelFormat, flags);
   }
 }