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; }