public WritableRaster INT_PACK_BYTE_COMP_Impl(WritableRaster wr) {
    // Get my source.
    CachableRed srcRed = (CachableRed) getSources().get(0);
    CachableRed alphaRed = (CachableRed) getSources().get(1);

    // Already has alpha channel so we use it.
    srcRed.copyData(wr);

    Rectangle rgn = wr.getBounds();
    rgn = rgn.intersection(alphaRed.getBounds());

    Raster r = alphaRed.getData(rgn);

    ComponentSampleModel csm;
    csm = (ComponentSampleModel) r.getSampleModel();
    final int alpScanStride = csm.getScanlineStride();

    DataBufferByte alpDB = (DataBufferByte) r.getDataBuffer();
    final int alpBase =
        (alpDB.getOffset()
            + csm.getOffset(
                rgn.x - r.getSampleModelTranslateX(), rgn.y - r.getSampleModelTranslateY()));

    // Access the pixel data array
    final byte[] alpPixels = alpDB.getBankData()[0];

    SinglePixelPackedSampleModel sppsm;
    sppsm = (SinglePixelPackedSampleModel) wr.getSampleModel();
    final int srcScanStride = sppsm.getScanlineStride();

    DataBufferInt srcDB = (DataBufferInt) wr.getDataBuffer();
    final int srcBase =
        (srcDB.getOffset()
            + sppsm.getOffset(
                rgn.x - wr.getSampleModelTranslateX(), rgn.y - wr.getSampleModelTranslateY()));

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

    ColorModel cm = srcRed.getColorModel();

    if (cm.isAlphaPremultiplied()) {
      // For alpha premult we need to multiply all comps.
      for (int y = 0; y < rgn.height; y++) {
        int sp = srcBase + y * srcScanStride;
        int ap = alpBase + y * alpScanStride;
        int end = sp + rgn.width;

        while (sp < end) {
          int a = ((int) alpPixels[ap++]) & 0xFF;
          final int pix = srcPixels[sp];
          srcPixels[sp] =
              ((((((pix >>> 24)) * a) & 0xFF00) << 16)
                  | (((((pix >>> 16) & 0xFF) * a) & 0xFF00) << 8)
                  | (((((pix >>> 8) & 0xFF) * a) & 0xFF00))
                  | (((((pix) & 0xFF) * a) & 0xFF00) >> 8));
          sp++;
        }
      }

    } else {
      // For non-alpha premult we only need to multiply alpha.
      for (int y = 0; y < rgn.height; y++) {
        int sp = srcBase + y * srcScanStride;
        int ap = alpBase + y * alpScanStride;
        int end = sp + rgn.width;
        while (sp < end) {
          int a = ((int) alpPixels[ap++]) & 0xFF;
          int sa = srcPixels[sp] >>> 24;
          srcPixels[sp] = ((((sa * a) & 0xFF00) << 16) | srcPixels[sp] & 0x00FFFFFF);
          sp++;
        }
      }
    }

    return wr;
  }
  public WritableRaster copyData(WritableRaster wr) {
    // Get my source.
    CachableRed srcRed = (CachableRed) getSources().get(0);
    CachableRed alphaRed = (CachableRed) getSources().get(1);

    if (is_INT_PACK_BYTE_COMP(srcRed.getSampleModel(), alphaRed.getSampleModel()))
      return INT_PACK_BYTE_COMP_Impl(wr);

    ColorModel cm = srcRed.getColorModel();
    if (cm.hasAlpha()) {
      // Already has alpha channel so we use it.
      srcRed.copyData(wr);

      Rectangle rgn = wr.getBounds();
      if (rgn.intersects(alphaRed.getBounds())) rgn = rgn.intersection(alphaRed.getBounds());
      else return wr;

      int[] wrData = null;
      int[] alphaData = null;

      Raster r = alphaRed.getData(rgn);
      int w = rgn.width;

      final int bands = wr.getSampleModel().getNumBands();

      if (cm.isAlphaPremultiplied()) {
        for (int y = rgn.y; y < rgn.y + rgn.height; y++) {
          wrData = wr.getPixels(rgn.x, y, w, 1, wrData);
          alphaData = r.getSamples(rgn.x, y, w, 1, 0, alphaData);
          int i = 0, a, b;
          // 4 is the most common case.
          // 2 is probably next most common...
          switch (bands) {
            case 2:
              for (int x = 0; x < alphaData.length; x++) {
                a = alphaData[x] & 0xFF;
                wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                ++i;
                wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                ++i;
              }
              break;
            case 4:
              for (int x = 0; x < alphaData.length; x++) {
                a = alphaData[x] & 0xFF;
                wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                ++i;
                wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                ++i;
                wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                ++i;
                wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                ++i;
              }
              break;
            default:
              for (int x = 0; x < alphaData.length; x++) {
                a = alphaData[x] & 0xFF;
                for (b = 0; b < bands; b++) {
                  wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                  ++i;
                }
              }
          }
          wr.setPixels(rgn.x, y, w, 1, wrData);
        }
      } else {
        int b = srcRed.getSampleModel().getNumBands() - 1;
        for (int y = rgn.y; y < rgn.y + rgn.height; y++) {
          wrData = wr.getSamples(rgn.x, y, w, 1, b, wrData);
          alphaData = r.getSamples(rgn.x, y, w, 1, 0, alphaData);
          for (int i = 0; i < wrData.length; i++) {
            wrData[i] = ((wrData[i] & 0xFF) * (alphaData[i] & 0xFF)) >> 8;
          }
          wr.setSamples(rgn.x, y, w, 1, b, wrData);
        }
      }

      return wr;
    }

    // No alpha in source, so we hide the alpha channel in wr and
    // have our source fill wr with color info...
    int[] bands = new int[wr.getNumBands() - 1];
    for (int i = 0; i < bands.length; i++) bands[i] = i;

    WritableRaster subWr;
    subWr =
        wr.createWritableChild(
            wr.getMinX(),
            wr.getMinY(),
            wr.getWidth(),
            wr.getHeight(),
            wr.getMinX(),
            wr.getMinY(),
            bands);

    srcRed.copyData(subWr);

    Rectangle rgn = wr.getBounds();
    rgn = rgn.intersection(alphaRed.getBounds());

    bands = new int[] {wr.getNumBands() - 1};
    subWr = wr.createWritableChild(rgn.x, rgn.y, rgn.width, rgn.height, rgn.x, rgn.y, bands);
    alphaRed.copyData(subWr);

    return wr;
  }