0001: /*
0002:
0003: Licensed to the Apache Software Foundation (ASF) under one or more
0004: contributor license agreements. See the NOTICE file distributed with
0005: this work for additional information regarding copyright ownership.
0006: The ASF licenses this file to You under the Apache License, Version 2.0
0007: (the "License"); you may not use this file except in compliance with
0008: the License. You may obtain a copy of the License at
0009:
0010: http://www.apache.org/licenses/LICENSE-2.0
0011:
0012: Unless required by applicable law or agreed to in writing, software
0013: distributed under the License is distributed on an "AS IS" BASIS,
0014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015: See the License for the specific language governing permissions and
0016: limitations under the License.
0017:
0018: */
0019: package org.apache.batik.ext.awt.image;
0020:
0021: import java.awt.AlphaComposite;
0022: import java.awt.Composite;
0023: import java.awt.CompositeContext;
0024: import java.awt.RenderingHints;
0025: import java.awt.color.ColorSpace;
0026: import java.awt.image.ColorModel;
0027: import java.awt.image.DataBufferInt;
0028: import java.awt.image.PackedColorModel;
0029: import java.awt.image.Raster;
0030: import java.awt.image.SinglePixelPackedSampleModel;
0031: import java.awt.image.WritableRaster;
0032:
0033: /**
0034: * This provides an implementation of all the composite rules in SVG.
0035: *
0036: * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
0037: * @version $Id: SVGComposite.java 478363 2006-11-22 23:01:13Z dvholten $
0038: */
0039: public class SVGComposite implements Composite {
0040:
0041: public static final SVGComposite OVER = new SVGComposite(
0042: CompositeRule.OVER);
0043:
0044: public static final SVGComposite IN = new SVGComposite(
0045: CompositeRule.IN);
0046:
0047: public static final SVGComposite OUT = new SVGComposite(
0048: CompositeRule.OUT);
0049:
0050: public static final SVGComposite ATOP = new SVGComposite(
0051: CompositeRule.ATOP);
0052:
0053: public static final SVGComposite XOR = new SVGComposite(
0054: CompositeRule.XOR);
0055:
0056: public static final SVGComposite MULTIPLY = new SVGComposite(
0057: CompositeRule.MULTIPLY);
0058:
0059: public static final SVGComposite SCREEN = new SVGComposite(
0060: CompositeRule.SCREEN);
0061:
0062: public static final SVGComposite DARKEN = new SVGComposite(
0063: CompositeRule.DARKEN);
0064:
0065: public static final SVGComposite LIGHTEN = new SVGComposite(
0066: CompositeRule.LIGHTEN);
0067:
0068: CompositeRule rule;
0069:
0070: public CompositeRule getRule() {
0071: return rule;
0072: }
0073:
0074: public SVGComposite(CompositeRule rule) {
0075: this .rule = rule;
0076: }
0077:
0078: public boolean equals(Object o) {
0079: if (o instanceof SVGComposite) {
0080: SVGComposite svgc = (SVGComposite) o;
0081: return (svgc.getRule() == getRule());
0082: } else if (o instanceof AlphaComposite) {
0083: AlphaComposite ac = (AlphaComposite) o;
0084: switch (getRule().getRule()) {
0085: case CompositeRule.RULE_OVER:
0086: return (ac == AlphaComposite.SrcOver);
0087: case CompositeRule.RULE_IN:
0088: return (ac == AlphaComposite.SrcIn);
0089: case CompositeRule.RULE_OUT:
0090: return (ac == AlphaComposite.SrcOut);
0091: default:
0092: return false;
0093: }
0094: }
0095: return false;
0096: }
0097:
0098: public boolean is_INT_PACK(ColorModel cm) {
0099: // Check ColorModel is of type DirectColorModel
0100: if (!(cm instanceof PackedColorModel))
0101: return false;
0102:
0103: PackedColorModel pcm = (PackedColorModel) cm;
0104:
0105: int[] masks = pcm.getMasks();
0106:
0107: // Check transfer type
0108: if (masks.length != 4)
0109: return false;
0110:
0111: if (masks[0] != 0x00ff0000)
0112: return false;
0113: if (masks[1] != 0x0000ff00)
0114: return false;
0115: if (masks[2] != 0x000000ff)
0116: return false;
0117: if (masks[3] != 0xff000000)
0118: return false;
0119:
0120: return true;
0121: }
0122:
0123: public CompositeContext createContext(ColorModel srcCM,
0124: ColorModel dstCM, RenderingHints hints) {
0125: if (false) {
0126: ColorSpace srcCS = srcCM.getColorSpace();
0127: ColorSpace dstCS = dstCM.getColorSpace();
0128: System.out.println("srcCS: " + srcCS);
0129: System.out.println("dstCS: " + dstCS);
0130: System.out.println("lRGB: "
0131: + ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB));
0132: System.out.println("sRGB: "
0133: + ColorSpace.getInstance(ColorSpace.CS_sRGB));
0134: }
0135:
0136: // Orig Time no int_pack = 51792
0137: // Simple int_pack = 19600
0138: boolean use_int_pack = (is_INT_PACK(srcCM) && is_INT_PACK(dstCM));
0139: // use_int_pack = false;
0140:
0141: switch (rule.getRule()) {
0142: case CompositeRule.RULE_OVER:
0143: if (!dstCM.hasAlpha()) {
0144: if (use_int_pack)
0145: return new OverCompositeContext_INT_PACK_NA(srcCM,
0146: dstCM);
0147: else
0148: return new OverCompositeContext_NA(srcCM, dstCM);
0149: }
0150:
0151: if (!use_int_pack)
0152: return new OverCompositeContext(srcCM, dstCM);
0153:
0154: if (srcCM.isAlphaPremultiplied())
0155: return new OverCompositeContext_INT_PACK(srcCM, dstCM);
0156: else
0157: return new OverCompositeContext_INT_PACK_UNPRE(srcCM,
0158: dstCM);
0159:
0160: case CompositeRule.RULE_IN:
0161: if (use_int_pack)
0162: return new InCompositeContext_INT_PACK(srcCM, dstCM);
0163: else
0164: return new InCompositeContext(srcCM, dstCM);
0165:
0166: case CompositeRule.RULE_OUT:
0167: if (use_int_pack)
0168: return new OutCompositeContext_INT_PACK(srcCM, dstCM);
0169: else
0170: return new OutCompositeContext(srcCM, dstCM);
0171:
0172: case CompositeRule.RULE_ATOP:
0173: if (use_int_pack)
0174: return new AtopCompositeContext_INT_PACK(srcCM, dstCM);
0175: else
0176: return new AtopCompositeContext(srcCM, dstCM);
0177:
0178: case CompositeRule.RULE_XOR:
0179: if (use_int_pack)
0180: return new XorCompositeContext_INT_PACK(srcCM, dstCM);
0181: else
0182: return new XorCompositeContext(srcCM, dstCM);
0183:
0184: case CompositeRule.RULE_ARITHMETIC:
0185: float[] coeff = rule.getCoefficients();
0186: if (use_int_pack)
0187: return new ArithCompositeContext_INT_PACK_LUT(srcCM,
0188: dstCM, coeff[0], coeff[1], coeff[2], coeff[3]);
0189: else
0190: return new ArithCompositeContext(srcCM, dstCM,
0191: coeff[0], coeff[1], coeff[2], coeff[3]);
0192:
0193: case CompositeRule.RULE_MULTIPLY:
0194: if (use_int_pack)
0195: return new MultiplyCompositeContext_INT_PACK(srcCM,
0196: dstCM);
0197: else
0198: return new MultiplyCompositeContext(srcCM, dstCM);
0199:
0200: case CompositeRule.RULE_SCREEN:
0201: if (use_int_pack)
0202: return new ScreenCompositeContext_INT_PACK(srcCM, dstCM);
0203: else
0204: return new ScreenCompositeContext(srcCM, dstCM);
0205:
0206: case CompositeRule.RULE_DARKEN:
0207: if (use_int_pack)
0208: return new DarkenCompositeContext_INT_PACK(srcCM, dstCM);
0209: else
0210: return new DarkenCompositeContext(srcCM, dstCM);
0211:
0212: case CompositeRule.RULE_LIGHTEN:
0213: if (use_int_pack)
0214: return new LightenCompositeContext_INT_PACK(srcCM,
0215: dstCM);
0216: else
0217: return new LightenCompositeContext(srcCM, dstCM);
0218:
0219: default:
0220: throw new UnsupportedOperationException(
0221: "Unknown composite rule requested.");
0222: }
0223:
0224: }
0225:
0226: public abstract static class AlphaPreCompositeContext implements
0227: CompositeContext {
0228:
0229: ColorModel srcCM, dstCM;
0230:
0231: AlphaPreCompositeContext(ColorModel srcCM, ColorModel dstCM) {
0232: this .srcCM = srcCM;
0233: this .dstCM = dstCM;
0234: }
0235:
0236: public void dispose() {
0237: srcCM = null;
0238: dstCM = null;
0239: }
0240:
0241: protected abstract void precompose(Raster src, Raster dstIn,
0242: WritableRaster dstOut);
0243:
0244: public void compose(Raster src, Raster dstIn,
0245: WritableRaster dstOut) {
0246: ColorModel srcPreCM = srcCM;
0247: if (!srcCM.isAlphaPremultiplied())
0248: srcPreCM = GraphicsUtil.coerceData(
0249: (WritableRaster) src, srcCM, true);
0250:
0251: ColorModel dstPreCM = dstCM;
0252: if (!dstCM.isAlphaPremultiplied())
0253: dstPreCM = GraphicsUtil.coerceData(
0254: (WritableRaster) dstIn, dstCM, true);
0255:
0256: precompose(src, dstIn, dstOut);
0257:
0258: if (!srcCM.isAlphaPremultiplied())
0259: GraphicsUtil.coerceData((WritableRaster) src, srcPreCM,
0260: false);
0261:
0262: if (!dstCM.isAlphaPremultiplied()) {
0263: GraphicsUtil.coerceData(dstOut, dstPreCM, false);
0264:
0265: if (dstIn != dstOut)
0266: GraphicsUtil.coerceData((WritableRaster) dstIn,
0267: dstPreCM, false);
0268: }
0269: }
0270: }
0271:
0272: public abstract static class AlphaPreCompositeContext_INT_PACK
0273: extends AlphaPreCompositeContext {
0274:
0275: AlphaPreCompositeContext_INT_PACK(ColorModel srcCM,
0276: ColorModel dstCM) {
0277: super (srcCM, dstCM);
0278: }
0279:
0280: protected abstract void precompose_INT_PACK(final int width,
0281: final int height, final int[] srcPixels,
0282: final int srcAdjust, int srcSp,
0283: final int[] dstInPixels, final int dstInAdjust,
0284: int dstInSp, final int[] dstOutPixels,
0285: final int dstOutAdjust, int dstOutSp);
0286:
0287: protected void precompose(Raster src, Raster dstIn,
0288: WritableRaster dstOut) {
0289:
0290: int x0 = dstOut.getMinX();
0291: int w = dstOut.getWidth();
0292:
0293: int y0 = dstOut.getMinY();
0294: int h = dstOut.getHeight();
0295:
0296: SinglePixelPackedSampleModel srcSPPSM;
0297: srcSPPSM = (SinglePixelPackedSampleModel) src
0298: .getSampleModel();
0299:
0300: final int srcScanStride = srcSPPSM.getScanlineStride();
0301: DataBufferInt srcDB = (DataBufferInt) src.getDataBuffer();
0302: final int[] srcPixels = srcDB.getBankData()[0];
0303: final int srcBase = (srcDB.getOffset() + srcSPPSM
0304: .getOffset(x0 - src.getSampleModelTranslateX(), y0
0305: - src.getSampleModelTranslateY()));
0306:
0307: SinglePixelPackedSampleModel dstInSPPSM;
0308: dstInSPPSM = (SinglePixelPackedSampleModel) dstIn
0309: .getSampleModel();
0310:
0311: final int dstInScanStride = dstInSPPSM.getScanlineStride();
0312: DataBufferInt dstInDB = (DataBufferInt) dstIn
0313: .getDataBuffer();
0314: final int[] dstInPixels = dstInDB.getBankData()[0];
0315: final int dstInBase = (dstInDB.getOffset() + dstInSPPSM
0316: .getOffset(x0 - dstIn.getSampleModelTranslateX(),
0317: y0 - dstIn.getSampleModelTranslateY()));
0318:
0319: SinglePixelPackedSampleModel dstOutSPPSM = (SinglePixelPackedSampleModel) dstOut
0320: .getSampleModel();
0321:
0322: final int dstOutScanStride = dstOutSPPSM
0323: .getScanlineStride();
0324: DataBufferInt dstOutDB = (DataBufferInt) dstOut
0325: .getDataBuffer();
0326: final int[] dstOutPixels = dstOutDB.getBankData()[0];
0327: final int dstOutBase = (dstOutDB.getOffset() + dstOutSPPSM
0328: .getOffset(x0 - dstOut.getSampleModelTranslateX(),
0329: y0 - dstOut.getSampleModelTranslateY()));
0330:
0331: final int srcAdjust = srcScanStride - w;
0332: final int dstInAdjust = dstInScanStride - w;
0333: final int dstOutAdjust = dstOutScanStride - w;
0334:
0335: precompose_INT_PACK(w, h, srcPixels, srcAdjust, srcBase,
0336: dstInPixels, dstInAdjust, dstInBase, dstOutPixels,
0337: dstOutAdjust, dstOutBase);
0338: }
0339: }
0340:
0341: /**
0342: * This implements SRC_OVER for 4 band byte data.
0343: */
0344: public static class OverCompositeContext extends
0345: AlphaPreCompositeContext {
0346: OverCompositeContext(ColorModel srcCM, ColorModel dstCM) {
0347: super (srcCM, dstCM);
0348: }
0349:
0350: public void precompose(Raster src, Raster dstIn,
0351: WritableRaster dstOut) {
0352: int[] srcPix = null;
0353: int[] dstPix = null;
0354:
0355: int x = dstOut.getMinX();
0356: int w = dstOut.getWidth();
0357:
0358: int y0 = dstOut.getMinY();
0359: int y1 = y0 + dstOut.getHeight();
0360:
0361: final int norm = (1 << 24) / 255;
0362: final int pt5 = (1 << 23);
0363:
0364: for (int y = y0; y < y1; y++) {
0365: srcPix = src.getPixels(x, y, w, 1, srcPix);
0366: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
0367: int sp = 0;
0368: int end = w * 4;
0369: while (sp < end) {
0370: final int dstM = (255 - srcPix[sp + 3]) * norm;
0371: dstPix[sp] = srcPix[sp]
0372: + ((dstPix[sp] * dstM + pt5) >>> 24);
0373: ++sp;
0374: dstPix[sp] = srcPix[sp]
0375: + ((dstPix[sp] * dstM + pt5) >>> 24);
0376: ++sp;
0377: dstPix[sp] = srcPix[sp]
0378: + ((dstPix[sp] * dstM + pt5) >>> 24);
0379: ++sp;
0380: dstPix[sp] = srcPix[sp]
0381: + ((dstPix[sp] * dstM + pt5) >>> 24);
0382: ++sp;
0383: }
0384: dstOut.setPixels(x, y, w, 1, dstPix);
0385: }
0386:
0387: }
0388: }
0389:
0390: /**
0391: * This implements SRC_OVER for 4 band byte src data and
0392: * 3 band byte dst data.
0393: */
0394: public static class OverCompositeContext_NA extends
0395: AlphaPreCompositeContext {
0396: OverCompositeContext_NA(ColorModel srcCM, ColorModel dstCM) {
0397: super (srcCM, dstCM);
0398: }
0399:
0400: public void precompose(Raster src, Raster dstIn,
0401: WritableRaster dstOut) {
0402: int[] srcPix = null;
0403: int[] dstPix = null;
0404:
0405: int x = dstOut.getMinX();
0406: int w = dstOut.getWidth();
0407:
0408: int y0 = dstOut.getMinY();
0409: int y1 = y0 + dstOut.getHeight();
0410:
0411: final int norm = (1 << 24) / 255;
0412: final int pt5 = (1 << 23);
0413:
0414: for (int y = y0; y < y1; y++) {
0415: srcPix = src.getPixels(x, y, w, 1, srcPix);
0416: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
0417: int srcSP = 0;
0418: int dstSP = 0;
0419: int end = w * 4;
0420: while (srcSP < end) {
0421: final int dstM = (255 - srcPix[srcSP + 3]) * norm;
0422: dstPix[dstSP] = srcPix[srcSP]
0423: + ((dstPix[dstSP] * dstM + pt5) >>> 24);
0424: ++srcSP;
0425: ++dstSP;
0426: dstPix[dstSP] = srcPix[srcSP]
0427: + ((dstPix[dstSP] * dstM + pt5) >>> 24);
0428: ++srcSP;
0429: ++dstSP;
0430: dstPix[dstSP] = srcPix[srcSP]
0431: + ((dstPix[dstSP] * dstM + pt5) >>> 24);
0432: srcSP += 2;
0433: ++dstSP;
0434: }
0435: dstOut.setPixels(x, y, w, 1, dstPix);
0436: }
0437: }
0438: }
0439:
0440: /**
0441: * This implements SRC_OVER for Int packed data where the src is
0442: * premultiplied.
0443: */
0444: public static class OverCompositeContext_INT_PACK extends
0445: AlphaPreCompositeContext_INT_PACK {
0446: OverCompositeContext_INT_PACK(ColorModel srcCM, ColorModel dstCM) {
0447: super (srcCM, dstCM);
0448: }
0449:
0450: public void precompose_INT_PACK(final int width,
0451: final int height, final int[] srcPixels,
0452: final int srcAdjust, int srcSp,
0453: final int[] dstInPixels, final int dstInAdjust,
0454: int dstInSp, final int[] dstOutPixels,
0455: final int dstOutAdjust, int dstOutSp) {
0456:
0457: final int norm = (1 << 24) / 255;
0458: final int pt5 = (1 << 23);
0459:
0460: int srcP, dstInP, dstM;
0461:
0462: for (int y = 0; y < height; y++) {
0463: final int end = dstOutSp + width;
0464: while (dstOutSp < end) {
0465: srcP = srcPixels[srcSp++];
0466: dstInP = dstInPixels[dstInSp++];
0467:
0468: dstM = (255 - (srcP >>> 24)) * norm;
0469: dstOutPixels[dstOutSp++] = (((srcP & 0xFF000000) + (((((dstInP >>> 24))
0470: * dstM + pt5) & 0xFF000000)))
0471: | ((srcP & 0x00FF0000) + (((((dstInP >> 16) & 0xFF)
0472: * dstM + pt5) & 0xFF000000) >>> 8))
0473: | ((srcP & 0x0000FF00) + (((((dstInP >> 8) & 0xFF)
0474: * dstM + pt5) & 0xFF000000) >>> 16)) | ((srcP & 0x000000FF) + (((((dstInP) & 0xFF)
0475: * dstM + pt5)) >>> 24)));
0476: }
0477: srcSp += srcAdjust;
0478: dstInSp += dstInAdjust;
0479: dstOutSp += dstOutAdjust;
0480: }
0481: }
0482: }
0483:
0484: /**
0485: * This implements SRC_OVER for Int packed data and dest has no Alpha...
0486: */
0487: public static class OverCompositeContext_INT_PACK_NA extends
0488: AlphaPreCompositeContext_INT_PACK {
0489: OverCompositeContext_INT_PACK_NA(ColorModel srcCM,
0490: ColorModel dstCM) {
0491: super (srcCM, dstCM);
0492: }
0493:
0494: // When we get here src data has been premultiplied.
0495: public void precompose_INT_PACK(final int width,
0496: final int height, final int[] srcPixels,
0497: final int srcAdjust, int srcSp,
0498: final int[] dstInPixels, final int dstInAdjust,
0499: int dstInSp, final int[] dstOutPixels,
0500: final int dstOutAdjust, int dstOutSp) {
0501:
0502: final int norm = (1 << 24) / 255;
0503: final int pt5 = (1 << 23);
0504:
0505: int srcP, dstInP, dstM;
0506:
0507: for (int y = 0; y < height; y++) {
0508: final int end = dstOutSp + width;
0509: while (dstOutSp < end) {
0510: srcP = srcPixels[srcSp++];
0511: dstInP = dstInPixels[dstInSp++];
0512:
0513: dstM = (255 - (srcP >>> 24)) * norm;
0514: dstOutPixels[dstOutSp++] = (((srcP & 0x00FF0000) + (((((dstInP >> 16) & 0xFF)
0515: * dstM + pt5) & 0xFF000000) >>> 8))
0516: | ((srcP & 0x0000FF00) + (((((dstInP >> 8) & 0xFF)
0517: * dstM + pt5) & 0xFF000000) >>> 16)) | ((srcP & 0x000000FF) + (((((dstInP) & 0xFF)
0518: * dstM + pt5)) >>> 24)));
0519: }
0520: srcSp += srcAdjust;
0521: dstInSp += dstInAdjust;
0522: dstOutSp += dstOutAdjust;
0523: }
0524: }
0525: }
0526:
0527: /**
0528: * This implements SRC_OVER for Int packed data where the src is
0529: * unpremultiplied. This avoids having to multiply the alpha on the
0530: * the source then divide it out again.
0531: */
0532: public static class OverCompositeContext_INT_PACK_UNPRE extends
0533: AlphaPreCompositeContext_INT_PACK {
0534: OverCompositeContext_INT_PACK_UNPRE(ColorModel srcCM,
0535: ColorModel dstCM) {
0536: super (srcCM, dstCM);
0537:
0538: if (srcCM.isAlphaPremultiplied())
0539: throw new IllegalArgumentException(
0540: "OverCompositeContext_INT_PACK_UNPRE is only for"
0541: + "sources with unpremultiplied alpha");
0542: }
0543:
0544: public void compose(Raster src, Raster dstIn,
0545: WritableRaster dstOut) {
0546: ColorModel dstPreCM = dstCM;
0547: if (!dstCM.isAlphaPremultiplied())
0548: dstPreCM = GraphicsUtil.coerceData(
0549: (WritableRaster) dstIn, dstCM, true);
0550:
0551: precompose(src, dstIn, dstOut);
0552:
0553: if (!dstCM.isAlphaPremultiplied()) {
0554: GraphicsUtil.coerceData(dstOut, dstPreCM, false);
0555:
0556: if (dstIn != dstOut)
0557: GraphicsUtil.coerceData((WritableRaster) dstIn,
0558: dstPreCM, false);
0559: }
0560: }
0561:
0562: public void precompose_INT_PACK(final int width,
0563: final int height, final int[] srcPixels,
0564: final int srcAdjust, int srcSp,
0565: final int[] dstInPixels, final int dstInAdjust,
0566: int dstInSp, final int[] dstOutPixels,
0567: final int dstOutAdjust, int dstOutSp) {
0568:
0569: final int norm = (1 << 24) / 255;
0570: final int pt5 = (1 << 23);
0571:
0572: int srcP, srcM, dstP, dstM;
0573:
0574: for (int y = 0; y < height; y++) {
0575: final int end = dstOutSp + width;
0576: while (dstOutSp < end) {
0577: srcP = srcPixels[srcSp++];
0578: dstP = dstInPixels[dstInSp++];
0579:
0580: srcM = ((srcP >>> 24)) * norm;
0581: dstM = (255 - (srcP >>> 24)) * norm;
0582:
0583: dstOutPixels[dstOutSp++] = (((((srcP & 0xFF000000)
0584: + ((dstP >>> 24)) * dstM + pt5) & 0xFF000000))
0585: | (((((srcP >> 16) & 0xFF) * srcM
0586: + ((dstP >> 16) & 0xFF) * dstM + pt5) & 0xFF000000) >>> 8)
0587: | (((((srcP >> 8) & 0xFF) * srcM
0588: + ((dstP >> 8) & 0xFF) * dstM + pt5) & 0xFF000000) >>> 16) | (((((srcP) & 0xFF)
0589: * srcM + ((dstP) & 0xFF) * dstM + pt5)) >>> 24));
0590: }
0591: srcSp += srcAdjust;
0592: dstInSp += dstInAdjust;
0593: dstOutSp += dstOutAdjust;
0594: }
0595: }
0596: }
0597:
0598: public static class InCompositeContext extends
0599: AlphaPreCompositeContext {
0600: InCompositeContext(ColorModel srcCM, ColorModel dstCM) {
0601: super (srcCM, dstCM);
0602: }
0603:
0604: public void precompose(Raster src, Raster dstIn,
0605: WritableRaster dstOut) {
0606: int[] srcPix = null;
0607: int[] dstPix = null;
0608:
0609: int x = dstOut.getMinX();
0610: int w = dstOut.getWidth();
0611:
0612: int y0 = dstOut.getMinY();
0613: int y1 = y0 + dstOut.getHeight();
0614:
0615: final int norm = (1 << 24) / 255;
0616: final int pt5 = (1 << 23);
0617:
0618: for (int y = y0; y < y1; y++) {
0619: srcPix = src.getPixels(x, y, w, 1, srcPix);
0620: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
0621: int sp = 0;
0622: int end = w * 4;
0623: while (sp < end) {
0624: final int srcM = dstPix[sp + 3] * norm;
0625: dstPix[sp] = (srcPix[sp] * srcM + pt5) >>> 24;
0626: ++sp;
0627: dstPix[sp] = (srcPix[sp] * srcM + pt5) >>> 24;
0628: ++sp;
0629: dstPix[sp] = (srcPix[sp] * srcM + pt5) >>> 24;
0630: ++sp;
0631: dstPix[sp] = (srcPix[sp] * srcM + pt5) >>> 24;
0632: ++sp;
0633: }
0634: dstOut.setPixels(x, y, w, 1, dstPix);
0635: }
0636:
0637: }
0638: }
0639:
0640: public static class InCompositeContext_INT_PACK extends
0641: AlphaPreCompositeContext_INT_PACK {
0642: InCompositeContext_INT_PACK(ColorModel srcCM, ColorModel dstCM) {
0643: super (srcCM, dstCM);
0644: }
0645:
0646: public void precompose_INT_PACK(final int width,
0647: final int height, final int[] srcPixels,
0648: final int srcAdjust, int srcSp,
0649: final int[] dstInPixels, final int dstInAdjust,
0650: int dstInSp, final int[] dstOutPixels,
0651: final int dstOutAdjust, int dstOutSp) {
0652:
0653: final int norm = (1 << 24) / 255;
0654: final int pt5 = (1 << 23);
0655:
0656: int srcP, srcM;
0657:
0658: for (int y = 0; y < height; y++) {
0659: final int end = dstOutSp + width;
0660: while (dstOutSp < end) {
0661: srcM = (dstInPixels[dstInSp++] >>> 24) * norm;
0662: srcP = srcPixels[srcSp++];
0663: dstOutPixels[dstOutSp++] = ((((((srcP >>> 24))
0664: * srcM + pt5) & 0xFF000000))
0665: | (((((srcP >> 16) & 0xFF) * srcM + pt5) & 0xFF000000) >>> 8)
0666: | (((((srcP >> 8) & 0xFF) * srcM + pt5) & 0xFF000000) >>> 16) | (((((srcP) & 0xFF)
0667: * srcM + pt5)) >>> 24));
0668: }
0669: srcSp += srcAdjust;
0670: dstInSp += dstInAdjust;
0671: dstOutSp += dstOutAdjust;
0672: }
0673: }
0674: }
0675:
0676: public static class OutCompositeContext extends
0677: AlphaPreCompositeContext {
0678: OutCompositeContext(ColorModel srcCM, ColorModel dstCM) {
0679: super (srcCM, dstCM);
0680: }
0681:
0682: public void precompose(Raster src, Raster dstIn,
0683: WritableRaster dstOut) {
0684: int[] srcPix = null;
0685: int[] dstPix = null;
0686:
0687: int x = dstOut.getMinX();
0688: int w = dstOut.getWidth();
0689:
0690: int y0 = dstOut.getMinY();
0691: int y1 = y0 + dstOut.getHeight();
0692:
0693: final int norm = (1 << 24) / 255;
0694: final int pt5 = (1 << 23);
0695:
0696: for (int y = y0; y < y1; y++) {
0697: srcPix = src.getPixels(x, y, w, 1, srcPix);
0698: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
0699: int sp = 0;
0700: int end = w * 4;
0701: while (sp < end) {
0702: final int srcM = (255 - dstPix[sp + 3]) * norm;
0703: dstPix[sp] = (srcPix[sp] * srcM + pt5) >>> 24;
0704: ++sp;
0705: dstPix[sp] = (srcPix[sp] * srcM + pt5) >>> 24;
0706: ++sp;
0707: dstPix[sp] = (srcPix[sp] * srcM + pt5) >>> 24;
0708: ++sp;
0709: dstPix[sp] = (srcPix[sp] * srcM + pt5) >>> 24;
0710: ++sp;
0711: }
0712: dstOut.setPixels(x, y, w, 1, dstPix);
0713: }
0714:
0715: }
0716: }
0717:
0718: public static class OutCompositeContext_INT_PACK extends
0719: AlphaPreCompositeContext_INT_PACK {
0720: OutCompositeContext_INT_PACK(ColorModel srcCM, ColorModel dstCM) {
0721: super (srcCM, dstCM);
0722: }
0723:
0724: public void precompose_INT_PACK(final int width,
0725: final int height, final int[] srcPixels,
0726: final int srcAdjust, int srcSp,
0727: final int[] dstInPixels, final int dstInAdjust,
0728: int dstInSp, final int[] dstOutPixels,
0729: final int dstOutAdjust, int dstOutSp) {
0730:
0731: final int norm = (1 << 24) / 255;
0732: final int pt5 = (1 << 23);
0733:
0734: int srcP, srcM;
0735:
0736: for (int y = 0; y < height; y++) {
0737: final int end = dstOutSp + width;
0738: while (dstOutSp < end) {
0739: srcM = (255 - (dstInPixels[dstInSp++] >>> 24))
0740: * norm;
0741: srcP = srcPixels[srcSp++];
0742: dstOutPixels[dstOutSp++] = ((((((srcP >>> 24))
0743: * srcM + pt5) & 0xFF000000))
0744: | (((((srcP >> 16) & 0xFF) * srcM + pt5) & 0xFF000000) >>> 8)
0745: | (((((srcP >> 8) & 0xFF) * srcM + pt5) & 0xFF000000) >>> 16) | (((((srcP) & 0xFF)
0746: * srcM + pt5)) >>> 24));
0747: }
0748: srcSp += srcAdjust;
0749: dstInSp += dstInAdjust;
0750: dstOutSp += dstOutAdjust;
0751: }
0752: }
0753: }
0754:
0755: public static class AtopCompositeContext extends
0756: AlphaPreCompositeContext {
0757: AtopCompositeContext(ColorModel srcCM, ColorModel dstCM) {
0758: super (srcCM, dstCM);
0759: }
0760:
0761: public void precompose(Raster src, Raster dstIn,
0762: WritableRaster dstOut) {
0763: int[] srcPix = null;
0764: int[] dstPix = null;
0765:
0766: int x = dstOut.getMinX();
0767: int w = dstOut.getWidth();
0768:
0769: int y0 = dstOut.getMinY();
0770: int y1 = y0 + dstOut.getHeight();
0771:
0772: final int norm = (1 << 24) / 255;
0773: final int pt5 = (1 << 23);
0774:
0775: for (int y = y0; y < y1; y++) {
0776: srcPix = src.getPixels(x, y, w, 1, srcPix);
0777: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
0778: int sp = 0;
0779: int end = w * 4;
0780: while (sp < end) {
0781: final int srcM = (dstPix[sp + 3]) * norm;
0782: final int dstM = (255 - srcPix[sp + 3]) * norm;
0783: dstPix[sp] = (srcPix[sp] * srcM + dstPix[sp] * dstM + pt5) >>> 24;
0784: ++sp;
0785: dstPix[sp] = (srcPix[sp] * srcM + dstPix[sp] * dstM + pt5) >>> 24;
0786: ++sp;
0787: dstPix[sp] = (srcPix[sp] * srcM + dstPix[sp] * dstM + pt5) >>> 24;
0788: sp += 2;
0789: }
0790: dstOut.setPixels(x, y, w, 1, dstPix);
0791: }
0792:
0793: }
0794: }
0795:
0796: public static class AtopCompositeContext_INT_PACK extends
0797: AlphaPreCompositeContext_INT_PACK {
0798: AtopCompositeContext_INT_PACK(ColorModel srcCM, ColorModel dstCM) {
0799: super (srcCM, dstCM);
0800: }
0801:
0802: public void precompose_INT_PACK(final int width,
0803: final int height, final int[] srcPixels,
0804: final int srcAdjust, int srcSp,
0805: final int[] dstInPixels, final int dstInAdjust,
0806: int dstInSp, final int[] dstOutPixels,
0807: final int dstOutAdjust, int dstOutSp) {
0808:
0809: final int norm = (1 << 24) / 255;
0810: final int pt5 = (1 << 23);
0811:
0812: int srcP, srcM, dstP, dstM;
0813:
0814: for (int y = 0; y < height; y++) {
0815: final int end = dstOutSp + width;
0816: while (dstOutSp < end) {
0817: srcP = srcPixels[srcSp++];
0818: dstP = dstInPixels[dstInSp++];
0819:
0820: srcM = (dstP >>> 24) * norm;
0821: dstM = (255 - (srcP >>> 24)) * norm;
0822:
0823: dstOutPixels[dstOutSp++] = ((dstP & 0xFF000000)
0824: | (((((srcP >> 16) & 0xFF) * srcM
0825: + ((dstP >> 16) & 0xFF) * dstM + pt5) & 0xFF000000) >>> 8)
0826: | (((((srcP >> 8) & 0xFF) * srcM
0827: + ((dstP >> 8) & 0xFF) * dstM + pt5) & 0xFF000000) >>> 16) | (((((srcP) & 0xFF)
0828: * srcM + ((dstP) & 0xFF) * dstM + pt5)) >>> 24));
0829: }
0830: srcSp += srcAdjust;
0831: dstInSp += dstInAdjust;
0832: dstOutSp += dstOutAdjust;
0833: }
0834: }
0835: }
0836:
0837: public static class XorCompositeContext extends
0838: AlphaPreCompositeContext {
0839:
0840: XorCompositeContext(ColorModel srcCM, ColorModel dstCM) {
0841: super (srcCM, dstCM);
0842: }
0843:
0844: public void precompose(Raster src, Raster dstIn,
0845: WritableRaster dstOut) {
0846: int[] srcPix = null;
0847: int[] dstPix = null;
0848:
0849: int x = dstOut.getMinX();
0850: int w = dstOut.getWidth();
0851:
0852: int y0 = dstOut.getMinY();
0853: int y1 = y0 + dstOut.getHeight();
0854:
0855: final int norm = (1 << 24) / 255;
0856: final int pt5 = (1 << 23);
0857:
0858: for (int y = y0; y < y1; y++) {
0859: srcPix = src.getPixels(x, y, w, 1, srcPix);
0860: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
0861: int sp = 0;
0862: int end = w * 4;
0863: while (sp < end) {
0864: final int srcM = (255 - dstPix[sp + 3]) * norm;
0865: final int dstM = (255 - srcPix[sp + 3]) * norm;
0866:
0867: dstPix[sp] = (srcPix[sp] * srcM + dstPix[sp] * dstM + pt5) >>> 24;
0868: ++sp;
0869: dstPix[sp] = (srcPix[sp] * srcM + dstPix[sp] * dstM + pt5) >>> 24;
0870: ++sp;
0871: dstPix[sp] = (srcPix[sp] * srcM + dstPix[sp] * dstM + pt5) >>> 24;
0872: ++sp;
0873: dstPix[sp] = (srcPix[sp] * srcM + dstPix[sp] * dstM + pt5) >>> 24;
0874: ++sp;
0875: }
0876: dstOut.setPixels(x, y, w, 1, dstPix);
0877: }
0878:
0879: }
0880: }
0881:
0882: public static class XorCompositeContext_INT_PACK extends
0883: AlphaPreCompositeContext_INT_PACK {
0884: XorCompositeContext_INT_PACK(ColorModel srcCM, ColorModel dstCM) {
0885: super (srcCM, dstCM);
0886: }
0887:
0888: public void precompose_INT_PACK(final int width,
0889: final int height, final int[] srcPixels,
0890: final int srcAdjust, int srcSp,
0891: final int[] dstInPixels, final int dstInAdjust,
0892: int dstInSp, final int[] dstOutPixels,
0893: final int dstOutAdjust, int dstOutSp) {
0894:
0895: final int norm = (1 << 24) / 255;
0896: final int pt5 = (1 << 23);
0897:
0898: int srcP, srcM, dstP, dstM;
0899:
0900: for (int y = 0; y < height; y++) {
0901: final int end = dstOutSp + width;
0902: while (dstOutSp < end) {
0903: srcP = srcPixels[srcSp++];
0904: dstP = dstInPixels[dstInSp++];
0905:
0906: srcM = (255 - (dstP >>> 24)) * norm;
0907: dstM = (255 - (srcP >>> 24)) * norm;
0908:
0909: dstOutPixels[dstOutSp++] = ((((((srcP >>> 24))
0910: * srcM + ((dstP >>> 24)) * dstM + pt5) & 0xFF000000))
0911: | (((((srcP >> 16) & 0xFF) * srcM
0912: + ((dstP >> 16) & 0xFF) * dstM + pt5) & 0xFF000000) >>> 8)
0913: | (((((srcP >> 8) & 0xFF) * srcM
0914: + ((dstP >> 8) & 0xFF) * dstM + pt5) & 0xFF000000) >>> 16) | (((((srcP) & 0xFF)
0915: * srcM + ((dstP) & 0xFF) * dstM + pt5)) >>> 24));
0916: }
0917: srcSp += srcAdjust;
0918: dstInSp += dstInAdjust;
0919: dstOutSp += dstOutAdjust;
0920: }
0921: }
0922: }
0923:
0924: public static class ArithCompositeContext extends
0925: AlphaPreCompositeContext {
0926: float k1, k2, k3, k4;
0927:
0928: ArithCompositeContext(ColorModel srcCM, ColorModel dstCM,
0929: float k1, float k2, float k3, float k4) {
0930: super (srcCM, dstCM);
0931: this .k1 = k1;
0932: this .k2 = k2;
0933: this .k3 = k3;
0934: this .k4 = k4;
0935: }
0936:
0937: public void precompose(Raster src, Raster dstIn,
0938: WritableRaster dstOut) {
0939: int[] srcPix = null;
0940: int[] dstPix = null;
0941:
0942: int x = dstOut.getMinX();
0943: int w = dstOut.getWidth();
0944: int bands = dstOut.getNumBands();
0945:
0946: int y0 = dstOut.getMinY();
0947: int y1 = y0 + dstOut.getHeight();
0948:
0949: float kk1 = k1 / 255.0f;
0950: float kk4 = k4 * 255.0f + 0.5f;
0951:
0952: int y, i, b, val, max;
0953: for (y = y0; y < y1; y++) {
0954: srcPix = src.getPixels(x, y, w, 1, srcPix);
0955: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
0956: for (i = 0; i < srcPix.length; i++) {
0957: max = 0;
0958: for (b = 1; b < bands; b++, i++) {
0959: val = (int) ((kk1 * srcPix[i] * dstPix[i]) + k2
0960: * srcPix[i] + k3 * dstPix[i] + kk4);
0961: if ((val & 0xFFFFFF00) != 0)
0962: if ((val & 0x80000000) != 0)
0963: val = 0;
0964: else
0965: val = 255;
0966: if (val > max)
0967: max = val;
0968: dstPix[i] = val;
0969: }
0970:
0971: val = (int) ((kk1 * srcPix[i] * dstPix[i]) + k2
0972: * srcPix[i] + k3 * dstPix[i] + kk4);
0973: if ((val & 0xFFFFFF00) != 0)
0974: if ((val & 0x80000000) != 0)
0975: val = 0;
0976: else
0977: val = 255;
0978: if (val > max)
0979: dstPix[i] = val;
0980: else
0981: dstPix[i] = max;
0982: }
0983: dstOut.setPixels(x, y, w, 1, dstPix);
0984: }
0985: }
0986: }
0987:
0988: public static class ArithCompositeContext_INT_PACK extends
0989: AlphaPreCompositeContext_INT_PACK {
0990: float k1, k2, k3, k4;
0991:
0992: ArithCompositeContext_INT_PACK(ColorModel srcCM,
0993: ColorModel dstCM, float k1, float k2, float k3, float k4) {
0994: super (srcCM, dstCM);
0995: this .k1 = k1 / 255.0f;
0996: this .k2 = k2;
0997: this .k3 = k3;
0998: this .k4 = k4 * 255.0f + 0.5f;
0999: }
1000:
1001: public void precompose_INT_PACK(final int width,
1002: final int height, final int[] srcPixels,
1003: final int srcAdjust, int srcSp,
1004: final int[] dstInPixels, final int dstInAdjust,
1005: int dstInSp, final int[] dstOutPixels,
1006: final int dstOutAdjust, int dstOutSp) {
1007:
1008: int srcP, dstP, a, r, g, b;
1009:
1010: for (int y = 0; y < height; y++) {
1011: final int end = dstOutSp + width;
1012: while (dstOutSp < end) {
1013: srcP = srcPixels[srcSp++];
1014: dstP = dstInPixels[dstInSp++];
1015: a = (int) ((srcP >>> 24) * (dstP >>> 24) * k1
1016: + (srcP >>> 24) * k2 + (dstP >>> 24) * k3 + k4);
1017: if ((a & 0xFFFFFF00) != 0)
1018: if ((a & 0x80000000) != 0)
1019: a = 0;
1020: else
1021: a = 255;
1022:
1023: r = (int) (((srcP >> 16) & 0xFF)
1024: * ((dstP >> 16) & 0xFF) * k1
1025: + ((srcP >> 16) & 0xFF) * k2
1026: + ((dstP >> 16) & 0xFF) * k3 + k4);
1027: if ((r & 0xFFFFFF00) != 0)
1028: if ((r & 0x80000000) != 0)
1029: r = 0;
1030: else
1031: r = 255;
1032: if (a < r)
1033: a = r;
1034:
1035: g = (int) (((srcP >> 8) & 0xFF)
1036: * ((dstP >> 8) & 0xFF) * k1
1037: + ((srcP >> 8) & 0xFF) * k2
1038: + ((dstP >> 8) & 0xFF) * k3 + k4);
1039: if ((g & 0xFFFFFF00) != 0)
1040: if ((g & 0x80000000) != 0)
1041: g = 0;
1042: else
1043: g = 255;
1044: if (a < g)
1045: a = g;
1046:
1047: b = (int) ((srcP & 0xFF) * (dstP & 0xFF) * k1
1048: + (srcP & 0xFF) * k2 + (dstP & 0xFF) * k3 + k4);
1049: if ((b & 0xFFFFFF00) != 0)
1050: if ((b & 0x80000000) != 0)
1051: b = 0;
1052: else
1053: b = 255;
1054: if (a < b)
1055: a = b;
1056:
1057: dstOutPixels[dstOutSp++] = ((a << 24) | (r << 16)
1058: | (g << 8) | b);
1059: }
1060: srcSp += srcAdjust;
1061: dstInSp += dstInAdjust;
1062: dstOutSp += dstOutAdjust;
1063: }
1064: // long endTime = System.currentTimeMillis();
1065: // System.out.println("Arith Time: " + (endTime-startTime));
1066: }
1067: }
1068:
1069: public static class ArithCompositeContext_INT_PACK_LUT extends
1070: AlphaPreCompositeContext_INT_PACK {
1071: byte[] lut;
1072:
1073: ArithCompositeContext_INT_PACK_LUT(ColorModel srcCM,
1074: ColorModel dstCM, float k1, float k2, float k3, float k4) {
1075: super (srcCM, dstCM);
1076: k1 = k1 / 255.0f;
1077: k4 = k4 * 255.0f + 0.5f;
1078: int sz = 256 * 256;
1079: lut = new byte[sz];
1080: int val;
1081: for (int i = 0; i < sz; i++) {
1082: val = (int) ((i >> 8) * (i & 0xFF) * k1 + (i >> 8) * k2
1083: + (i & 0xFF) * k3 + k4);
1084: if ((val & 0xFFFFFF00) != 0)
1085: if ((val & 0x80000000) != 0)
1086: val = 0;
1087: else
1088: val = 255;
1089: lut[i] = (byte) val;
1090: }
1091: }
1092:
1093: public void precompose_INT_PACK(final int width,
1094: final int height, final int[] srcPixels,
1095: final int srcAdjust, int srcSp,
1096: final int[] dstInPixels, final int dstInAdjust,
1097: int dstInSp, final int[] dstOutPixels,
1098: final int dstOutAdjust, int dstOutSp) {
1099:
1100: byte[] workTbl = lut; // local is cheaper
1101: int srcP, dstP;
1102: for (int y = 0; y < height; y++) {
1103: final int end = dstOutSp + width;
1104: while (dstOutSp < end) {
1105: srcP = srcPixels[srcSp++];
1106: dstP = dstInPixels[dstInSp++];
1107:
1108: int a = 0xFF & workTbl[(((srcP >> 16) & 0xFF00) | ((dstP >>> 24)))];
1109: int r = 0xFF & workTbl[(((srcP >> 8) & 0xFF00) | ((dstP >> 16) & 0x00FF))];
1110: int g = 0xFF & workTbl[(((srcP) & 0xFF00) | ((dstP >> 8) & 0x00FF))];
1111: int b = 0xFF & workTbl[(((srcP << 8) & 0xFF00) | ((dstP) & 0x00FF))];
1112: if (r > a)
1113: a = r;
1114: if (g > a)
1115: a = g;
1116: if (b > a)
1117: a = b;
1118: dstOutPixels[dstOutSp++] = (a << 24) | (r << 16)
1119: | (g << 8) | (b);
1120: }
1121: srcSp += srcAdjust;
1122: dstInSp += dstInAdjust;
1123: dstOutSp += dstOutAdjust;
1124: }
1125: // long endTime = System.currentTimeMillis();
1126: // System.out.println("ArithLut Time: " + (endTime-startTime));
1127: }
1128: }
1129:
1130: /**
1131: * The following classes implement the various blend modes from SVG. */
1132: public static class MultiplyCompositeContext extends
1133: AlphaPreCompositeContext {
1134:
1135: MultiplyCompositeContext(ColorModel srcCM, ColorModel dstCM) {
1136: super (srcCM, dstCM);
1137: }
1138:
1139: public void precompose(Raster src, Raster dstIn,
1140: WritableRaster dstOut) {
1141: int[] srcPix = null;
1142: int[] dstPix = null;
1143:
1144: int x = dstOut.getMinX();
1145: int w = dstOut.getWidth();
1146:
1147: int y0 = dstOut.getMinY();
1148: int y1 = y0 + dstOut.getHeight();
1149:
1150: final int norm = (1 << 24) / 255;
1151: final int pt5 = (1 << 23);
1152: int srcM, dstM;
1153:
1154: for (int y = y0; y < y1; y++) {
1155: srcPix = src.getPixels(x, y, w, 1, srcPix);
1156: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
1157: int sp = 0;
1158: int end = w * 4;
1159: while (sp < end) {
1160: srcM = 255 - dstPix[sp + 3];
1161: dstM = 255 - srcPix[sp + 3];
1162:
1163: dstPix[sp] = ((srcPix[sp] * srcM + dstPix[sp]
1164: * dstM + srcPix[sp] * dstPix[sp])
1165: * norm + pt5) >>> 24;
1166: ++sp;
1167:
1168: dstPix[sp] = ((srcPix[sp] * srcM + dstPix[sp]
1169: * dstM + srcPix[sp] * dstPix[sp])
1170: * norm + pt5) >>> 24;
1171: ++sp;
1172:
1173: dstPix[sp] = ((srcPix[sp] * srcM + dstPix[sp]
1174: * dstM + srcPix[sp] * dstPix[sp])
1175: * norm + pt5) >>> 24;
1176: ++sp;
1177:
1178: dstPix[sp] = (srcPix[sp] + dstPix[sp] - ((dstPix[sp]
1179: * srcPix[sp] * norm + pt5) >>> 24));
1180: ++sp;
1181: }
1182: dstOut.setPixels(x, y, w, 1, dstPix);
1183: }
1184: }
1185: }
1186:
1187: public static class MultiplyCompositeContext_INT_PACK extends
1188: AlphaPreCompositeContext_INT_PACK {
1189: MultiplyCompositeContext_INT_PACK(ColorModel srcCM,
1190: ColorModel dstCM) {
1191: super (srcCM, dstCM);
1192: }
1193:
1194: public void precompose_INT_PACK(final int width,
1195: final int height, final int[] srcPixels,
1196: final int srcAdjust, int srcSp,
1197: final int[] dstInPixels, final int dstInAdjust,
1198: int dstInSp, final int[] dstOutPixels,
1199: final int dstOutAdjust, int dstOutSp) {
1200:
1201: final int norm = (1 << 24) / 255;
1202: final int pt5 = (1 << 23);
1203:
1204: int srcP, srcA, srcR, srcG, srcB, srcM;
1205: int dstP, dstA, dstR, dstG, dstB, dstM;
1206:
1207: for (int y = 0; y < height; y++) {
1208: final int end = dstOutSp + width;
1209: while (dstOutSp < end) {
1210: srcP = srcPixels[srcSp++];
1211: dstP = dstInPixels[dstInSp++];
1212:
1213: srcA = (srcP >>> 24);
1214: dstA = (dstP >>> 24);
1215: srcR = (srcP >> 16) & 0xFF;
1216: dstR = (dstP >> 16) & 0xFF;
1217: srcG = (srcP >> 8) & 0xFF;
1218: dstG = (dstP >> 8) & 0xFF;
1219: srcB = (srcP) & 0xFF;
1220: dstB = (dstP) & 0xFF;
1221:
1222: srcM = 255 - dstA;
1223: dstM = 255 - srcA;
1224:
1225: dstOutPixels[dstOutSp++] = (((((srcR * srcM + dstR
1226: * dstM + srcR * dstR)
1227: * norm + pt5) & 0xFF000000) >>> 8)
1228: | ((((srcG * srcM + dstG * dstM + srcG
1229: * dstG)
1230: * norm + pt5) & 0xFF000000) >>> 16)
1231: | ((((srcB * srcM + dstB * dstM + srcB
1232: * dstB)
1233: * norm + pt5)) >>> 24) | ((srcA
1234: + dstA - ((srcA * dstA * norm + pt5) >>> 24)) << 24));
1235: }
1236: srcSp += srcAdjust;
1237: dstInSp += dstInAdjust;
1238: dstOutSp += dstOutAdjust;
1239: }
1240: }
1241: }
1242:
1243: public static class ScreenCompositeContext extends
1244: AlphaPreCompositeContext {
1245:
1246: ScreenCompositeContext(ColorModel srcCM, ColorModel dstCM) {
1247: super (srcCM, dstCM);
1248: }
1249:
1250: public void precompose(Raster src, Raster dstIn,
1251: WritableRaster dstOut) {
1252: int[] srcPix = null;
1253: int[] dstPix = null;
1254:
1255: int x = dstOut.getMinX();
1256: int w = dstOut.getWidth();
1257:
1258: int y0 = dstOut.getMinY();
1259: int y1 = y0 + dstOut.getHeight();
1260:
1261: final int norm = (1 << 24) / 255;
1262: final int pt5 = (1 << 23);
1263:
1264: for (int y = y0; y < y1; y++) {
1265: srcPix = src.getPixels(x, y, w, 1, srcPix);
1266: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
1267: int sp = 0;
1268: int end = w * 4;
1269: while (sp < end) {
1270:
1271: int iSrcPix = srcPix[sp];
1272: int iDstPix = dstPix[sp];
1273:
1274: dstPix[sp] = (iSrcPix + iDstPix - ((iDstPix
1275: * iSrcPix * norm + pt5) >>> 24));
1276: ++sp;
1277: iSrcPix = srcPix[sp];
1278: iDstPix = dstPix[sp];
1279: dstPix[sp] = (iSrcPix + iDstPix - ((iDstPix
1280: * iSrcPix * norm + pt5) >>> 24));
1281: ++sp;
1282: iSrcPix = srcPix[sp];
1283: iDstPix = dstPix[sp];
1284: dstPix[sp] = (iSrcPix + iDstPix - ((iDstPix
1285: * iSrcPix * norm + pt5) >>> 24));
1286: ++sp;
1287: iSrcPix = srcPix[sp];
1288: iDstPix = dstPix[sp];
1289: dstPix[sp] = (iSrcPix + iDstPix - ((iDstPix
1290: * iSrcPix * norm + pt5) >>> 24));
1291: ++sp;
1292: }
1293: dstOut.setPixels(x, y, w, 1, dstPix);
1294: }
1295: }
1296: }
1297:
1298: public static class ScreenCompositeContext_INT_PACK extends
1299: AlphaPreCompositeContext_INT_PACK {
1300: ScreenCompositeContext_INT_PACK(ColorModel srcCM,
1301: ColorModel dstCM) {
1302: super (srcCM, dstCM);
1303: }
1304:
1305: public void precompose_INT_PACK(final int width,
1306: final int height, final int[] srcPixels,
1307: final int srcAdjust, int srcSp,
1308: final int[] dstInPixels, final int dstInAdjust,
1309: int dstInSp, final int[] dstOutPixels,
1310: final int dstOutAdjust, int dstOutSp) {
1311:
1312: final int norm = (1 << 24) / 255;
1313: final int pt5 = (1 << 23);
1314:
1315: int srcP, srcA, srcR, srcG, srcB;
1316: int dstP, dstA, dstR, dstG, dstB;
1317:
1318: for (int y = 0; y < height; y++) {
1319: final int end = dstOutSp + width;
1320: while (dstOutSp < end) {
1321: srcP = srcPixels[srcSp++];
1322: dstP = dstInPixels[dstInSp++];
1323:
1324: srcA = (srcP >>> 24);
1325: dstA = (dstP >>> 24);
1326: srcR = (srcP >> 16) & 0xFF;
1327: dstR = (dstP >> 16) & 0xFF;
1328: srcG = (srcP >> 8) & 0xFF;
1329: dstG = (dstP >> 8) & 0xFF;
1330: srcB = (srcP) & 0xFF;
1331: dstB = (dstP) & 0xFF;
1332:
1333: dstOutPixels[dstOutSp++] = (((srcR + dstR - ((srcR
1334: * dstR * norm + pt5) >>> 24)) << 16)
1335: | ((srcG + dstG - ((srcG * dstG * norm + pt5) >>> 24)) << 8)
1336: | ((srcB + dstB - ((srcB * dstB * norm + pt5) >>> 24))) | ((srcA
1337: + dstA - ((srcA * dstA * norm + pt5) >>> 24)) << 24));
1338: }
1339: srcSp += srcAdjust;
1340: dstInSp += dstInAdjust;
1341: dstOutSp += dstOutAdjust;
1342: }
1343: }
1344: }
1345:
1346: public static class DarkenCompositeContext extends
1347: AlphaPreCompositeContext {
1348:
1349: DarkenCompositeContext(ColorModel srcCM, ColorModel dstCM) {
1350: super (srcCM, dstCM);
1351: }
1352:
1353: public void precompose(Raster src, Raster dstIn,
1354: WritableRaster dstOut) {
1355: int[] srcPix = null;
1356: int[] dstPix = null;
1357:
1358: int x = dstOut.getMinX();
1359: int w = dstOut.getWidth();
1360:
1361: int y0 = dstOut.getMinY();
1362: int y1 = y0 + dstOut.getHeight();
1363:
1364: final int norm = (1 << 24) / 255;
1365: final int pt5 = (1 << 23);
1366:
1367: int sp, srcM, dstM, t1, t2;
1368:
1369: for (int y = y0; y < y1; y++) {
1370: srcPix = src.getPixels(x, y, w, 1, srcPix);
1371: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
1372: sp = 0;
1373: final int end = w * 4;
1374: while (sp < end) {
1375: srcM = 255 - dstPix[sp + 3];
1376: dstM = 255 - srcPix[sp + 3];
1377:
1378: t1 = ((srcM * srcPix[sp] * norm + pt5) >>> 24)
1379: + dstPix[sp];
1380: t2 = ((dstM * dstPix[sp] * norm + pt5) >>> 24)
1381: + srcPix[sp];
1382: if (t1 > t2)
1383: dstPix[sp] = t2;
1384: else
1385: dstPix[sp] = t1;
1386: ++sp;
1387:
1388: t1 = ((srcM * srcPix[sp] * norm + pt5) >>> 24)
1389: + dstPix[sp];
1390: t2 = ((dstM * dstPix[sp] * norm + pt5) >>> 24)
1391: + srcPix[sp];
1392: if (t1 > t2)
1393: dstPix[sp] = t2;
1394: else
1395: dstPix[sp] = t1;
1396: ++sp;
1397:
1398: t1 = ((srcM * srcPix[sp] * norm + pt5) >>> 24)
1399: + dstPix[sp];
1400: t2 = ((dstM * dstPix[sp] * norm + pt5) >>> 24)
1401: + srcPix[sp];
1402: if (t1 > t2)
1403: dstPix[sp] = t2;
1404: else
1405: dstPix[sp] = t1;
1406: ++sp;
1407:
1408: dstPix[sp] = (srcPix[sp] + dstPix[sp] - ((dstPix[sp]
1409: * srcPix[sp] * norm + pt5) >>> 24));
1410: ++sp;
1411: }
1412: dstOut.setPixels(x, y, w, 1, dstPix);
1413: }
1414: }
1415: }
1416:
1417: public static class DarkenCompositeContext_INT_PACK extends
1418: AlphaPreCompositeContext_INT_PACK {
1419: DarkenCompositeContext_INT_PACK(ColorModel srcCM,
1420: ColorModel dstCM) {
1421: super (srcCM, dstCM);
1422: }
1423:
1424: public void precompose_INT_PACK(final int width,
1425: final int height, final int[] srcPixels,
1426: final int srcAdjust, int srcSp,
1427: final int[] dstInPixels, final int dstInAdjust,
1428: int dstInSp, final int[] dstOutPixels,
1429: final int dstOutAdjust, int dstOutSp) {
1430:
1431: final int norm = (1 << 24) / 255;
1432: final int pt5 = (1 << 23);
1433:
1434: int srcP, srcM;
1435: int dstP, dstM, dstA, dstR, dstG, dstB;
1436:
1437: int srcV, dstV, tmp;
1438:
1439: for (int y = 0; y < height; y++) {
1440: final int end = dstOutSp + width;
1441: while (dstOutSp < end) {
1442: srcP = srcPixels[srcSp++];
1443: dstP = dstInPixels[dstInSp++];
1444:
1445: srcV = (srcP >>> 24);
1446: dstV = (dstP >>> 24);
1447: srcM = (255 - dstV) * norm;
1448: dstM = (255 - srcV) * norm;
1449: dstA = (srcV + dstV - ((srcV * dstV * norm + pt5) >>> 24));
1450:
1451: srcV = (srcP >> 16) & 0xFF;
1452: dstV = (dstP >> 16) & 0xFF;
1453: dstR = ((srcM * srcV + pt5) >>> 24) + dstV;
1454: tmp = ((dstM * dstV + pt5) >>> 24) + srcV;
1455: if (dstR > tmp)
1456: dstR = tmp;
1457:
1458: srcV = (srcP >> 8) & 0xFF;
1459: dstV = (dstP >> 8) & 0xFF;
1460: dstG = ((srcM * srcV + pt5) >>> 24) + dstV;
1461: tmp = ((dstM * dstV + pt5) >>> 24) + srcV;
1462: if (dstG > tmp)
1463: dstG = tmp;
1464:
1465: srcV = (srcP) & 0xFF;
1466: dstV = (dstP) & 0xFF;
1467: dstB = ((srcM * srcV + pt5) >>> 24) + dstV;
1468: tmp = ((dstM * dstV + pt5) >>> 24) + srcV;
1469: if (dstB > tmp)
1470: dstB = tmp;
1471:
1472: dstA &= 0xFF; // trim to 8 bit
1473: dstR &= 0xFF;
1474: dstG &= 0xFF;
1475: dstB &= 0xFF;
1476:
1477: dstOutPixels[dstOutSp++] = ((dstA << 24)
1478: | (dstR << 16) | (dstG << 8) | dstB);
1479: }
1480: srcSp += srcAdjust;
1481: dstInSp += dstInAdjust;
1482: dstOutSp += dstOutAdjust;
1483: }
1484: }
1485: }
1486:
1487: public static class LightenCompositeContext extends
1488: AlphaPreCompositeContext {
1489:
1490: LightenCompositeContext(ColorModel srcCM, ColorModel dstCM) {
1491: super (srcCM, dstCM);
1492: }
1493:
1494: public void precompose(Raster src, Raster dstIn,
1495: WritableRaster dstOut) {
1496: int[] srcPix = null;
1497: int[] dstPix = null;
1498:
1499: int x = dstOut.getMinX();
1500: int w = dstOut.getWidth();
1501:
1502: int y0 = dstOut.getMinY();
1503: int y1 = y0 + dstOut.getHeight();
1504:
1505: final int norm = (1 << 24) / 255;
1506: final int pt5 = (1 << 23);
1507:
1508: int sp, srcM, dstM, t1, t2;
1509:
1510: for (int y = y0; y < y1; y++) {
1511: srcPix = src.getPixels(x, y, w, 1, srcPix);
1512: dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
1513: sp = 0;
1514: final int end = w * 4;
1515: while (sp < end) {
1516: srcM = 255 - dstPix[sp + 3];
1517: dstM = 255 - srcPix[sp + 3];
1518:
1519: t1 = ((srcM * srcPix[sp] * norm + pt5) >>> 24)
1520: + dstPix[sp];
1521: t2 = ((dstM * dstPix[sp] * norm + pt5) >>> 24)
1522: + srcPix[sp];
1523: if (t1 > t2)
1524: dstPix[sp] = t1;
1525: else
1526: dstPix[sp] = t2;
1527: ++sp;
1528:
1529: t1 = ((srcM * srcPix[sp] * norm + pt5) >>> 24)
1530: + dstPix[sp];
1531: t2 = ((dstM * dstPix[sp] * norm + pt5) >>> 24)
1532: + srcPix[sp];
1533: if (t1 > t2)
1534: dstPix[sp] = t1;
1535: else
1536: dstPix[sp] = t2;
1537: ++sp;
1538:
1539: t1 = ((srcM * srcPix[sp] * norm + pt5) >>> 24)
1540: + dstPix[sp];
1541: t2 = ((dstM * dstPix[sp] * norm + pt5) >>> 24)
1542: + srcPix[sp];
1543: if (t1 > t2)
1544: dstPix[sp] = t1;
1545: else
1546: dstPix[sp] = t2;
1547: ++sp;
1548:
1549: dstPix[sp] = (srcPix[sp] + dstPix[sp] - ((dstPix[sp]
1550: * srcPix[sp] * norm + pt5) >>> 24));
1551: ++sp;
1552: }
1553: dstOut.setPixels(x, y, w, 1, dstPix);
1554: }
1555: }
1556: }
1557:
1558: public static class LightenCompositeContext_INT_PACK extends
1559: AlphaPreCompositeContext_INT_PACK {
1560: LightenCompositeContext_INT_PACK(ColorModel srcCM,
1561: ColorModel dstCM) {
1562: super (srcCM, dstCM);
1563: }
1564:
1565: public void precompose_INT_PACK(final int width,
1566: final int height, final int[] srcPixels,
1567: final int srcAdjust, int srcSp,
1568: final int[] dstInPixels, final int dstInAdjust,
1569: int dstInSp, final int[] dstOutPixels,
1570: final int dstOutAdjust, int dstOutSp) {
1571:
1572: final int norm = (1 << 24) / 255;
1573: final int pt5 = (1 << 23);
1574:
1575: int srcP, srcM;
1576: int dstP, dstM, dstA, dstR, dstG, dstB;
1577:
1578: int srcV, dstV, tmp;
1579:
1580: for (int y = 0; y < height; y++) {
1581: final int end = dstOutSp + width;
1582: while (dstOutSp < end) {
1583: srcP = srcPixels[srcSp++];
1584: dstP = dstInPixels[dstInSp++];
1585:
1586: srcV = (srcP >>> 24);
1587: dstV = (dstP >>> 24);
1588: srcM = (255 - dstV) * norm;
1589: dstM = (255 - srcV) * norm;
1590: dstA = (srcV + dstV - ((srcV * dstV * norm + pt5) >>> 24));
1591:
1592: srcV = (srcP >> 16) & 0xFF;
1593: dstV = (dstP >> 16) & 0xFF;
1594: dstR = ((srcM * srcV + pt5) >>> 24) + dstV;
1595: tmp = ((dstM * dstV + pt5) >>> 24) + srcV;
1596: if (dstR < tmp)
1597: dstR = tmp;
1598:
1599: srcV = (srcP >> 8) & 0xFF;
1600: dstV = (dstP >> 8) & 0xFF;
1601: dstG = ((srcM * srcV + pt5) >>> 24) + dstV;
1602: tmp = ((dstM * dstV + pt5) >>> 24) + srcV;
1603: if (dstG < tmp)
1604: dstG = tmp;
1605:
1606: srcV = (srcP) & 0xFF;
1607: dstV = (dstP) & 0xFF;
1608: dstB = ((srcM * srcV + pt5) >>> 24) + dstV;
1609: tmp = ((dstM * dstV + pt5) >>> 24) + srcV;
1610: if (dstB < tmp)
1611: dstB = tmp;
1612:
1613: dstA &= 0xFF; // trim to 8 bit
1614: dstR &= 0xFF;
1615: dstG &= 0xFF;
1616: dstB &= 0xFF;
1617:
1618: dstOutPixels[dstOutSp++] = ((dstA << 24)
1619: | (dstR << 16) | (dstG << 8) | dstB);
1620: }
1621: srcSp += srcAdjust;
1622: dstInSp += dstInAdjust;
1623: dstOutSp += dstOutAdjust;
1624: }
1625: }
1626: }
1627:
1628: }
|