/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.apache.batik.ext.awt.image.rendered;
import java.awt.Rectangle;
import java.awt.image.ColorModel;
import java.awt.image.DataBufferInt;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import org.apache.batik.ext.awt.image.GraphicsUtil;
import org.apache.batik.ext.awt.image.Light;
Author: Vincent Hardy Version: $Id: DiffuseLightingRed.java 1733416 2016-03-03 07:07:13Z gadams $
/**
*
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
* @version $Id: DiffuseLightingRed.java 1733416 2016-03-03 07:07:13Z gadams $
*/
public class DiffuseLightingRed extends AbstractRed{
Diffuse lighting constant
/**
* Diffuse lighting constant
*/
private double kd;
Light used for diffuse lighting
/**
* Light used for diffuse lighting
*/
private Light light;
BumpMap source
/**
* BumpMap source
*/
private BumpMap bumpMap;
Device space to user space scale factors, along
each axis
/**
* Device space to user space scale factors, along
* each axis
*/
private double scaleX, scaleY;
LitRegion
/**
* LitRegion
*/
private Rectangle litRegion;
true if calculations should be performed in linear sRGB
/**
* true if calculations should be performed in linear sRGB
*/
private boolean linear;
public DiffuseLightingRed(double kd,
Light light,
BumpMap bumpMap,
Rectangle litRegion,
double scaleX, double scaleY,
boolean linear){
this.kd = kd;
this.light = light;
this.bumpMap = bumpMap;
this.litRegion = litRegion;
this.scaleX = scaleX;
this.scaleY = scaleY;
this.linear = linear;
ColorModel cm;
if (linear)
cm = GraphicsUtil.Linear_sRGB_Pre;
else
cm = GraphicsUtil.sRGB_Pre;
SampleModel sm =
cm.createCompatibleSampleModel(litRegion.width,
litRegion.height);
init((CachableRed)null, litRegion, cm, sm,
litRegion.x, litRegion.y, null);
}
public WritableRaster copyData(WritableRaster wr){
final double[] lightColor = light.getColor(linear);
final int w = wr.getWidth();
final int h = wr.getHeight();
final int minX = wr.getMinX();
final int minY = wr.getMinY();
final DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
final int[] pixels = db.getBankData()[0];
final SinglePixelPackedSampleModel sppsm;
sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel();
final int offset =
(db.getOffset() +
sppsm.getOffset(minX-wr.getSampleModelTranslateX(),
minY-wr.getSampleModelTranslateY()));
final int scanStride = sppsm.getScanlineStride();
final int adjust = scanStride - w;
int p = offset;
int r=0, g=0, b=0;
int i=0, j=0;
// System.out.println("Getting diffuse red : " + minX + "/" + minY + "/" + w + "/" + h);
double x = scaleX*minX;
double y = scaleY*minY;
double NL = 0;
// final double[] L = new double[3];
final double[][][] NA = bumpMap.getNormalArray(minX, minY, w, h);
if(!light.isConstant()){
final double[][] LA = new double[w][3];
for(i=0; i<h; i++){
final double [][] NR = NA[i];
light.getLightRow(x, y+i*scaleY, scaleX, w, NR, LA);
for(j=0; j<w; j++){
// Get Normal
final double [] N = NR[j];
// Get Light Vector
final double [] L = LA[j];
NL = 255.*kd*(N[0]*L[0] + N[1]*L[1] + N[2]*L[2]);
r = (int)(NL*lightColor[0]);
g = (int)(NL*lightColor[1]);
b = (int)(NL*lightColor[2]);
// If any high bits are set we are not in range.
// If the highest bit is set then we are negative so
// clamp to zero else we are > 255 so clamp to 255.
if ((r & 0xFFFFFF00) != 0)
r = ((r & 0x80000000) != 0)?0:255;
if ((g & 0xFFFFFF00) != 0)
g = ((g & 0x80000000) != 0)?0:255;
if ((b & 0xFFFFFF00) != 0)
b = ((b & 0x80000000) != 0)?0:255;
pixels[p++] = (0xff000000
|
r << 16
|
g << 8
|
b);
}
p += adjust;
}
}
else{
// System.out.println(">>>>>>>> Processing constant light ...");
// Constant light
final double[] L = new double[3];
light.getLight(0, 0, 0, L);
for(i=0; i<h; i++){
final double [][] NR = NA[i];
for(j=0; j<w; j++){
// Get Normal
final double[] N = NR[j];
NL = 255.*kd*(N[0]*L[0] + N[1]*L[1] + N[2]*L[2]);
r = (int)(NL*lightColor[0]);
g = (int)(NL*lightColor[1]);
b = (int)(NL*lightColor[2]);
// If any high bits are set we are not in range.
// If the highest bit is set then we are negative so
// clamp to zero else we are > 255 so clamp to 255.
if ((r & 0xFFFFFF00) != 0)
r = ((r & 0x80000000) != 0)?0:255;
if ((g & 0xFFFFFF00) != 0)
g = ((g & 0x80000000) != 0)?0:255;
if ((b & 0xFFFFFF00) != 0)
b = ((b & 0x80000000) != 0)?0:255;
pixels[p++] = (0xff000000
|
r << 16
|
g << 8
|
b);
}
p += adjust;
}
}
return wr;
}
}