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