jhlabs-filters-2.0.235/0000755000175000017500000000000011242107015013635 5ustar varunvarunjhlabs-filters-2.0.235/META-INF/0000755000175000017500000000000010527110626015004 5ustar varunvarunjhlabs-filters-2.0.235/META-INF/MANIFEST.MF0000644000175000017500000000015610527110624016436 0ustar varunvarunManifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: 1.5.0_05-b05 (Sun Microsystems Inc.) jhlabs-filters-2.0.235/com/0000755000175000017500000000000010527103462014422 5ustar varunvarunjhlabs-filters-2.0.235/com/jhlabs/0000755000175000017500000000000010527103462015665 5ustar varunvarunjhlabs-filters-2.0.235/com/jhlabs/vecmath/0000755000175000017500000000000010527103464017316 5ustar varunvarunjhlabs-filters-2.0.235/com/jhlabs/vecmath/Vector4f.java0000644000175000017500000000260110521402274021647 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.vecmath; /** * Vector math package, converted to look similar to javax.vecmath. */ public class Vector4f extends Tuple4f { public Vector4f() { this( 0, 0, 0, 0 ); } public Vector4f( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; this.w = x[2]; } public Vector4f( float x, float y, float z, float w ) { this.x = x; this.y = y; this.z = z; this.w = w; } public Vector4f( Vector4f t ) { x = t.x; y = t.y; z = t.z; w = t.w; } public Vector4f( Tuple4f t ) { x = t.x; y = t.y; z = t.z; w = t.w; } public float dot( Vector4f v ) { return v.x * x + v.y * y + v.z * z + v.w * w; } public float length() { return (float)Math.sqrt( x*x+y*y+z*z+w*w ); } public void normalize() { float d = 1.0f/( x*x+y*y+z*z+w*w ); x *= d; y *= d; z *= d; w *= d; } } jhlabs-filters-2.0.235/com/jhlabs/vecmath/Tuple4f.java0000644000175000017500000000561510521402274021506 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.vecmath; /** * Vector math package, converted to look similar to javax.vecmath. */ public class Tuple4f { public float x, y, z, w; public Tuple4f() { this( 0, 0, 0, 0 ); } public Tuple4f( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; this.w = x[2]; } public Tuple4f( float x, float y, float z, float w ) { this.x = x; this.y = y; this.z = z; this.w = w; } public Tuple4f( Tuple4f t ) { this.x = t.x; this.y = t.y; this.z = t.z; this.w = t.w; } public void absolute() { x = Math.abs(x); y = Math.abs(y); z = Math.abs(z); w = Math.abs(w); } public void absolute( Tuple4f t ) { x = Math.abs(t.x); y = Math.abs(t.y); z = Math.abs(t.z); w = Math.abs(t.w); } public void clamp( float min, float max ) { if ( x < min ) x = min; else if ( x > max ) x = max; if ( y < min ) y = min; else if ( y > max ) y = max; if ( z < min ) z = min; else if ( z > max ) z = max; if ( w < min ) w = min; else if ( w > max ) w = max; } public void set( float x, float y, float z, float w ) { this.x = x; this.y = y; this.z = z; this.w = w; } public void set( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; this.w = x[2]; } public void set( Tuple4f t ) { x = t.x; y = t.y; z = t.z; w = t.w; } public void get( Tuple4f t ) { t.x = x; t.y = y; t.z = z; t.w = w; } public void get( float[] t ) { t[0] = x; t[1] = y; t[2] = z; t[3] = w; } public void negate() { x = -x; y = -y; z = -z; w = -w; } public void negate( Tuple4f t ) { x = -t.x; y = -t.y; z = -t.z; w = -t.w; } public void interpolate( Tuple4f t, float alpha ) { float a = 1-alpha; x = a*x + alpha*t.x; y = a*y + alpha*t.y; z = a*z + alpha*t.z; w = a*w + alpha*t.w; } public void scale( float s ) { x *= s; y *= s; z *= s; w *= s; } public void add( Tuple4f t ) { x += t.x; y += t.y; z += t.z; w += t.w; } public void add( Tuple4f t1, Tuple4f t2 ) { x = t1.x+t2.x; y = t1.y+t2.y; z = t1.z+t2.z; w = t1.w+t2.w; } public void sub( Tuple4f t ) { x -= t.x; y -= t.y; z -= t.z; w -= t.w; } public void sub( Tuple4f t1, Tuple4f t2 ) { x = t1.x-t2.x; y = t1.y-t2.y; z = t1.z-t2.z; w = t1.w-t2.w; } public String toString() { return "["+x+", "+y+", "+z+", "+w+"]"; } } jhlabs-filters-2.0.235/com/jhlabs/vecmath/Quat4f.java0000644000175000017500000000724510521402274021330 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.vecmath; /** * Vector math package, converted to look similar to javax.vecmath. */ public class Quat4f extends Tuple4f { public Quat4f() { this( 0, 0, 0, 0 ); } public Quat4f( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; this.w = x[3]; } public Quat4f( float x, float y, float z, float w ) { this.x = x; this.y = y; this.z = z; this.w = w; } public Quat4f( Quat4f t ) { this.x = t.x; this.y = t.y; this.z = t.z; this.w = t.w; } public Quat4f( Tuple4f t ) { this.x = t.x; this.y = t.y; this.z = t.z; this.w = t.w; } public void set( AxisAngle4f a ) { float halfTheta = a.angle * 0.5f; float cosHalfTheta = (float)Math.cos(halfTheta); float sinHalfTheta = (float)Math.sin(halfTheta); x = a.x * sinHalfTheta; y = a.y * sinHalfTheta; z = a.z * sinHalfTheta; w = cosHalfTheta; } /* public void EulerToQuaternion(float roll, float pitch, float yaw) { float cr, cp, cy, sr, sp, sy, cpcy, spsy; cr = cos(roll/2); cp = cos(pitch/2); cy = cos(yaw/2); sr = sin(roll/2); sp = sin(pitch/2); sy = sin(yaw/2); cpcy = cp * cy; spsy = sp * sy; w = cr * cpcy + sr * spsy; x = sr * cpcy - cr * spsy; y = cr * sp * cy + sr * cp * sy; z = cr * cp * sy - sr * sp * cy; } */ public void normalize() { float d = 1.0f/( x*x+y*y+z*z+w*w ); x *= d; y *= d; z *= d; w *= d; } /* public void mul( Quat4f q ) { Quat4f q3 = new Quat4f(); Vector3f vectorq1 = new Vector3f( x, y, z ); Vector3f vectorq2 = new Vector3f( q.x, q.y, q.z ); Vector3f tempvec1 = new Vector3f( vectorq1 ); Vector3f tempvec2; Vector3f tempvec3; q3.w = (w*q.w) - tempvec1.dot(vectorq2); tempvec1.cross(vectorq2); tempvec2.x = w * q.x; tempvec2.y = w * q.y; tempvec2.z = w * q.z; tempvec3.x = q.w * x; tempvec3.y = q.w * y; tempvec3.z = q.w * z; q3.x = tempvec1.x + tempvec2.x + tempvec3.x; q3.y = tempvec1.y + tempvec2.y + tempvec3.y; q3.z = tempvec1.z + tempvec2.z + tempvec3.z; set(q3); } */ public void set( Matrix4f m ) { float s; int i; float tr = m.m00 + m.m11 + m.m22; if (tr > 0.0) { s = (float)Math.sqrt(tr + 1.0f); w = s / 2.0f; s = 0.5f / s; x = (m.m12 - m.m21) * s; y = (m.m20 - m.m02) * s; z = (m.m01 - m.m10) * s; } else { i = 0; if ( m.m11 > m.m00 ) { i = 1; if ( m.m22 > m.m11 ) { i = 2; } else { } } else { if ( m.m22 > m.m00 ) { i = 2; } else { } } switch ( i ) { case 0: s = (float)Math.sqrt ((m.m00 - (m.m11 + m.m22)) + 1.0f); x = s * 0.5f; if (s != 0.0) s = 0.5f / s; w = (m.m12 - m.m21) * s; y = (m.m01 + m.m10) * s; z = (m.m02 + m.m20) * s; break; case 1: s = (float)Math.sqrt ((m.m11 - (m.m22 + m.m00)) + 1.0f); y = s * 0.5f; if (s != 0.0) s = 0.5f / s; w = (m.m20 - m.m02) * s; z = (m.m12 + m.m21) * s; x = (m.m10 + m.m01) * s; break; case 2: s = (float)Math.sqrt ((m.m00 - (m.m11 + m.m22)) + 1.0f); z = s * 0.5f; if (s != 0.0) s = 0.5f / s; w = (m.m01 - m.m10) * s; x = (m.m20 + m.m02) * s; y = (m.m21 + m.m12) * s; break; } } } } jhlabs-filters-2.0.235/com/jhlabs/vecmath/AxisAngle4f.java0000644000175000017500000000331110521402274022257 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.vecmath; /** * Vector math package, converted to look similar to javax.vecmath. */ public class AxisAngle4f { public float x, y, z, angle; public AxisAngle4f() { this( 0, 0, 0, 0 ); } public AxisAngle4f( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; this.angle = x[2]; } public AxisAngle4f( float x, float y, float z, float angle ) { this.x = x; this.y = y; this.z = z; this.angle = angle; } public AxisAngle4f( AxisAngle4f t ) { this.x = t.x; this.y = t.y; this.z = t.z; this.angle = t.angle; } public AxisAngle4f( Vector3f v, float angle ) { this.x = v.x; this.y = v.y; this.z = v.z; this.angle = angle; } public void set( float x, float y, float z, float angle ) { this.x = x; this.y = y; this.z = z; this.angle = angle; } public void set( AxisAngle4f t ) { x = t.x; y = t.y; z = t.z; angle = t.angle; } public void get( AxisAngle4f t ) { t.x = x; t.y = y; t.z = z; t.angle = angle; } public void get( float[] t ) { t[0] = x; t[1] = y; t[2] = z; t[3] = angle; } public String toString() { return "["+x+", "+y+", "+z+", "+angle+"]"; } } jhlabs-filters-2.0.235/com/jhlabs/vecmath/Matrix4f.java0000644000175000017500000001470210521402274021656 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.vecmath; /** * Vector math package, converted to look similar to javax.vecmath. */ public class Matrix4f { public float m00, m01, m02, m03; public float m10, m11, m12, m13; public float m20, m21, m22, m23; public float m30, m31, m32, m33; public Matrix4f() { setIdentity(); } public Matrix4f( Matrix4f m ) { set( m ); } public Matrix4f(float[] m) { set( m ); } public void set( Matrix4f m) { m00 = m.m00; m01 = m.m01; m02 = m.m02; m03 = m.m03; m10 = m.m10; m11 = m.m11; m12 = m.m12; m13 = m.m13; m20 = m.m20; m21 = m.m21; m22 = m.m22; m23 = m.m23; m30 = m.m30; m31 = m.m31; m32 = m.m32; m33 = m.m33; } public void set(float[] m) { m00 = m[0]; m01 = m[1]; m02 = m[2]; m03 = m[3]; m10 = m[4]; m11 = m[5]; m12 = m[6]; m13 = m[7]; m20 = m[8]; m21 = m[9]; m22 = m[10]; m23 = m[11]; m30 = m[12]; m31 = m[13]; m32 = m[14]; m33 = m[15]; } public void get( Matrix4f m) { m.m00 = m00; m.m01 = m01; m.m02 = m02; m.m03 = m03; m.m10 = m10; m.m11 = m11; m.m12 = m12; m.m13 = m13; m.m20 = m20; m.m21 = m21; m.m22 = m22; m.m23 = m23; m.m30 = m30; m.m31 = m31; m.m32 = m32; m.m33 = m33; } public void get(float[] m) { m[0] = m00; m[1] = m01; m[2] = m02; m[3] = m03; m[4] = m10; m[5] = m11; m[6] = m12; m[7] = m13; m[8] = m20; m[9] = m21; m[10] = m22; m[11] = m23; m[12] = m30; m[13] = m31; m[14] = m32; m[15] = m33; } public void setIdentity() { m00 = 1.0f; m01 = 0.0f; m02 = 0.0f; m03 = 0.0f; m10 = 0.0f; m11 = 1.0f; m12 = 0.0f; m13 = 0.0f; m20 = 0.0f; m21 = 0.0f; m22 = 1.0f; m23 = 0.0f; m30 = 0.0f; m31 = 0.0f; m32 = 0.0f; m33 = 1.0f; } public void mul( Matrix4f m ) { float tm00 = m00; float tm01 = m01; float tm02 = m02; float tm03 = m03; float tm10 = m10; float tm11 = m11; float tm12 = m12; float tm13 = m13; float tm20 = m20; float tm21 = m21; float tm22 = m22; float tm23 = m23; float tm30 = m30; float tm31 = m31; float tm32 = m32; float tm33 = m33; m00 = tm00*m.m00 + tm10*m.m01 + tm20*m.m02 + tm30*m.m03; m01 = tm01*m.m00 + tm11*m.m01 + tm21*m.m02 + tm31*m.m03; m02 = tm02*m.m00 + tm12*m.m01 + tm22*m.m02 + tm32*m.m03; m03 = tm03*m.m00 + tm13*m.m01 + tm23*m.m02 + tm33*m.m03; m10 = tm00*m.m10 + tm10*m.m11 + tm20*m.m12 + tm30*m.m13; m11 = tm01*m.m10 + tm11*m.m11 + tm21*m.m12 + tm31*m.m13; m12 = tm02*m.m10 + tm12*m.m11 + tm22*m.m12 + tm32*m.m13; m13 = tm03*m.m10 + tm13*m.m11 + tm23*m.m12 + tm33*m.m13; m20 = tm00*m.m20 + tm10*m.m21 + tm20*m.m22 + tm30*m.m23; m21 = tm01*m.m20 + tm11*m.m21 + tm21*m.m22 + tm31*m.m23; m22 = tm02*m.m20 + tm12*m.m21 + tm22*m.m22 + tm32*m.m23; m23 = tm03*m.m20 + tm13*m.m21 + tm23*m.m22 + tm33*m.m23; m30 = tm00*m.m30 + tm10*m.m31 + tm20*m.m32 + tm30*m.m33; m31 = tm01*m.m30 + tm11*m.m31 + tm21*m.m32 + tm31*m.m33; m32 = tm02*m.m30 + tm12*m.m31 + tm22*m.m32 + tm32*m.m33; m33 = tm03*m.m30 + tm13*m.m31 + tm23*m.m32 + tm33*m.m33; } public void invert() { Matrix4f t = new Matrix4f( this ); invert( t ); } public void invert( Matrix4f t ) { m00 = t.m00; m01 = t.m10; m02 = t.m20; m03 = t.m03; m10 = t.m01; m11 = t.m11; m12 = t.m21; m13 = t.m13; m20 = t.m02; m21 = t.m12; m22 = t.m22; m23 = t.m23; m30 *= -1.0f; m31 *= -1.0f; m32 *= -1.0f; m33 = t.m33; } public void set( AxisAngle4f a ) { float halfTheta = a.angle * 0.5f; float cosHalfTheta = (float)Math.cos(halfTheta); float sinHalfTheta = (float)Math.sin(halfTheta); set( new Quat4f( a.x * sinHalfTheta, a.y * sinHalfTheta, a.z * sinHalfTheta, cosHalfTheta ) ); } public void set( Quat4f q ) { float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2; x2 = q.x + q.x; y2 = q.y + q.y; z2 = q.z + q.z; xx = q.x * x2; xy = q.x * y2; xz = q.x * z2; yy = q.y * y2; yz = q.y * z2; zz = q.z * z2; wx = q.w * x2; wy = q.w * y2; wz = q.w * z2; m00 = 1.0f - (yy + zz); m01 = xy - wz; m02 = xz + wy; m03 = 0.0f; m10 = xy + wz; m11 = 1.0f - (xx + zz); m12 = yz - wx; m13 = 0.0f; m20 = xz - wy; m21 = yz + wx; m22 = 1.0f - (xx + yy); m23 = 0.0f; m30 = 0; m31 = 0; m32 = 0; m33 = 1; } public void transform( Point3f v ) { float x = v.x * m00 + v.y * m10 + v.z * m20 + m30; float y = v.x * m01 + v.y * m11 + v.z * m21 + m31; float z = v.x * m02 + v.y * m12 + v.z * m22 + m32; v.x = x; v.y = y; v.z = z; } public void transform( Vector3f v ) { float x = v.x * m00 + v.y * m10 + v.z * m20; float y = v.x * m01 + v.y * m11 + v.z * m21; float z = v.x * m02 + v.y * m12 + v.z * m22; v.x = x; v.y = y; v.z = z; } public void setTranslation( Vector3f v ) { m30 = v.x; m31 = v.y; m32 = v.z; } public void set( float scale ) { m00 = scale; m11 = scale; m22 = scale; } public void rotX( float angle ) { float s = (float)Math.sin( angle ); float c = (float)Math.cos( angle ); m00 = 1.0f; m01 = 0.0f; m02 = 0.0f; m03 = 0.0f; m10 = 0.0f; m11 = c; m12 = s; m13 = 0.0f; m20 = 0.0f; m21 = -s; m22 = c; m23 = 0.0f; m30 = 0.0f; m31 = 0.0f; m32 = 0.0f; m33 = 1.0f; } public void rotY( float angle ) { float s = (float)Math.sin( angle ); float c = (float)Math.cos( angle ); m00 = c; m01 = 0.0f; m02 = -s; m03 = 0.0f; m10 = 0.0f; m11 = 1.0f; m12 = 0.0f; m13 = 0.0f; m20 = s; m21 = 0.0f; m22 = c; m23 = 0.0f; m30 = 0.0f; m31 = 0.0f; m32 = 0.0f; m33 = 1.0f; } public void rotZ( float angle ) { float s = (float)Math.sin( angle ); float c = (float)Math.cos( angle ); m00 = c; m01 = s; m02 = 0.0f; m03 = 0.0f; m10 = -s; m11 = c; m12 = 0.0f; m13 = 0.0f; m20 = 0.0f; m21 = 0.0f; m22 = 1.0f; m23 = 0.0f; m30 = 0.0f; m31 = 0.0f; m32 = 0.0f; m33 = 1.0f; } /* void rotate(float angle, float x, float y, float z) { Matrix4f m = new Matrix4f();//FIXME m.MatrixFromAxisAngle(Vector3f(x, y, z), angle); Multiply(m); } */ } jhlabs-filters-2.0.235/com/jhlabs/vecmath/Point3f.java0000644000175000017500000000272210521402274021501 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.vecmath; /** * Vector math package, converted to look similar to javax.vecmath. */ public class Point3f extends Tuple3f { public Point3f() { this( 0, 0, 0 ); } public Point3f( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; } public Point3f( float x, float y, float z ) { this.x = x; this.y = y; this.z = z; } public Point3f( Point3f t ) { this.x = t.x; this.y = t.y; this.z = t.z; } public Point3f( Tuple3f t ) { this.x = t.x; this.y = t.y; this.z = t.z; } public float distanceL1( Point3f p ) { return Math.abs(x-p.x) + Math.abs(y-p.y) + Math.abs(z-p.z); } public float distanceSquared( Point3f p ) { float dx = x-p.x; float dy = y-p.y; float dz = z-p.z; return dx*dx+dy*dy+dz*dz; } public float distance( Point3f p ) { float dx = x-p.x; float dy = y-p.y; float dz = z-p.z; return (float)Math.sqrt( dx*dx+dy*dy+dz*dz ); } } jhlabs-filters-2.0.235/com/jhlabs/vecmath/Color4f.java0000644000175000017500000000252710521402274021472 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.vecmath; import java.awt.*; /** * Vector math package, converted to look similar to javax.vecmath. */ public class Color4f extends Tuple4f { public Color4f() { this( 0, 0, 0, 0 ); } public Color4f( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; this.w = x[3]; } public Color4f( float x, float y, float z, float w ) { this.x = x; this.y = y; this.z = z; this.w = w; } public Color4f( Color4f t ) { this.x = t.x; this.y = t.y; this.z = t.z; this.w = t.w; } public Color4f( Tuple4f t ) { this.x = t.x; this.y = t.y; this.z = t.z; this.w = t.w; } public Color4f( Color c ) { set( c ); } public void set( Color c ) { set( c.getRGBComponents( null ) ); } public Color get() { return new Color( x, y, z, w ); } } jhlabs-filters-2.0.235/com/jhlabs/vecmath/Tuple3f.java0000644000175000017500000000540210521402274021477 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.vecmath; /** * Vector math package, converted to look similar to javax.vecmath. */ public class Tuple3f { public float x, y, z; public Tuple3f() { this( 0, 0, 0 ); } public Tuple3f( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; } public Tuple3f( float x, float y, float z ) { this.x = x; this.y = y; this.z = z; } public Tuple3f( Tuple3f t ) { this.x = t.x; this.y = t.y; this.z = t.z; } public void absolute() { x = Math.abs(x); y = Math.abs(y); z = Math.abs(z); } public void absolute( Tuple3f t ) { x = Math.abs(t.x); y = Math.abs(t.y); z = Math.abs(t.z); } public void clamp( float min, float max ) { if ( x < min ) x = min; else if ( x > max ) x = max; if ( y < min ) y = min; else if ( y > max ) y = max; if ( z < min ) z = min; else if ( z > max ) z = max; } public void set( float x, float y, float z ) { this.x = x; this.y = y; this.z = z; } public void set( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; } public void set( Tuple3f t ) { x = t.x; y = t.y; z = t.z; } public void get( Tuple3f t ) { t.x = x; t.y = y; t.z = z; } public void get( float[] t ) { t[0] = x; t[1] = y; t[2] = z; } public void negate() { x = -x; y = -y; z = -z; } public void negate( Tuple3f t ) { x = -t.x; y = -t.y; z = -t.z; } public void interpolate( Tuple3f t, float alpha ) { float a = 1-alpha; x = a*x + alpha*t.x; y = a*y + alpha*t.y; z = a*z + alpha*t.z; } public void scale( float s ) { x *= s; y *= s; z *= s; } public void add( Tuple3f t ) { x += t.x; y += t.y; z += t.z; } public void add( Tuple3f t1, Tuple3f t2 ) { x = t1.x+t2.x; y = t1.y+t2.y; z = t1.z+t2.z; } public void sub( Tuple3f t ) { x -= t.x; y -= t.y; z -= t.z; } public void sub( Tuple3f t1, Tuple3f t2 ) { x = t1.x-t2.x; y = t1.y-t2.y; z = t1.z-t2.z; } public void scaleAdd( float s, Tuple3f t ) { x += s*t.x; y += s*t.y; z += s*t.z; } public void scaleAdd( float s, Tuple3f t1, Tuple3f t2 ) { x = s*t1.x + t2.x; y = s*t1.y + t2.y; z = s*t1.z + t2.z; } public String toString() { return "["+x+", "+y+", "+z+"]"; } } jhlabs-filters-2.0.235/com/jhlabs/vecmath/Point4f.java0000644000175000017500000000314310521402274021500 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.vecmath; /** * Vector math package, converted to look similar to javax.vecmath. */ public class Point4f extends Tuple4f { public Point4f() { this( 0, 0, 0, 0 ); } public Point4f( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; this.w = x[3]; } public Point4f( float x, float y, float z, float w ) { this.x = x; this.y = y; this.z = z; this.w = w; } public Point4f( Point4f t ) { this.x = t.x; this.y = t.y; this.z = t.z; this.w = t.w; } public Point4f( Tuple4f t ) { this.x = t.x; this.y = t.y; this.z = t.z; this.w = t.w; } public float distanceL1( Point4f p ) { return Math.abs(x-p.x) + Math.abs(y-p.y) + Math.abs(z-p.z) + Math.abs(w-p.w); } public float distanceSquared( Point4f p ) { float dx = x-p.x; float dy = y-p.y; float dz = z-p.z; float dw = w-p.w; return dx*dx+dy*dy+dz*dz+dw*dw; } public float distance( Point4f p ) { float dx = x-p.x; float dy = y-p.y; float dz = z-p.z; float dw = w-p.w; return (float)Math.sqrt( dx*dx+dy*dy+dz*dz+dw*dw ); } } jhlabs-filters-2.0.235/com/jhlabs/vecmath/Vector3f.java0000644000175000017500000000311710521402274021651 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.vecmath; /** * Vector math package, converted to look similar to javax.vecmath. */ public class Vector3f extends Tuple3f { public Vector3f() { this( 0, 0, 0 ); } public Vector3f( float[] x ) { this.x = x[0]; this.y = x[1]; this.z = x[2]; } public Vector3f( float x, float y, float z ) { this.x = x; this.y = y; this.z = z; } public Vector3f( Vector3f t ) { this.x = t.x; this.y = t.y; this.z = t.z; } public Vector3f( Tuple3f t ) { this.x = t.x; this.y = t.y; this.z = t.z; } public float angle( Vector3f v ) { return (float)Math.acos( dot(v) / (length()*v.length()) ); } public float dot( Vector3f v ) { return v.x * x + v.y * y + v.z * z; } public void cross( Vector3f v1, Vector3f v2 ) { x = v1.y * v2.z - v1.z * v2.y; y = v1.z * v2.x - v1.x * v2.z; z = v1.x * v2.y - v1.y * v2.x; } public float length() { return (float)Math.sqrt( x*x+y*y+z*z ); } public void normalize() { float d = 1.0f/(float)Math.sqrt( x*x+y*y+z*z ); x *= d; y *= d; z *= d; } } jhlabs-filters-2.0.235/com/jhlabs/image/0000755000175000017500000000000010527103462016747 5ustar varunvarunjhlabs-filters-2.0.235/com/jhlabs/image/WaterFilter.java0000644000175000017500000000572110521402274022044 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import com.jhlabs.math.*; public class WaterFilter extends TransformFilter { static final long serialVersionUID = 8789236343162990941L; private float wavelength = 16; private float amplitude = 10; private float phase = 0; private float centreX = 0.5f; private float centreY = 0.5f; private float radius = 50; private float radius2 = 0; private float icentreX; private float icentreY; public WaterFilter() { setEdgeAction( CLAMP ); } public void setWavelength(float wavelength) { this.wavelength = wavelength; } public float getWavelength() { return wavelength; } public void setAmplitude(float amplitude) { this.amplitude = amplitude; } public float getAmplitude() { return amplitude; } public void setPhase(float phase) { this.phase = phase; } public float getPhase() { return phase; } public void setCentreX( float centreX ) { this.centreX = centreX; } public float getCentreX() { return centreX; } public void setCentreY( float centreY ) { this.centreY = centreY; } public float getCentreY() { return centreY; } public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } public void setRadius(float radius) { this.radius = radius; } public float getRadius() { return radius; } private boolean inside(int v, int a, int b) { return a <= v && v <= b; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { icentreX = src.getWidth() * centreX; icentreY = src.getHeight() * centreY; if ( radius == 0 ) radius = Math.min(icentreX, icentreY); radius2 = radius*radius; return super.filter( src, dst ); } protected void transformInverse(int x, int y, float[] out) { float dx = x-icentreX; float dy = y-icentreY; float distance2 = dx*dx + dy*dy; if (distance2 > radius2) { out[0] = x; out[1] = y; } else { float distance = (float)Math.sqrt(distance2); float amount = amplitude * (float)Math.sin(distance / wavelength * ImageMath.TWO_PI - phase); amount *= (radius-distance)/radius; if ( distance != 0 ) amount *= wavelength/distance; out[0] = x + dx*amount; out[1] = y + dy*amount; } } public String toString() { return "Distort/Water Ripples..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/TransformFilter.java0000644000175000017500000001317610521402274022740 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * An abstract superclass for filters which distort images in some way. The subclass only needs to override * two methods to provide the mapping between source and destination pixels. */ public abstract class TransformFilter extends AbstractBufferedImageOp { public final static int ZERO = 0; public final static int CLAMP = 1; public final static int WRAP = 2; public final static int NEAREST_NEIGHBOUR = 0; public final static int BILINEAR = 1; protected int edgeAction = ZERO; protected int interpolation = BILINEAR; protected Rectangle transformedSpace; protected Rectangle originalSpace; public void setEdgeAction(int edgeAction) { this.edgeAction = edgeAction; } public int getEdgeAction() { return edgeAction; } public void setInterpolation(int interpolation) { this.interpolation = interpolation; } public int getInterpolation() { return interpolation; } protected abstract void transformInverse(int x, int y, float[] out); protected void transformSpace(Rectangle rect) { } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int type = src.getType(); WritableRaster srcRaster = src.getRaster(); originalSpace = new Rectangle(0, 0, width, height); transformedSpace = new Rectangle(0, 0, width, height); transformSpace(transformedSpace); if ( dst == null ) { ColorModel dstCM = src.getColorModel(); dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(transformedSpace.width, transformedSpace.height), dstCM.isAlphaPremultiplied(), null); } WritableRaster dstRaster = dst.getRaster(); int[] inPixels = getRGB( src, 0, 0, width, height, null ); if ( interpolation == NEAREST_NEIGHBOUR ) return filterPixelsNN( dst, width, height, inPixels, transformedSpace ); int srcWidth = width; int srcHeight = height; int srcWidth1 = width-1; int srcHeight1 = height-1; int outWidth = transformedSpace.width; int outHeight = transformedSpace.height; int outX, outY; int index = 0; int[] outPixels = new int[outWidth]; outX = transformedSpace.x; outY = transformedSpace.y; float[] out = new float[2]; for (int y = 0; y < outHeight; y++) { for (int x = 0; x < outWidth; x++) { transformInverse(outX+x, outY+y, out); int srcX = (int)Math.floor( out[0] ); int srcY = (int)Math.floor( out[1] ); float xWeight = out[0]-srcX; float yWeight = out[1]-srcY; int nw, ne, sw, se; if ( srcX >= 0 && srcX < srcWidth1 && srcY >= 0 && srcY < srcHeight1) { // Easy case, all corners are in the image int i = srcWidth*srcY + srcX; nw = inPixels[i]; ne = inPixels[i+1]; sw = inPixels[i+srcWidth]; se = inPixels[i+srcWidth+1]; } else { // Some of the corners are off the image nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight ); ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight ); sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight ); se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight ); } outPixels[x] = ImageMath.bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se); } setRGB( dst, 0, y, transformedSpace.width, 1, outPixels ); } return dst; } final private int getPixel( int[] pixels, int x, int y, int width, int height ) { if (x < 0 || x >= width || y < 0 || y >= height) { switch (edgeAction) { case ZERO: default: return 0; case WRAP: return pixels[(ImageMath.mod(y, height) * width) + ImageMath.mod(x, width)]; case CLAMP: return pixels[(ImageMath.clamp(y, 0, height-1) * width) + ImageMath.clamp(x, 0, width-1)]; } } return pixels[ y*width+x ]; } protected BufferedImage filterPixelsNN( BufferedImage dst, int width, int height, int[] inPixels, Rectangle transformedSpace ) { int srcWidth = width; int srcHeight = height; int outWidth = transformedSpace.width; int outHeight = transformedSpace.height; int outX, outY, srcX, srcY; int[] outPixels = new int[outWidth]; outX = transformedSpace.x; outY = transformedSpace.y; int[] rgb = new int[4]; float[] out = new float[2]; for (int y = 0; y < outHeight; y++) { for (int x = 0; x < outWidth; x++) { transformInverse(outX+x, outY+y, out); srcX = (int)out[0]; srcY = (int)out[1]; // int casting rounds towards zero, so we check out[0] < 0, not srcX < 0 if (out[0] < 0 || srcX >= srcWidth || out[1] < 0 || srcY >= srcHeight) { int p; switch (edgeAction) { case ZERO: default: p = 0; break; case WRAP: p = inPixels[(ImageMath.mod(srcY, srcHeight) * srcWidth) + ImageMath.mod(srcX, srcWidth)]; break; case CLAMP: p = inPixels[(ImageMath.clamp(srcY, 0, srcHeight-1) * srcWidth) + ImageMath.clamp(srcX, 0, srcWidth-1)]; break; } outPixels[x] = p; } else { int i = srcWidth*srcY + srcX; rgb[0] = inPixels[i]; outPixels[x] = inPixels[i]; } } setRGB( dst, 0, y, transformedSpace.width, 1, outPixels ); } return dst; } } jhlabs-filters-2.0.235/com/jhlabs/image/SolarizeFilter.java0000644000175000017500000000155010521402274022546 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A filter which solarizes an image. */ public class SolarizeFilter extends TransferFilter { protected float transferFunction( float v ) { return v > 0.5f ? 2*(v-0.5f) : 2*(0.5f-v); } public String toString() { return "Colors/Solarize"; } } jhlabs-filters-2.0.235/com/jhlabs/image/WeaveFilter.java0000644000175000017500000001003210521402274022020 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class WeaveFilter extends PointFilter implements java.io.Serializable { static final long serialVersionUID = 4847932412277504482L; private float xWidth = 16; private float yWidth = 16; private float xGap = 6; private float yGap = 6; private int rows = 4; private int cols = 4; private int rgbX = 0xffff8080; private int rgbY = 0xff8080ff; private boolean useImageColors = true; private boolean roundThreads = false; private boolean shadeCrossings = true; public int[][] matrix = { { 0, 1, 0, 1 }, { 1, 0, 1, 0 }, { 0, 1, 0, 1 }, { 1, 0, 1, 0 }, }; public WeaveFilter() { } public void setXGap(float xGap) { this.xGap = xGap; } public void setXWidth(float xWidth) { this.xWidth = xWidth; } public float getXWidth() { return xWidth; } public void setYWidth(float yWidth) { this.yWidth = yWidth; } public float getYWidth() { return yWidth; } public float getXGap() { return xGap; } public void setYGap(float yGap) { this.yGap = yGap; } public float getYGap() { return yGap; } public void setCrossings(int[][] matrix) { this.matrix = matrix; } public int[][] getCrossings() { return matrix; } public void setUseImageColors(boolean useImageColors) { this.useImageColors = useImageColors; } public boolean getUseImageColors() { return useImageColors; } public void setRoundThreads(boolean roundThreads) { this.roundThreads = roundThreads; } public boolean getRoundThreads() { return roundThreads; } public void setShadeCrossings(boolean shadeCrossings) { this.shadeCrossings = shadeCrossings; } public boolean getShadeCrossings() { return shadeCrossings; } public int filterRGB(int x, int y, int rgb) { x += xWidth+xGap/2; y += yWidth+yGap/2; float nx = ImageMath.mod(x, xWidth+xGap); float ny = ImageMath.mod(y, yWidth+yGap); int ix = (int)(x / (xWidth+xGap)); int iy = (int)(y / (yWidth+yGap)); boolean inX = nx < xWidth; boolean inY = ny < yWidth; float dX, dY; float cX, cY; int lrgbX, lrgbY; if (roundThreads) { dX = Math.abs(xWidth/2-nx) / xWidth / 2; dY = Math.abs(yWidth/2-ny) / yWidth / 2; } else { dX = dY = 0; } if (shadeCrossings) { cX = ImageMath.smoothStep(xWidth/2, xWidth/2+xGap, Math.abs(xWidth/2-nx)); cY = ImageMath.smoothStep(yWidth/2, yWidth/2+yGap, Math.abs(yWidth/2-ny)); } else { cX = cY = 0; } if (useImageColors) { lrgbX = lrgbY = rgb; } else { lrgbX = rgbX; lrgbY = rgbY; } int v; int ixc = ix % cols; int iyr = iy % rows; int m = matrix[iyr][ixc]; if (inX) { if (inY) { v = m == 1 ? lrgbX : lrgbY; v = ImageMath.mixColors(2 * (m == 1 ? dX : dY), v, 0xff000000); } else { if (shadeCrossings) { if (m != matrix[(iy+1) % rows][ixc]) { if (m == 0) cY = 1-cY; cY *= 0.5f; lrgbX = ImageMath.mixColors(cY, lrgbX, 0xff000000); } else if (m == 0) lrgbX = ImageMath.mixColors(0.5f, lrgbX, 0xff000000); } v = ImageMath.mixColors(2 * dX, lrgbX, 0xff000000); } } else if (inY) { if (shadeCrossings) { if (m != matrix[iyr][(ix+1) % cols]) { if (m == 1) cX = 1-cX; cX *= 0.5f; lrgbY = ImageMath.mixColors(cX, lrgbY, 0xff000000); } else if (m == 1) lrgbY = ImageMath.mixColors(0.5f, lrgbY, 0xff000000); } v = ImageMath.mixColors(2 * dY, lrgbY, 0xff000000); } else v = 0x00000000; return v; } public String toString() { return "Texture/Weave..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/LookupFilter.java0000644000175000017500000000262110521402274022227 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter which uses the brightness of each pixel to lookup a color from a colormap. */ public class LookupFilter extends PointFilter { private Colormap colormap = new Gradient(); public LookupFilter() { canFilterIndexColorModel = true; } public LookupFilter(Colormap colormap) { canFilterIndexColorModel = true; this.colormap = colormap; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public int filterRGB(int x, int y, int rgb) { // int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; rgb = (r + g + b) / 3; return colormap.getColor(rgb/255.0f); } public String toString() { return "Colors/Lookup..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/PinchFilter.java0000644000175000017500000000573410521402274022027 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; public class PinchFilter extends TransformFilter { private float angle = 0; private float centreX = 0.5f; private float centreY = 0.5f; private float radius = 100; private float amount = 0.5f; private float radius2 = 0; private float icentreX; private float icentreY; private float width; private float height; public PinchFilter() { } /** * Set the angle of twirl in radians. 0 means no distortion. * @param angle the angle of twirl. This is the angle by which pixels at the nearest edge of the image will move. */ public void setAngle(float angle) { this.angle = angle; } /** * Get the angle of twist. * @return the angle in radians. */ public float getAngle() { return angle; } public void setCentreX( float centreX ) { this.centreX = centreX; } public float getCentreX() { return centreX; } public void setCentreY( float centreY ) { this.centreY = centreY; } public float getCentreY() { return centreY; } public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } public void setRadius(float radius) { this.radius = radius; } public float getRadius() { return radius; } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { width = src.getWidth(); height = src.getHeight(); icentreX = width * centreX; icentreY = height * centreY; if ( radius == 0 ) radius = Math.min(icentreX, icentreY); radius2 = radius*radius; return super.filter( src, dst ); } protected void transformInverse(int x, int y, float[] out) { float dx = x-icentreX; float dy = y-icentreY; float distance = dx*dx + dy*dy; if ( distance > radius2 || distance == 0 ) { out[0] = x; out[1] = y; } else { float d = (float)Math.sqrt( distance / radius2 ); float t = (float)Math.pow( Math.sin( Math.PI*0.5 * d ), -amount); dx *= t; dy *= t; float e = 1 - d; float a = angle * e * e; float s = (float)Math.sin( a ); float c = (float)Math.cos( a ); out[0] = icentreX + c*dx - s*dy; out[1] = icentreY + s*dx + c*dy; } } public String toString() { return "Distort/Pinch..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/GaussianFilter.java0000644000175000017500000001052610521402272022531 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A filter which applies Gaussian blur to an image. This is a subclass of ConvolveFilter * which simply creates a kernel with a Gaussian distribution for blurring. * @author Jerry Huxtable */ public class GaussianFilter extends ConvolveFilter { protected float radius; protected Kernel kernel; /** * Construct a Gaussian filter */ public GaussianFilter() { this(2); } /** * Construct a Gaussian filter * @param radius blur radius in pixels */ public GaussianFilter(float radius) { setRadius(radius); } /** * Set the radius of the kernel, and hence the amount of blur. The bigger the radius, the longer this filter will take. * @param radius the radius of the blur in pixels. */ public void setRadius(float radius) { this.radius = radius; kernel = makeKernel(radius); } /** * Get the radius of the kernel. * @return the radius */ public float getRadius() { return radius; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; src.getRGB( 0, 0, width, height, inPixels, 0, width ); if ( radius > 0 ) { convolveAndTranspose(kernel, inPixels, outPixels, width, height, alpha, CLAMP_EDGES); convolveAndTranspose(kernel, outPixels, inPixels, height, width, alpha, CLAMP_EDGES); } dst.setRGB( 0, 0, width, height, inPixels, 0, width ); return dst; } public static void convolveAndTranspose(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, boolean alpha, int edgeAction) { float[] matrix = kernel.getKernelData( null ); int cols = kernel.getWidth(); int cols2 = cols/2; for (int y = 0; y < height; y++) { int index = y; int ioffset = y*width; for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; int moffset = cols2; for (int col = -cols2; col <= cols2; col++) { float f = matrix[moffset+col]; if (f != 0) { int ix = x+col; if ( ix < 0 ) { if ( edgeAction == CLAMP_EDGES ) ix = 0; else if ( edgeAction == WRAP_EDGES ) ix = (x+width) % width; } else if ( ix >= width) { if ( edgeAction == CLAMP_EDGES ) ix = width-1; else if ( edgeAction == WRAP_EDGES ) ix = (x+width) % width; } int rgb = inPixels[ioffset+ix]; a += f * ((rgb >> 24) & 0xff); r += f * ((rgb >> 16) & 0xff); g += f * ((rgb >> 8) & 0xff); b += f * (rgb & 0xff); } } int ia = alpha ? PixelUtils.clamp((int)(a+0.5)) : 0xff; int ir = PixelUtils.clamp((int)(r+0.5)); int ig = PixelUtils.clamp((int)(g+0.5)); int ib = PixelUtils.clamp((int)(b+0.5)); outPixels[index] = (ia << 24) | (ir << 16) | (ig << 8) | ib; index += height; } } } /** * Make a Gaussian blur kernel. */ public static Kernel makeKernel(float radius) { int r = (int)Math.ceil(radius); int rows = r*2+1; float[] matrix = new float[rows]; float sigma = radius/3; float sigma22 = 2*sigma*sigma; float sigmaPi2 = 2*ImageMath.PI*sigma; float sqrtSigmaPi2 = (float)Math.sqrt(sigmaPi2); float radius2 = radius*radius; float total = 0; int index = 0; for (int row = -r; row <= r; row++) { float distance = row*row; if (distance > radius2) matrix[index] = 0; else matrix[index] = (float)Math.exp(-(distance)/sigma22) / sqrtSigmaPi2; total += matrix[index]; index++; } for (int i = 0; i < rows; i++) matrix[i] /= total; return new Kernel(rows, 1, matrix); } public String toString() { return "Blur/Gaussian Blur..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/Histogram.java0000644000175000017500000001030010521402274021536 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * An image histogram. */ public class Histogram { public static final int RED = 0; public static final int GREEN = 1; public static final int BLUE = 2; public static final int GRAY = 3; protected int[][] histogram; protected int numSamples; protected int[] minValue; protected int[] maxValue; protected int[] minFrequency; protected int[] maxFrequency; protected float[] mean; protected boolean isGray; public Histogram() { histogram = null; numSamples = 0; isGray = true; minValue = null; maxValue = null; minFrequency = null; maxFrequency = null; mean = null; } public Histogram(int[] pixels, int w, int h, int offset, int stride) { histogram = new int[3][256]; minValue = new int[4]; maxValue = new int[4]; minFrequency = new int[3]; maxFrequency = new int[3]; mean = new float[3]; numSamples = w*h; isGray = true; int index = 0; for (int y = 0; y < h; y++) { index = offset+y*stride; for (int x = 0; x < w; x++) { int rgb = pixels[index++]; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; histogram[RED][r]++; histogram[GREEN][g]++; histogram[BLUE][b]++; } } for (int i = 0; i < 256; i++) { if (histogram[RED][i] != histogram[GREEN][i] || histogram[GREEN][i] != histogram[BLUE][i]) { isGray = false; break; } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 256; j++) { if (histogram[i][j] > 0) { minValue[i] = j; break; } } for (int j = 255; j >= 0; j--) { if (histogram[i][j] > 0) { maxValue[i] = j; break; } } minFrequency[i] = Integer.MAX_VALUE; maxFrequency[i] = 0; for (int j = 0; j < 256; j++) { minFrequency[i] = Math.min(minFrequency[i], histogram[i][j]); maxFrequency[i] = Math.max(maxFrequency[i], histogram[i][j]); mean[i] += (float)(j*histogram[i][j]); } mean[i] /= (float)numSamples; } minValue[GRAY] = Math.min(Math.min(minValue[RED], minValue[GREEN]), minValue[BLUE]); maxValue[GRAY] = Math.max(Math.max(maxValue[RED], maxValue[GREEN]), maxValue[BLUE]); } public boolean isGray() { return isGray; } public int getNumSamples() { return numSamples; } public int getFrequency(int value) { if (numSamples > 0 && isGray && value >= 0 && value <= 255) return histogram[0][value]; return -1; } public int getFrequency(int channel, int value) { if (numSamples < 1 || channel < 0 || channel > 2 || value < 0 || value > 255) return -1; return histogram[channel][value]; } public int getMinFrequency() { if (numSamples > 0 && isGray) return minFrequency[0]; return -1; } public int getMinFrequency(int channel) { if (numSamples < 1 || channel < 0 || channel > 2) return -1; return minFrequency[channel]; } public int getMaxFrequency() { if (numSamples > 0 && isGray) return maxFrequency[0]; return -1; } public int getMaxFrequency(int channel) { if (numSamples < 1 || channel < 0 || channel > 2) return -1; return maxFrequency[channel]; } public int getMinValue() { if (numSamples > 0 && isGray) return minValue[0]; return -1; } public int getMinValue(int channel) { return minValue[channel]; } public int getMaxValue() { if (numSamples > 0 && isGray) return maxValue[0]; return -1; } public int getMaxValue(int channel) { return maxValue[channel]; } public float getMeanValue() { if (numSamples > 0 && isGray) return mean[0]; return -1.0F; } public float getMeanValue(int channel) { if (numSamples > 0 && RED <= channel && channel <= BLUE) return mean[channel]; return -1.0F; } } jhlabs-filters-2.0.235/com/jhlabs/image/ScaleFilter.java0000644000175000017500000000305410521402274022006 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * Scales an image using the area-averaging algorithm, which can't be done with AffineTransformOp. */ public class ScaleFilter extends AbstractBufferedImageOp { private int width; private int height; public ScaleFilter() { this(32, 32); } public ScaleFilter( int width, int height ) { this.width = width; this.height = height; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int w = src.getWidth(); int h = src.getHeight(); if ( dst == null ) { ColorModel dstCM = src.getColorModel(); dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(w, h), dstCM.isAlphaPremultiplied(), null); } Image scaleImage = src.getScaledInstance( w, h, Image.SCALE_AREA_AVERAGING ); Graphics2D g = dst.createGraphics(); g.drawImage( src, 0, 0, width, height, null ); g.dispose(); return dst; } public String toString() { return "Distort/Scale"; } } jhlabs-filters-2.0.235/com/jhlabs/image/SplineColormap.java0000644000175000017500000000533510521402274022544 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.Color; import java.util.Vector; import java.io.*; /** * A Colormap implemented using Catmull-Rom colour splines. The map has a variable number * of knots with a minimum of four. The first and last knots give the tangent at the end * of the spline, and colours are interpolated from the second to the second-last knots. */ public class SplineColormap extends ArrayColormap implements Serializable { public int numKnots = 4; public int[] xKnots = { 0, 0, 255, 255 }; public int[] yKnots = { 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, }; public SplineColormap() { rebuildGradient(); } public SplineColormap(int[] xKnots, int[] yKnots) { this.xKnots = xKnots; this.yKnots = yKnots; numKnots = xKnots.length; rebuildGradient(); } public int getKnot(int n) { return yKnots[n]; } public void setKnot(int n, int color) { yKnots[n] = color; rebuildGradient(); } public void addKnot(int x, int color) { int[] nx = new int[numKnots+1]; int[] ny = new int[numKnots+1]; System.arraycopy(xKnots, 0, nx, 0, numKnots); System.arraycopy(yKnots, 0, ny, 0, numKnots); xKnots = nx; yKnots = ny; xKnots[numKnots] = x; yKnots[numKnots] = color; numKnots++; sortKnots(); rebuildGradient(); } public void removeKnot(int n) { if (numKnots <= 4) return; if (n < numKnots-1) { System.arraycopy(xKnots, n+1, xKnots, n, numKnots-n-1); System.arraycopy(yKnots, n+1, yKnots, n, numKnots-n-1); } numKnots--; rebuildGradient(); } public void setKnotPosition(int n, int x) { xKnots[n] = PixelUtils.clamp(x); sortKnots(); rebuildGradient(); } private void rebuildGradient() { xKnots[0] = -1; xKnots[numKnots-1] = 256; yKnots[0] = yKnots[1]; yKnots[numKnots-1] = yKnots[numKnots-2]; for (int i = 0; i < 256; i++) map[i] = ImageMath.colorSpline(i, numKnots, xKnots, yKnots); } private void sortKnots() { for (int i = 1; i < numKnots; i++) { for (int j = 1; j < i; j++) { if (xKnots[i] < xKnots[j]) { int t = xKnots[i]; xKnots[i] = xKnots[j]; xKnots[j] = t; t = yKnots[i]; yKnots[i] = yKnots[j]; yKnots[j] = t; } } } } } jhlabs-filters-2.0.235/com/jhlabs/image/MinimumFilter.java0000644000175000017500000000276610521402274022403 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class MinimumFilter extends WholeImageFilter { static final long serialVersionUID = 1925266438370819998L; public MinimumFilter() { } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] outPixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixel = 0xffffffff; for (int dy = -1; dy <= 1; dy++) { int iy = y+dy; int ioffset; if (0 <= iy && iy < height) { ioffset = iy*width; for (int dx = -1; dx <= 1; dx++) { int ix = x+dx; if (0 <= ix && ix < width) { pixel = PixelUtils.combinePixels(pixel, inPixels[ioffset+ix], PixelUtils.MIN); } } } } outPixels[index++] = pixel; } } return outPixels; } public String toString() { return "Blur/Minimum"; } } jhlabs-filters-2.0.235/com/jhlabs/image/BorderFilter.java0000644000175000017500000000526110521402272022174 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; /** * A filter to add a border around an image using the supplied Paint, which may be null for no painting. */ public class BorderFilter extends AbstractBufferedImageOp { private int leftBorder, rightBorder; private int topBorder, bottomBorder; private Paint borderPaint; public BorderFilter() { } public BorderFilter( int leftBorder, int topBorder, int rightBorder, int bottomBorder, Paint borderPaint ) { this.leftBorder = leftBorder; this.topBorder = topBorder; this.rightBorder = rightBorder; this.bottomBorder = bottomBorder; this.borderPaint = borderPaint; } public void setLeftBorder(int leftBorder) { this.leftBorder = leftBorder; } public int getLeftBorder() { return leftBorder; } public void setRightBorder(int rightBorder) { this.rightBorder = rightBorder; } public int getRightBorder() { return rightBorder; } public void setTopBorder(int topBorder) { this.topBorder = topBorder; } public int getTopBorder() { return topBorder; } public void setBottomBorder(int bottomBorder) { this.bottomBorder = bottomBorder; } public int getBottomBorder() { return bottomBorder; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = new BufferedImage( width+leftBorder+rightBorder, height+topBorder+bottomBorder, src.getType() ); Graphics2D g = dst.createGraphics(); if ( borderPaint != null ) { g.setPaint( borderPaint ); if ( leftBorder > 0 ) g.fillRect( 0, 0, leftBorder, height ); if ( rightBorder > 0 ) g.fillRect( width-rightBorder, 0, rightBorder, height ); if ( topBorder > 0 ) g.fillRect( leftBorder, 0, width-leftBorder-rightBorder, topBorder ); if ( bottomBorder > 0 ) g.fillRect( leftBorder, height-bottomBorder, width-leftBorder-rightBorder, bottomBorder ); } g.drawRenderedImage( src, AffineTransform.getTranslateInstance( leftBorder, rightBorder ) ); g.dispose(); return dst; } public String toString() { return "Distort/Border..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/EdgeFilter.java0000644000175000017500000000652310521402272021625 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * An edge-detection filter. */ public class EdgeFilter extends WholeImageFilter { static final long serialVersionUID = -1084121755410916989L; public final static float R2 = (float)Math.sqrt(2); public final static float[] ROBERTS_V = { 0, 0, -1, 0, 1, 0, 0, 0, 0, }; public final static float[] ROBERTS_H = { -1, 0, 0, 0, 1, 0, 0, 0, 0, }; public final static float[] PREWITT_V = { -1, 0, 1, -1, 0, 1, -1, 0, 1, }; public final static float[] PREWITT_H = { -1, -1, -1, 0, 0, 0, 1, 1, 1, }; public final static float[] SOBEL_V = { -1, 0, 1, -2, 0, 2, -1, 0, 1, }; public static float[] SOBEL_H = { -1, -2, -1, 0, 0, 0, 1, 2, 1, }; public final static float[] FREI_CHEN_V = { -1, 0, 1, -R2, 0, R2, -1, 0, 1, }; public static float[] FREI_CHEN_H = { -1, -R2, -1, 0, 0, 0, 1, R2, 1, }; protected float[] vEdgeMatrix = SOBEL_V; protected float[] hEdgeMatrix = SOBEL_H; public EdgeFilter() { } public void setVEdgeMatrix(float[] vEdgeMatrix) { this.vEdgeMatrix = vEdgeMatrix; } public float[] getVEdgeMatrix() { return vEdgeMatrix; } public void setHEdgeMatrix(float[] hEdgeMatrix) { this.hEdgeMatrix = hEdgeMatrix; } public float[] getHEdgeMatrix() { return hEdgeMatrix; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] outPixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int r = 0, g = 0, b = 0; int rh = 0, gh = 0, bh = 0; int rv = 0, gv = 0, bv = 0; int a = inPixels[y*width+x] & 0xff000000; for (int row = -1; row <= 1; row++) { int iy = y+row; int ioffset; if (0 <= iy && iy < height) ioffset = iy*width; else ioffset = y*width; int moffset = 3*(row+1)+1; for (int col = -1; col <= 1; col++) { int ix = x+col; if (!(0 <= ix && ix < width)) ix = x; int rgb = inPixels[ioffset+ix]; float h = hEdgeMatrix[moffset+col]; float v = vEdgeMatrix[moffset+col]; r = (rgb & 0xff0000) >> 16; g = (rgb & 0x00ff00) >> 8; b = rgb & 0x0000ff; rh += (int)(h * r); gh += (int)(h * g); bh += (int)(h * b); rv += (int)(v * r); gv += (int)(v * g); bv += (int)(v * b); } } r = (int)(Math.sqrt(rh*rh + rv*rv) / 1.8); g = (int)(Math.sqrt(gh*gh + gv*gv) / 1.8); b = (int)(Math.sqrt(bh*bh + bv*bv) / 1.8); r = PixelUtils.clamp(r); g = PixelUtils.clamp(g); b = PixelUtils.clamp(b); outPixels[index++] = a | (r << 16) | (g << 8) | b; } } return outPixels; } public String toString() { return "Blur/Detect Edges"; } } jhlabs-filters-2.0.235/com/jhlabs/image/GlintFilter.java0000644000175000017500000001372110521402274022036 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import com.jhlabs.composite.*; public class GlintFilter extends AbstractBufferedImageOp { private float threshold = 1.0f; private int length = 5; private float blur = 0.0f; private float amount = 0.1f; private boolean glintOnly = false; private Colormap colormap = new LinearColormap( 0xffffffff, 0xff000000 ); public GlintFilter() { } public void setThreshold( float threshold ) { this.threshold = threshold; } public float getThreshold() { return threshold; } public void setAmount( float amount ) { this.amount = amount; } public float getAmount() { return amount; } public void setLength( int length ) { this.length = length; } public int getLength() { return length; } public void setBlur(float blur) { this.blur = blur; } public float getBlur() { return blur; } public void setGlintOnly(boolean glintOnly) { this.glintOnly = glintOnly; } public boolean getGlintOnly() { return glintOnly; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int[] pixels = new int[width]; int length2 = (int)(length / 1.414f); int[] colors = new int[length+1]; int[] colors2 = new int[length2+1]; if ( colormap != null ) { for (int i = 0; i <= length; i++) { int argb = colormap.getColor( (float)i/length ); int r = (argb >> 16) & 0xff; int g = (argb >> 8) & 0xff; int b = argb & 0xff; argb = (argb & 0xff000000) | ((int)(amount*r) << 16) | ((int)(amount*g) << 8) | (int)(amount*b); colors[i] = argb; } for (int i = 0; i <= length2; i++) { int argb = colormap.getColor( (float)i/length2 ); int r = (argb >> 16) & 0xff; int g = (argb >> 8) & 0xff; int b = argb & 0xff; argb = (argb & 0xff000000) | ((int)(amount*r) << 16) | ((int)(amount*g) << 8) | (int)(amount*b); colors2[i] = argb; } } BufferedImage mask = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); int threshold3 = (int)(threshold*3*255); for ( int y = 0; y < height; y++ ) { getRGB( src, 0, y, width, 1, pixels ); for ( int x = 0; x < width; x++ ) { int rgb = pixels[x]; int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; int l = r + g + b; if (l < threshold3) pixels[x] = 0xff000000; else { l /= 3; pixels[x] = a | (l << 16) | (l << 8) | l; } } setRGB( mask, 0, y, width, 1, pixels ); } if ( blur != 0 ) mask = new GaussianFilter(blur).filter( mask, null ); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int[] dstPixels; if ( glintOnly ) dstPixels = new int[width*height]; else dstPixels = getRGB( src, 0, 0, width, height, null );//FIXME - only need 2*length for ( int y = 0; y < height; y++ ) { int index = y*width; getRGB( mask, 0, y, width, 1, pixels ); int ymin = Math.max( y-length, 0 )-y; int ymax = Math.min( y+length, height-1 )-y; int ymin2 = Math.max( y-length2, 0 )-y; int ymax2 = Math.min( y+length2, height-1 )-y; for ( int x = 0; x < width; x++ ) { if ( (pixels[x] & 0xff) > threshold*255 ) { int xmin = Math.max( x-length, 0 )-x; int xmax = Math.min( x+length, width-1 )-x; int xmin2 = Math.max( x-length2, 0 )-x; int xmax2 = Math.min( x+length2, width-1 )-x; // Horizontal for ( int i = 0, k = 0; i <= xmax; i++, k++ ) dstPixels[index+i] = PixelUtils.combinePixels( dstPixels[index+i], colors[k], PixelUtils.ADD ); for ( int i = -1, k = 1; i >= xmin; i--, k++ ) dstPixels[index+i] = PixelUtils.combinePixels( dstPixels[index+i], colors[k], PixelUtils.ADD ); // Vertical for ( int i = 1, j = index+width, k = 0; i <= ymax; i++, j += width, k++ ) dstPixels[j] = PixelUtils.combinePixels( dstPixels[j], colors[k], PixelUtils.ADD ); for ( int i = -1, j = index-width, k = 0; i >= ymin; i--, j -= width, k++ ) dstPixels[j] = PixelUtils.combinePixels( dstPixels[j], colors[k], PixelUtils.ADD ); // Diagonals int xymin = Math.max( xmin2, ymin2 ); int xymax = Math.min( xmax2, ymax2 ); // SE int count = Math.min( xmax2, ymax2 ); for ( int i = 1, j = index+width+1, k = 0; i <= count; i++, j += width+1, k++ ) dstPixels[j] = PixelUtils.combinePixels( dstPixels[j], colors2[k], PixelUtils.ADD ); // NW count = Math.min( -xmin2, -ymin2 ); for ( int i = 1, j = index-width-1, k = 0; i <= count; i++, j -= width+1, k++ ) dstPixels[j] = PixelUtils.combinePixels( dstPixels[j], colors2[k], PixelUtils.ADD ); // NE count = Math.min( xmax2, -ymin2 ); for ( int i = 1, j = index-width+1, k = 0; i <= count; i++, j += -width+1, k++ ) dstPixels[j] = PixelUtils.combinePixels( dstPixels[j], colors2[k], PixelUtils.ADD ); // SW count = Math.min( -xmin2, ymax2 ); for ( int i = 1, j = index+width-1, k = 0; i <= count; i++, j += width-1, k++ ) dstPixels[j] = PixelUtils.combinePixels( dstPixels[j], colors2[k], PixelUtils.ADD ); } index++; } } setRGB( dst, 0, 0, width, height, dstPixels ); return dst; } public String toString() { return "Effects/Glint..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/MutatableFilter.java0000644000175000017500000000136110521402274022674 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; public interface MutatableFilter { public void mutate(float mutationLevel, BufferedImageOp dst, boolean keepShape, boolean keepColors); } jhlabs-filters-2.0.235/com/jhlabs/image/FlareFilter.java0000644000175000017500000000676010521402272022015 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.geom.*; import java.awt.image.*; import java.util.*; import com.jhlabs.math.*; /** * An experimental filter for rendering lens flares. */ public class FlareFilter extends PointFilter { private int rays = 50; private float radius; private float baseAmount = 1.0f; private float ringAmount = 0.2f; private float rayAmount = 0.1f; private int color = 0xffffffff; private int width, height; private float centreX = 0.5f, centreY = 0.5f; private float ringWidth = 1.6f; private float linear = 0.03f; private float gauss = 0.006f; private float mix = 0.50f; private float falloff = 6.0f; private float sigma; private float icentreX, icentreY; public FlareFilter() { setRadius(50.0f); } public void setColor(int color) { this.color = color; } public int getColor() { return color; } public void setRingWidth(float ringWidth) { this.ringWidth = ringWidth; } public float getRingWidth() { return ringWidth; } public void setBaseAmount(float baseAmount) { this.baseAmount = baseAmount; } public float getBaseAmount() { return baseAmount; } public void setRingAmount(float ringAmount) { this.ringAmount = ringAmount; } public float getRingAmount() { return ringAmount; } public void setRayAmount(float rayAmount) { this.rayAmount = rayAmount; } public float getRayAmount() { return rayAmount; } public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } public void setRadius(float radius) { this.radius = radius; sigma = radius/3; } public float getRadius() { return radius; } public void setDimensions(int width, int height) { this.width = width; this.height = height; icentreX = centreX*width; icentreY = centreY*height; super.setDimensions(width, height); } public int filterRGB(int x, int y, int rgb) { float dx = x-icentreX; float dy = y-icentreY; float distance = (float)Math.sqrt(dx*dx+dy*dy); float a = (float)Math.exp(-distance*distance*gauss)*mix + (float)Math.exp(-distance*linear)*(1-mix); float ring; a *= baseAmount; if (distance > radius + ringWidth) a = ImageMath.lerp((distance - (radius + ringWidth))/falloff, a, 0); if (distance < radius - ringWidth || distance > radius + ringWidth) ring = 0; else { ring = Math.abs(distance-radius)/ringWidth; ring = 1 - ring*ring*(3 - 2*ring); ring *= ringAmount; } a += ring; float angle = (float)Math.atan2(dx, dy)+ImageMath.PI; angle = (ImageMath.mod(angle/ImageMath.PI*17 + 1.0f + Noise.noise1(angle*10), 1.0f) - 0.5f)*2; angle = Math.abs(angle); angle = (float)Math.pow(angle, 5.0); float b = rayAmount * angle / (1 + distance*0.1f); a += b; a = ImageMath.clamp(a, 0, 1); return ImageMath.mixColors(a, rgb, color); } public String toString() { return "Stylize/Flare..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/PlasmaFilter.java0000644000175000017500000001363410521402274022201 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.util.*; import java.awt.*; import java.awt.image.*; import com.jhlabs.math.*; public class PlasmaFilter extends WholeImageFilter implements java.io.Serializable { static final long serialVersionUID = 6491871753122667752L; public float turbulence = 1.0f; private float scaling = 0.0f; private Colormap colormap = new LinearColormap(); private Random randomGenerator; private long seed = 567; private boolean useColormap = false; private boolean useImageColors = false; public PlasmaFilter() { randomGenerator = new Random(); } public void setTurbulence(float turbulence) { this.turbulence = turbulence; } public float getTurbulence() { return turbulence; } public void setScaling(float scaling) { this.scaling = scaling; } public float getScaling() { return scaling; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public void setUseColormap(boolean useColormap) { this.useColormap = useColormap; } public boolean getUseColormap() { return useColormap; } public void setUseImageColors(boolean useImageColors) { this.useImageColors = useImageColors; } public boolean getUseImageColors() { return useImageColors; } public void setSeed(int seed) { this.seed = seed; } public int getSeed() { return (int)seed; } public void randomize() { seed = new Date().getTime(); } private int randomRGB(int[] inPixels, int x, int y) { if (useImageColors) { return inPixels[y*originalSpace.width+x]; } else { int r = (int)(255 * randomGenerator.nextFloat()); int g = (int)(255 * randomGenerator.nextFloat()); int b = (int)(255 * randomGenerator.nextFloat()); return 0xff000000 | (r << 16) | (g << 8) | b; } } private int displace(int rgb, float amount) { int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; r = PixelUtils.clamp(r + (int)(amount * (randomGenerator.nextFloat()-0.5))); g = PixelUtils.clamp(g + (int)(amount * (randomGenerator.nextFloat()-0.5))); b = PixelUtils.clamp(b + (int)(amount * (randomGenerator.nextFloat()-0.5))); return 0xff000000 | (r << 16) | (g << 8) | b; } private int average(int rgb1, int rgb2) { return PixelUtils.combinePixels(rgb1, rgb2, PixelUtils.AVERAGE); } private int getPixel(int x, int y, int[] pixels, int stride) { return pixels[y*stride+x]; } private void putPixel(int x, int y, int rgb, int[] pixels, int stride) { pixels[y*stride+x] = rgb; } private boolean doPixel(int x1, int y1, int x2, int y2, int[] pixels, int stride, int depth, int scale) { int mx, my; if (depth == 0) { int ml, mr, mt, mb, mm, t; int tl = getPixel(x1, y1, pixels, stride); int bl = getPixel(x1, y2, pixels, stride); int tr = getPixel(x2, y1, pixels, stride); int br = getPixel(x2, y2, pixels, stride); float amount = (256.0f / (2.0f * scale)) * turbulence; mx = (x1 + x2) / 2; my = (y1 + y2) / 2; if (mx == x1 && mx == x2 && my == y1 && my == y2) return true; if (mx != x1 || mx != x2) { ml = average(tl, bl); ml = displace(ml, amount); putPixel(x1, my, ml, pixels, stride); if (x1 != x2){ mr = average(tr, br); mr = displace(mr, amount); putPixel(x2, my, mr, pixels, stride); } } if (my != y1 || my != y2){ if (x1 != mx || my != y2){ mb = average(bl, br); mb = displace(mb, amount); putPixel(mx, y2, mb, pixels, stride); } if (y1 != y2){ mt = average(tl, tr); mt = displace(mt, amount); putPixel(mx, y1, mt, pixels, stride); } } if (y1 != y2 || x1 != x2) { mm = average(tl, br); t = average(bl, tr); mm = average(mm, t); mm = displace(mm, amount); putPixel(mx, my, mm, pixels, stride); } if (x2-x1 < 3 && y2-y1 < 3) return false; return true; } mx = (x1 + x2) / 2; my = (y1 + y2) / 2; doPixel(x1, y1, mx, my, pixels, stride, depth-1, scale+1); doPixel(x1, my, mx ,y2, pixels, stride, depth-1, scale+1); doPixel(mx, y1, x2 , my, pixels, stride, depth-1, scale+1); return doPixel(mx, my, x2, y2, pixels, stride, depth-1, scale+1); } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int[] outPixels = new int[width * height]; randomGenerator.setSeed(seed); int w1 = width-1; int h1 = height-1; putPixel(0, 0, randomRGB(inPixels, 0, 0), outPixels, width); putPixel(w1, 0, randomRGB(inPixels, w1, 0), outPixels, width); putPixel(0, h1, randomRGB(inPixels, 0, h1), outPixels, width); putPixel(w1, h1, randomRGB(inPixels, w1, h1), outPixels, width); putPixel(w1/2, h1/2, randomRGB(inPixels, w1/2, h1/2), outPixels, width); putPixel(0, h1/2, randomRGB(inPixels, 0, h1/2), outPixels, width); putPixel(w1, h1/2, randomRGB(inPixels, w1, h1/2), outPixels, width); putPixel(w1/2, 0, randomRGB(inPixels, w1/2, 0), outPixels, width); putPixel(w1/2, h1, randomRGB(inPixels, w1/2, h1), outPixels, width); int depth = 1; while (doPixel(0, 0, width-1, height-1, outPixels, width, depth, 0)) depth++; if (useColormap && colormap != null) { int index = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { outPixels[index] = colormap.getColor((outPixels[index] & 0xff)/255.0f); index++; } } } return outPixels; } public String toString() { return "Texture/Plasma..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/DiffusionFilter.java0000644000175000017500000000744510521402272022713 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter which uses Floyd-Steinberg error diffusion dithering to halftone an image. */ public class DiffusionFilter extends WholeImageFilter { protected final static int[] diffusionMatrix = { 0, 0, 0, 0, 0, 7, 3, 5, 1, }; private int[] matrix; private int sum = 3+5+7+1; private boolean serpentine = true; private boolean colorDither = true; public int levels = 6; /** * Construct a DiffusionFilter */ public DiffusionFilter() { setMatrix(diffusionMatrix); } /** * Set whether to use a serpentine pattern for return or not. This can reduce 'avalanche' artifacts in the output. * @param serpentine true to use serpentine pattern */ public void setSerpentine(boolean serpentine) { this.serpentine = serpentine; } /** * Return the serpentine setting * @return the current setting */ public boolean getSerpentine() { return serpentine; } public void setColorDither(boolean colorDither) { this.colorDither = colorDither; } public boolean getColorDither() { return colorDither; } public void setMatrix(int[] matrix) { this.matrix = matrix; sum = 0; for (int i = 0; i < matrix.length; i++) sum += matrix[i]; } public int[] getMatrix() { return matrix; } public void setLevels(int levels) { this.levels = levels; } public int getLevels() { return levels; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int[] outPixels = new int[width * height]; int index = 0; int[] map = new int[levels]; for (int i = 0; i < levels; i++) { int v = 255 * i / (levels-1); map[i] = v; } int[] div = new int[256]; for (int i = 0; i < 256; i++) div[i] = levels*i / 256; for (int y = 0; y < height; y++) { boolean reverse = serpentine && (y & 1) == 1; int direction; if (reverse) { index = y*width+width-1; direction = -1; } else { index = y*width; direction = 1; } for (int x = 0; x < width; x++) { int rgb1 = inPixels[index]; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; if (!colorDither) r1 = g1 = b1 = (r1+g1+b1) / 3; int r2 = map[div[r1]]; int g2 = map[div[g1]]; int b2 = map[div[b1]]; outPixels[index] = 0xff000000 | (r2 << 16) | (g2 << 8) | b2; int er = r1-r2; int eg = g1-g2; int eb = b1-b2; for (int i = -1; i <= 1; i++) { int iy = i+y; if (0 <= iy && iy < height) { for (int j = -1; j <= 1; j++) { int jx = j+x; if (0 <= jx && jx < width) { int w; if (reverse) w = matrix[(i+1)*3-j+1]; else w = matrix[(i+1)*3+j+1]; if (w != 0) { int k = reverse ? index - j : index + j; rgb1 = inPixels[k]; r1 = (rgb1 >> 16) & 0xff; g1 = (rgb1 >> 8) & 0xff; b1 = rgb1 & 0xff; r1 += er * w/sum; g1 += eg * w/sum; b1 += eb * w/sum; inPixels[k] = (PixelUtils.clamp(r1) << 16) | (PixelUtils.clamp(g1) << 8) | PixelUtils.clamp(b1); } } } } } index += direction; } } return outPixels; } public String toString() { return "Colors/Diffusion Dither..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/BlurFilter.java0000644000175000017500000000201310521402272021653 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A simple blur filter. You should probably use BoxBlurFilter instead. */ public class BlurFilter extends ConvolveFilter { static final long serialVersionUID = -4753886159026796838L; protected static float[] blurMatrix = { 1/14f, 2/14f, 1/14f, 2/14f, 2/14f, 2/14f, 1/14f, 2/14f, 1/14f }; public BlurFilter() { super( blurMatrix ); } public String toString() { return "Blur/Simple Blur"; } } jhlabs-filters-2.0.235/com/jhlabs/image/CurlFilter.java0000644000175000017500000002001010521402272021651 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; /** * A page curl effect. */ public class CurlFilter extends TransformFilter { private float angle = 0; private float transition = 0.0f; private float width; private float height; private float radius; /** * Construct a CurlFilter with no distortion. */ public CurlFilter() { setEdgeAction( ZERO ); } public void setTransition( float transition ) { this.transition = transition; } public float getTransition() { return transition; } public void setAngle(float angle) { this.angle = angle; } public float getAngle() { return angle; } public void setRadius( float radius ) { this.radius = radius; } public float getRadius() { return radius; } /* public BufferedImage filter( BufferedImage src, BufferedImage dst ) { this.width = src.getWidth(); this.height = src.getHeight(); return super.filter( src, dst ); } */ static class Sampler { private int edgeAction; private int width, height; private int[] inPixels; public Sampler( BufferedImage image ) { int width = image.getWidth(); int height = image.getHeight(); int type = image.getType(); inPixels = ImageUtils.getRGB( image, 0, 0, width, height, null ); } public int sample( float x, float y ) { int srcX = (int)Math.floor( x ); int srcY = (int)Math.floor( y ); float xWeight = x-srcX; float yWeight = y-srcY; int nw, ne, sw, se; if ( srcX >= 0 && srcX < width-1 && srcY >= 0 && srcY < height-1) { // Easy case, all corners are in the image int i = width*srcY + srcX; nw = inPixels[i]; ne = inPixels[i+1]; sw = inPixels[i+width]; se = inPixels[i+width+1]; } else { // Some of the corners are off the image nw = getPixel( inPixels, srcX, srcY, width, height ); ne = getPixel( inPixels, srcX+1, srcY, width, height ); sw = getPixel( inPixels, srcX, srcY+1, width, height ); se = getPixel( inPixels, srcX+1, srcY+1, width, height ); } return ImageMath.bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se); } final private int getPixel( int[] pixels, int x, int y, int width, int height ) { if (x < 0 || x >= width || y < 0 || y >= height) { switch (edgeAction) { case ZERO: default: return 0; case WRAP: return pixels[(ImageMath.mod(y, height) * width) + ImageMath.mod(x, width)]; case CLAMP: return pixels[(ImageMath.clamp(y, 0, height-1) * width) + ImageMath.clamp(x, 0, width-1)]; } } return pixels[ y*width+x ]; } } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); this.width = src.getWidth(); this.height = src.getHeight(); int type = src.getType(); originalSpace = new Rectangle(0, 0, width, height); transformedSpace = new Rectangle(0, 0, width, height); transformSpace(transformedSpace); if ( dst == null ) { ColorModel dstCM = src.getColorModel(); dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(transformedSpace.width, transformedSpace.height), dstCM.isAlphaPremultiplied(), null); } WritableRaster dstRaster = dst.getRaster(); int[] inPixels = getRGB( src, 0, 0, width, height, null ); if ( interpolation == NEAREST_NEIGHBOUR ) return filterPixelsNN( dst, width, height, inPixels, transformedSpace ); int srcWidth = width; int srcHeight = height; int srcWidth1 = width-1; int srcHeight1 = height-1; int outWidth = transformedSpace.width; int outHeight = transformedSpace.height; int outX, outY; int index = 0; int[] outPixels = new int[outWidth]; outX = transformedSpace.x; outY = transformedSpace.y; float[] out = new float[4]; for (int y = 0; y < outHeight; y++) { for (int x = 0; x < outWidth; x++) { transformInverse(outX+x, outY+y, out); int srcX = (int)Math.floor( out[0] ); int srcY = (int)Math.floor( out[1] ); float xWeight = out[0]-srcX; float yWeight = out[1]-srcY; int nw, ne, sw, se; if ( srcX >= 0 && srcX < srcWidth1 && srcY >= 0 && srcY < srcHeight1) { // Easy case, all corners are in the image int i = srcWidth*srcY + srcX; nw = inPixels[i]; ne = inPixels[i+1]; sw = inPixels[i+srcWidth]; se = inPixels[i+srcWidth+1]; } else { // Some of the corners are off the image nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight ); ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight ); sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight ); se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight ); } int rgb = ImageMath.bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se); int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; float shade = out[2]; r = (int)(r * shade); g = (int)(g * shade); b = (int)(b * shade); rgb = (rgb & 0xff000000) | (r << 16) | (g << 8) | b; if ( out[3] != 0 ) outPixels[x] = PixelUtils.combinePixels( rgb, inPixels[srcWidth*y + x], PixelUtils.NORMAL ); else outPixels[x] = rgb; } setRGB( dst, 0, y, transformedSpace.width, 1, outPixels ); } return dst; } final private int getPixel( int[] pixels, int x, int y, int width, int height ) { if (x < 0 || x >= width || y < 0 || y >= height) { switch (edgeAction) { case ZERO: default: return 0; case WRAP: return pixels[(ImageMath.mod(y, height) * width) + ImageMath.mod(x, width)]; case CLAMP: return pixels[(ImageMath.clamp(y, 0, height-1) * width) + ImageMath.clamp(x, 0, width-1)]; } } return pixels[ y*width+x ]; } protected void transformInverse(int x, int y, float[] out) { /*Fisheye float mirrorDistance = width*centreX; float mirrorRadius = width*centreY; float cx = width*.5f; float cy = height*.5f; float dx = x-cx; float dy = y-cy; float r2 = dx*dx+dy*dy; float r = (float)Math.sqrt( r2 ); float phi = (float)(Math.PI*.5-Math.asin( Math.sqrt( mirrorRadius*mirrorRadius-r2 )/mirrorRadius )); r = r > mirrorRadius ? width : mirrorDistance * (float)Math.tan( phi ); phi = (float)Math.atan2( dy, dx ); out[0] = cx + r*(float)Math.cos( phi ); out[1] = cy + r*(float)Math.sin( phi ); */ float t = transition; float px = x, py = y; float s = (float)Math.sin( angle ); float c = (float)Math.cos( angle ); float tx = t*width; tx = t * (float)Math.sqrt( width*width + height*height); // Start from the correct corner according to the angle float xoffset = c < 0 ? width : 0; float yoffset = s < 0 ? height : 0; // Transform into unrotated coordinates px -= xoffset; py -= yoffset; float qx = px * c + py * s; float qy = -px * s + py * c; boolean outside = qx < tx; boolean unfolded = qx > tx*2; boolean oncurl = !(outside || unfolded); qx = qx > tx*2 ? qx : 2*tx-qx; // Transform back into rotated coordinates px = qx * c - qy * s; py = qx * s + qy * c; px += xoffset; py += yoffset; // See if we're off the edge of the page boolean offpage = px < 0 || py < 0 || px >= width || py >= height; // If we're off the edge, but in the curl... if ( offpage && oncurl ) { px = x; py = y; } // Shade the curl float shade = !offpage && oncurl ? 1.9f * (1.0f-(float)Math.cos( Math.exp((qx-tx)/radius) )) : 0; out[2] = 1-shade; if ( outside ) { out[0] = out[1] = -1; } else { out[0] = px; out[1] = py; } out[3] = !offpage && oncurl ? 1 : 0; } public String toString() { return "Distort/Curl..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/BicubicScaleFilter.java0000644000175000017500000000357110521402272023271 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * Scales an image using bi-cubic interpolation, which can't be done with AffineTransformOp. */ public class BicubicScaleFilter extends AbstractBufferedImageOp { private int width; private int height; public BicubicScaleFilter() { this(32, 32); } /** * Constructor for a filter which scales the input image to the given width and height using bicubic interpolation. * Unfortunately, it appears that bicubic actually looks worse than bilinear interpolation on most Java implementations, * but you can be the judge. */ public BicubicScaleFilter( int width, int height ) { this.width = width; this.height = height; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int w = src.getWidth(); int h = src.getHeight(); if ( dst == null ) { ColorModel dstCM = src.getColorModel(); dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(width, height), dstCM.isAlphaPremultiplied(), null); } Graphics2D g = dst.createGraphics(); g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC ); g.drawImage( src, 0, 0, width, height, null ); g.dispose(); return dst; } public String toString() { return "Distort/Bicubic Scale"; } } jhlabs-filters-2.0.235/com/jhlabs/image/MapColorsFilter.java0000644000175000017500000000231010521402274022650 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A filter which replaces one color by another in an image. This is frankly, not often useful, but has its occasional * uses when dealing with GIF transparency and the like. */ public class MapColorsFilter extends PointFilter { private int oldColor; private int newColor; public MapColorsFilter() { this( 0xffffffff, 0xff000000 ); } public MapColorsFilter(int oldColor, int newColor) { canFilterIndexColorModel = true; this.oldColor = oldColor; this.newColor = newColor; } public int filterRGB(int x, int y, int rgb) { if (rgb == oldColor) return newColor; return rgb; } } jhlabs-filters-2.0.235/com/jhlabs/image/DilateFilter.java0000644000175000017500000000465310521402272022165 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * Given a binary image, this filter performs binary dilation, setting all added pixels to the given 'new' color. */ public class DilateFilter extends BinaryFilter { public int threshold = 2; public DilateFilter() { } /** * Set the threshold - the number of neighbouring pixels for dilation to occur. * @param threshold the new threshold */ public void setThreshold(int threshold) { this.threshold = threshold; } /** * Return the threshold - the number of neighbouring pixels for dilation to occur. * @return the current threshold */ public int getThreshold() { return threshold; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int[] outPixels = new int[width * height]; for (int i = 0; i < iterations; i++) { int index = 0; if (i > 0) { int[] t = inPixels; inPixels = outPixels; outPixels = t; } for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixel = inPixels[y*width+x]; if (!blackFunction.isBlack(pixel)) { int neighbours = 0; for (int dy = -1; dy <= 1; dy++) { int iy = y+dy; int ioffset; if (0 <= iy && iy < height) { ioffset = iy*width; for (int dx = -1; dx <= 1; dx++) { int ix = x+dx; if (!(dy == 0 && dx == 0) && 0 <= ix && ix < width) { int rgb = inPixels[ioffset+ix]; if (blackFunction.isBlack(rgb)) neighbours++; } } } } if (neighbours >= threshold) { if (colormap != null) pixel = colormap.getColor((float)i/iterations); else pixel = newColor; } } outPixels[index++] = pixel; } } } return outPixels; } public String toString() { return "Binary/Dilate..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/BrushedMetalFilter.java0000644000175000017500000001422110521402272023332 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.awt.geom.*; import java.util.*; /** * A filter which produces an image simulating brushed metal. */ public class BrushedMetalFilter implements BufferedImageOp { private int radius = 10; private float amount = 0.1f; private int color = 0xff888888; private float shine = 0.1f; private boolean monochrome = true; private Random randomNumbers; public BrushedMetalFilter() { } public BrushedMetalFilter( int color, int radius, float amount, boolean monochrome, float shine) { this.color = color; this.radius = radius; this.amount = amount; this.monochrome = monochrome; this.shine = shine; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int[] inPixels = new int[width]; int[] outPixels = new int[width]; randomNumbers = new Random(0); int a = color & 0xff000000; int r = (color >> 16) & 0xff; int g = (color >> 8) & 0xff; int b = color & 0xff; for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++ ) { int tr = r; int tg = g; int tb = b; if ( shine != 0 ) { int f = (int)(255*shine*Math.sin( (double)x/width*Math.PI )); tr += f; tg += f; tb += f; } if (monochrome) { int n = (int)(255 * (2*randomNumbers.nextFloat() - 1) * amount); inPixels[x] = a | (clamp(tr+n) << 16) | (clamp(tg+n) << 8) | clamp(tb+n); } else { inPixels[x] = a | (random(tr) << 16) | (random(tg) << 8) | random(tb); } } if ( radius != 0 ) { blur( inPixels, outPixels, width, radius ); setRGB( dst, 0, y, width, 1, outPixels ); } else setRGB( dst, 0, y, width, 1, inPixels ); } return dst; } private int random(int x) { x += (int)(255*(2*randomNumbers.nextFloat() - 1) * amount); if (x < 0) x = 0; else if (x > 0xff) x = 0xff; return x; } private static int clamp(int c) { if (c < 0) return 0; if (c > 255) return 255; return c; } /** * Return a mod b. This differs from the % operator with respect to negative numbers. * @param a the dividend * @param b the divisor * @return a mod b */ private static int mod(int a, int b) { int n = a/b; a -= n*b; if (a < 0) return a + b; return a; } public void blur( int[] in, int[] out, int width, int radius ) { int widthMinus1 = width-1; int r2 = 2*radius+1; int tr = 0, tg = 0, tb = 0; for ( int i = -radius; i <= radius; i++ ) { int rgb = in[mod(i, width)]; tr += (rgb >> 16) & 0xff; tg += (rgb >> 8) & 0xff; tb += rgb & 0xff; } for ( int x = 0; x < width; x++ ) { out[x] = 0xff000000 | ((tr/r2) << 16) | ((tg/r2) << 8) | (tb/r2); int i1 = x+radius+1; if ( i1 > widthMinus1 ) i1 = mod( i1, width ); int i2 = x-radius; if ( i2 < 0 ) i2 = mod( i2, width ); int rgb1 = in[i1]; int rgb2 = in[i2]; tr += ((rgb1 & 0xff0000)-(rgb2 & 0xff0000)) >> 16; tg += ((rgb1 & 0xff00)-(rgb2 & 0xff00)) >> 8; tb += (rgb1 & 0xff)-(rgb2 & 0xff); } } public void setRadius(int radius) { this.radius = radius; } public int getRadius() { return radius; } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public void setColor(int color) { this.color = color; } public int getColor() { return color; } public void setMonochrome(boolean monochrome) { this.monochrome = monochrome; } public boolean getMonochrome() { return monochrome; } public void setShine( float shine ) { this.shine = shine; } public float getShine() { return shine; } public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) { if ( dstCM == null ) dstCM = src.getColorModel(); return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null); } public Rectangle2D getBounds2D( BufferedImage src ) { return new Rectangle(0, 0, src.getWidth(), src.getHeight()); } public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) { if ( dstPt == null ) dstPt = new Point2D.Double(); dstPt.setLocation( srcPt.getX(), srcPt.getY() ); return dstPt; } public RenderingHints getRenderingHints() { return null; } /** * A convenience method for setting ARGB pixels in an image. This tries to avoid the performance * penalty of BufferedImage.setRGB unmanaging the image. */ public void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { int type = image.getType(); if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) image.getRaster().setDataElements( x, y, width, height, pixels ); else image.setRGB( x, y, width, height, pixels, 0, width ); } public String toString() { return "Texture/Brushed Metal..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/RotateFilter.java0000644000175000017500000000451210521402274022215 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class RotateFilter extends TransformFilter { static final long serialVersionUID = 1166374736665848180L; private float angle; private float cos, sin; private boolean resize = true; public RotateFilter() { this(ImageMath.PI); } public RotateFilter(float angle) { this(angle, true); } public RotateFilter(float angle, boolean resize) { setAngle(angle); this.resize = resize; } public void setAngle(float angle) { this.angle = angle; cos = (float)Math.cos(this.angle); sin = (float)Math.sin(this.angle); } public float getAngle() { return angle; } protected void transformSpace(Rectangle rect) { if (resize) { Point out = new Point(0, 0); int minx = Integer.MAX_VALUE; int miny = Integer.MAX_VALUE; int maxx = Integer.MIN_VALUE; int maxy = Integer.MIN_VALUE; int w = rect.width; int h = rect.height; int x = rect.x; int y = rect.y; for (int i = 0; i < 4; i++) { switch (i) { case 0: transform(x, y, out); break; case 1: transform(x + w, y, out); break; case 2: transform(x, y + h, out); break; case 3: transform(x + w, y + h, out); break; } minx = Math.min(minx, out.x); miny = Math.min(miny, out.y); maxx = Math.max(maxx, out.x); maxy = Math.max(maxy, out.y); } rect.x = minx; rect.y = miny; rect.width = maxx - rect.x; rect.height = maxy - rect.y; } } protected void transform(int x, int y, Point out) { out.x = (int)((x * cos) + (y * sin)); out.y = (int)((y * cos) - (x * sin)); } protected void transformInverse(int x, int y, float[] out) { out[0] = (x * cos) - (y * sin); out[1] = (y * cos) + (x * sin); } public String toString() { return "Rotate "+(int)(angle * 180 / Math.PI); } } jhlabs-filters-2.0.235/com/jhlabs/image/ImageCombiningFilter.java0000644000175000017500000000407210521402274023630 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class ImageCombiningFilter { public int filterRGB(int x, int y, int rgb1, int rgb2) { int a1 = (rgb1 >> 24) & 0xff; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; int a2 = (rgb2 >> 24) & 0xff; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; int r = PixelUtils.clamp(r1 + r2); int g = PixelUtils.clamp(r1 + r2); int b = PixelUtils.clamp(r1 + r2); return (a1 << 24) | (r << 16) | (g << 8) | b; } public ImageProducer filter(Image image1, Image image2, int x, int y, int w, int h) { int[] pixels1 = new int[w * h]; int[] pixels2 = new int[w * h]; int[] pixels3 = new int[w * h]; PixelGrabber pg1 = new PixelGrabber(image1, x, y, w, h, pixels1, 0, w); PixelGrabber pg2 = new PixelGrabber(image2, x, y, w, h, pixels2, 0, w); try { pg1.grabPixels(); pg2.grabPixels(); } catch (InterruptedException e) { System.err.println("interrupted waiting for pixels!"); return null; } if ((pg1.status() & ImageObserver.ABORT) != 0) { System.err.println("image fetch aborted or errored"); return null; } if ((pg2.status() & ImageObserver.ABORT) != 0) { System.err.println("image fetch aborted or errored"); return null; } for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { int k = j * w + i; pixels3[k] = filterRGB(x+i, y+j, pixels1[k], pixels2[k]); } } return new MemoryImageSource(w, h, pixels3, 0, w); } } jhlabs-filters-2.0.235/com/jhlabs/image/PerspectiveFilter.java0000644000175000017500000000726510521402274023260 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.awt.geom.*; public class PerspectiveFilter extends TransformFilter { private float x0, y0, x1, y1, x2, y2, x3, y3; private float dx1, dy1, dx2, dy2, dx3, dy3; private float A, B, C, D, E, F, G, H, I; public PerspectiveFilter() { this(0, 0, 100, 0, 100, 100, 0, 100); } public PerspectiveFilter(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) { setCorners(x0, y0, x1, y1, x2, y2, x3, y3); } public void setCorners(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) { this.x0 = x0; this.y0 = y0; this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.x3 = x3; this.y3 = y3; dx1 = x1-x2; dy1 = y1-y2; dx2 = x3-x2; dy2 = y3-y2; dx3 = x0-x1+x2-x3; dy3 = y0-y1+y2-y3; float a11, a12, a13, a21, a22, a23, a31, a32; if (dx3 == 0 && dy3 == 0) { a11 = x1-x0; a21 = x2-x1; a31 = x0; a12 = y1-y0; a22 = y2-y1; a32 = y0; a13 = a23 = 0; } else { a13 = (dx3*dy2-dx2*dy3)/(dx1*dy2-dy1*dx2); a23 = (dx1*dy3-dy1*dx3)/(dx1*dy2-dy1*dx2); a11 = x1-x0+a13*x1; a21 = x3-x0+a23*x3; a31 = x0; a12 = y1-y0+a13*y1; a22 = y3-y0+a23*y3; a32 = y0; } A = a22 - a32*a23; B = a31*a23 - a21; C = a21*a32 - a31*a22; D = a32*a13 - a12; E = a11 - a31*a13; F = a31*a12 - a11*a32; G = a12*a23 - a22*a13; H = a21*a13 - a11*a23; I = a11*a22 - a21*a12; } protected void transformSpace(Rectangle rect) { rect.x = (int)Math.min( Math.min( x0, x1 ), Math.min( x2, x3 ) ); rect.y = (int)Math.min( Math.min( y0, y1 ), Math.min( y2, y3 ) ); rect.width = (int)Math.max( Math.max( x0, x1 ), Math.max( x2, x3 ) ) - rect.x; rect.height = (int)Math.max( Math.max( y0, y1 ), Math.max( y2, y3 ) ) - rect.y; } public float getOriginX() { return x0 - (int)Math.min( Math.min( x0, x1 ), Math.min( x2, x3 ) ); } public float getOriginY() { return y0 - (int)Math.min( Math.min( y0, y1 ), Math.min( y2, y3 ) ); } /* public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) { if ( dstPt == null ) dstPt = new Point2D.Double(); dx1 = x1-x2; dy1 = y1-y2; dx2 = x3-x2; dy2 = y3-y2; dx3 = x0-x1+x2-x3; dy3 = y0-y1+y2-y3; float a11, a12, a13, a21, a22, a23, a31, a32; if (dx3 == 0 && dy3 == 0) { a11 = x1-x0; a21 = x2-x1; a31 = x0; a12 = y1-y0; a22 = y2-y1; a32 = y0; a13 = a23 = 0; } else { a13 = (dx3*dy2-dx2*dy3)/(dx1*dy2-dy1*dx2); a23 = (dx1*dy3-dy1*dx3)/(dx1*dy2-dy1*dx2); a11 = x1-x0+a13*x1; a21 = x3-x0+a23*x3; a31 = x0; a12 = y1-y0+a13*y1; a22 = y3-y0+a23*y3; a32 = y0; } float x = (float)srcPt.getX(); float y = (float)srcPt.getY(); float D = 1.0f/(a13*x + a23*y + 1); dstPt.setLocation( (a11*x + a21*y + a31)*D, (a12*x + a22*y + a32)*D ); return dstPt; } */ protected void transformInverse(int x, int y, float[] out) { out[0] = originalSpace.width * (A*x+B*y+C)/(G*x+H*y+I); out[1] = originalSpace.height * (D*x+E*y+F)/(G*x+H*y+I); } public String toString() { return "Distort/Perspective..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ConvolveFilter.java0000644000175000017500000002137210521402272022553 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.awt.geom.*; /** * A filter which applies a convolution kernel to an image. * @author Jerry Huxtable */ public class ConvolveFilter extends AbstractBufferedImageOp { static final long serialVersionUID = 2239251672685254626L; public static int ZERO_EDGES = 0; public static int CLAMP_EDGES = 1; public static int WRAP_EDGES = 2; protected Kernel kernel = null; protected boolean alpha = true; private int edgeAction = CLAMP_EDGES; /** * Construct a filter with a null kernel. This is only useful if you're going to change the kernel later on. */ public ConvolveFilter() { this(new float[9]); } /** * Construct a filter with the given 3x3 kernel. * @param matrix an array of 9 floats containing the kernel */ public ConvolveFilter(float[] matrix) { this(new Kernel(3, 3, matrix)); } /** * Construct a filter with the given kernel. * @param rows the number of rows in the kernel * @param cols the number of columns in the kernel * @param matrix an array of rows*cols floats containing the kernel */ public ConvolveFilter(int rows, int cols, float[] matrix) { this(new Kernel(cols, rows, matrix)); } /** * Construct a filter with the given 3x3 kernel. * @param matrix an array of 9 floats containing the kernel */ public ConvolveFilter(Kernel kernel) { this.kernel = kernel; } public void setKernel(Kernel kernel) { this.kernel = kernel; } public Kernel getKernel() { return kernel; } public void setEdgeAction(int edgeAction) { this.edgeAction = edgeAction; } public int getEdgeAction() { return edgeAction; } public void setUseAlpha( boolean useAlpha ) { this.alpha = useAlpha; } public boolean getUseAlpha() { return alpha; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; getRGB( src, 0, 0, width, height, inPixels ); convolve(kernel, inPixels, outPixels, width, height, alpha, edgeAction); setRGB( dst, 0, 0, width, height, outPixels ); return dst; } public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) { if ( dstCM == null ) dstCM = src.getColorModel(); return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null); } public Rectangle2D getBounds2D( BufferedImage src ) { return new Rectangle(0, 0, src.getWidth(), src.getHeight()); } public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) { if ( dstPt == null ) dstPt = new Point2D.Double(); dstPt.setLocation( srcPt.getX(), srcPt.getY() ); return dstPt; } public RenderingHints getRenderingHints() { return null; } public static void convolve(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, int edgeAction) { convolve(kernel, inPixels, outPixels, width, height, true, edgeAction); } public static void convolve(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, boolean alpha, int edgeAction) { if (kernel.getHeight() == 1) convolveH(kernel, inPixels, outPixels, width, height, alpha, edgeAction); else if (kernel.getWidth() == 1) convolveV(kernel, inPixels, outPixels, width, height, alpha, edgeAction); else convolveHV(kernel, inPixels, outPixels, width, height, alpha, edgeAction); } /** * Convolve with a 2D kernel */ public static void convolveHV(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, boolean alpha, int edgeAction) { int index = 0; float[] matrix = kernel.getKernelData( null ); int rows = kernel.getHeight(); int cols = kernel.getWidth(); int rows2 = rows/2; int cols2 = cols/2; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; for (int row = -rows2; row <= rows2; row++) { int iy = y+row; int ioffset; if (0 <= iy && iy < height) ioffset = iy*width; else if ( edgeAction == CLAMP_EDGES ) ioffset = y*width; else if ( edgeAction == WRAP_EDGES ) ioffset = ((iy+height) % height) * width; else continue; int moffset = cols*(row+rows2)+cols2; for (int col = -cols2; col <= cols2; col++) { float f = matrix[moffset+col]; if (f != 0) { int ix = x+col; if (!(0 <= ix && ix < width)) { if ( edgeAction == CLAMP_EDGES ) ix = x; else if ( edgeAction == WRAP_EDGES ) ix = (x+width) % width; else continue; } int rgb = inPixels[ioffset+ix]; a += f * ((rgb >> 24) & 0xff); r += f * ((rgb >> 16) & 0xff); g += f * ((rgb >> 8) & 0xff); b += f * (rgb & 0xff); } } } int ia = alpha ? PixelUtils.clamp((int)(a+0.5)) : 0xff; int ir = PixelUtils.clamp((int)(r+0.5)); int ig = PixelUtils.clamp((int)(g+0.5)); int ib = PixelUtils.clamp((int)(b+0.5)); outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib; } } } /** * Convolve with a kernel consisting of one row */ public static void convolveH(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, boolean alpha, int edgeAction) { int index = 0; float[] matrix = kernel.getKernelData( null ); int cols = kernel.getWidth(); int cols2 = cols/2; for (int y = 0; y < height; y++) { int ioffset = y*width; for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; int moffset = cols2; for (int col = -cols2; col <= cols2; col++) { float f = matrix[moffset+col]; if (f != 0) { int ix = x+col; if ( ix < 0 ) { if ( edgeAction == CLAMP_EDGES ) ix = 0; else if ( edgeAction == WRAP_EDGES ) ix = (x+width) % width; } else if ( ix >= width) { if ( edgeAction == CLAMP_EDGES ) ix = width-1; else if ( edgeAction == WRAP_EDGES ) ix = (x+width) % width; } int rgb = inPixels[ioffset+ix]; a += f * ((rgb >> 24) & 0xff); r += f * ((rgb >> 16) & 0xff); g += f * ((rgb >> 8) & 0xff); b += f * (rgb & 0xff); } } int ia = alpha ? PixelUtils.clamp((int)(a+0.5)) : 0xff; int ir = PixelUtils.clamp((int)(r+0.5)); int ig = PixelUtils.clamp((int)(g+0.5)); int ib = PixelUtils.clamp((int)(b+0.5)); outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib; } } } /** * Convolve with a kernel consisting of one column */ public static void convolveV(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, boolean alpha, int edgeAction) { int index = 0; float[] matrix = kernel.getKernelData( null ); int rows = kernel.getHeight(); int rows2 = rows/2; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; for (int row = -rows2; row <= rows2; row++) { int iy = y+row; int ioffset; if ( iy < 0 ) { if ( edgeAction == CLAMP_EDGES ) ioffset = 0; else if ( edgeAction == WRAP_EDGES ) ioffset = ((y+height) % height)*width; else ioffset = iy*width; } else if ( iy >= height) { if ( edgeAction == CLAMP_EDGES ) ioffset = (height-1)*width; else if ( edgeAction == WRAP_EDGES ) ioffset = ((y+height) % height)*width; else ioffset = iy*width; } else ioffset = iy*width; float f = matrix[row+rows2]; if (f != 0) { int rgb = inPixels[ioffset+x]; a += f * ((rgb >> 24) & 0xff); r += f * ((rgb >> 16) & 0xff); g += f * ((rgb >> 8) & 0xff); b += f * (rgb & 0xff); } } int ia = alpha ? PixelUtils.clamp((int)(a+0.5)) : 0xff; int ir = PixelUtils.clamp((int)(r+0.5)); int ig = PixelUtils.clamp((int)(g+0.5)); int ib = PixelUtils.clamp((int)(b+0.5)); outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib; } } } public String toString() { return "Blur/Convolve..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/SkeletonFilter.java0000644000175000017500000000667610521402274022560 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; // Based on an algorithm by Zhang and Suen (CACM, March 1984, 236-239). public class SkeletonFilter extends BinaryFilter { private final static byte[] skeletonTable = { 0, 0, 0, 1, 0, 0, 1, 3, 0, 0, 3, 1, 1, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 3, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 2, 0, 0, 1, 3, 1, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 1, 3, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 1, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0, 0 }; public SkeletonFilter() { newColor = 0xffffffff; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int[] outPixels = new int[width * height]; int count = 0; int black = 0xff000000; int white = 0xffffffff; for (int i = 0; i < iterations; i++) { count = 0; for (int pass = 0; pass < 2; pass++) { for (int y = 1; y < height-1; y++) { int offset = y*width+1; for (int x = 1; x < width-1; x++) { int pixel = inPixels[offset]; if (pixel == black) { int tableIndex = 0; if (inPixels[offset-width-1] == black) tableIndex |= 1; if (inPixels[offset-width] == black) tableIndex |= 2; if (inPixels[offset-width+1] == black) tableIndex |= 4; if (inPixels[offset+1] == black) tableIndex |= 8; if (inPixels[offset+width+1] == black) tableIndex |= 16; if (inPixels[offset+width] == black) tableIndex |= 32; if (inPixels[offset+width-1] == black) tableIndex |= 64; if (inPixels[offset-1] == black) tableIndex |= 128; int code = skeletonTable[tableIndex]; if (pass == 1) { if (code == 2 || code == 3) { if (colormap != null) pixel = colormap.getColor((float)i/iterations); else pixel = newColor; count++; } } else { if (code == 1 || code == 3) { if (colormap != null) pixel = colormap.getColor((float)i/iterations); else pixel = newColor; count++; } } } outPixels[offset++] = pixel; } } if (pass == 0) { inPixels = outPixels; outPixels = new int[width * height]; } } if (count == 0) break; } return outPixels; } public String toString() { return "Binary/Skeletonize..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/MirrorFilter.java0000644000175000017500000000510410521402274022227 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; public class MirrorFilter extends AbstractBufferedImageOp { private float opacity = 1.0f; private float centreY = 0.5f; private float distance; private float angle; private float rotation; private float gap; public MirrorFilter() { } public void setAngle( float angle ) { this.angle = angle; } public float getAngle() { return angle; } public void setDistance( float distance ) { this.distance = distance; } public float getDistance() { return distance; } public void setRotation( float rotation ) { this.rotation = rotation; } public float getRotation() { return rotation; } public void setGap( float gap ) { this.gap = gap; } public float getGap() { return gap; } public void setOpacity( float opacity ) { this.opacity = opacity; } public float getOpacity() { return opacity; } public void setCentreY( float centreY ) { this.centreY = centreY; } public float getCentreY() { return centreY; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { if ( dst == null ) dst = createCompatibleDestImage( src, null ); BufferedImage tsrc = src; Shape clip; int width = src.getWidth(); int height = src.getHeight(); int h = (int)(centreY * height); int d = (int)(gap * height); Graphics2D g = dst.createGraphics(); clip = g.getClip(); g.clipRect( 0, 0, width, h ); g.drawRenderedImage( src, null ); g.setClip( clip ); g.clipRect( 0, h+d, width, height-h-d ); g.translate( 0, 2*h+d ); g.scale( 1, -1 ); g.drawRenderedImage( src, null ); g.setPaint( new GradientPaint( 0, 0, new Color( 1.0f, 0.0f, 0.0f, 0.0f ), 0, h, new Color( 0.0f, 1.0f, 0.0f, opacity ) ) ); g.setComposite( AlphaComposite.getInstance( AlphaComposite.DST_IN ) ); g.fillRect( 0, 0, width, h ); g.setClip( clip ); g.dispose(); return dst; } public String toString() { return "Effects/Mirror..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/DisplaceFilter.java0000644000175000017500000000566310521402272022511 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import com.jhlabs.math.*; /** * A filter which simulates the appearance of looking through glass. A separate grayscale displacement image is provided and * pixels in the source image are displaced according to the gradient of the displacement map. */ public class DisplaceFilter extends TransformFilter { private float amount = 1; private BufferedImage displacementMap = null; private int[] xmap, ymap; private int dw, dh; public DisplaceFilter() { } public void setDisplacementMap(BufferedImage displacementMap) { this.displacementMap = displacementMap; } public BufferedImage getDisplacementMap() { return displacementMap; } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int w = src.getWidth(); int h = src.getHeight(); BufferedImage dm = displacementMap != null ? displacementMap : src; dw = dm.getWidth(); dh = dm.getHeight(); int[] mapPixels = new int[dw*dh]; getRGB( dm, 0, 0, dw, dh, mapPixels ); xmap = new int[dw*dh]; ymap = new int[dw*dh]; int i = 0; for ( int y = 0; y < dh; y++ ) { for ( int x = 0; x < dw; x++ ) { int rgb = mapPixels[i]; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; mapPixels[i] = (r+g+b) / 8; // An arbitrary scaling factor which gives a good range for "amount" i++; } } i = 0; for ( int y = 0; y < dh; y++ ) { int j1 = ((y+dh-1) % dh) * dw; int j2 = y*dw; int j3 = ((y+1) % dh) * dw; for ( int x = 0; x < dw; x++ ) { int k1 = (x+dw-1) % dw; int k2 = x; int k3 = (x+1) % dw; xmap[i] = mapPixels[k1+j1] + mapPixels[k1+j2] + mapPixels[k1+j3] - mapPixels[k3+j1] - mapPixels[k3+j2] - mapPixels[k3+j3]; ymap[i] = mapPixels[k1+j3] + mapPixels[k2+j3] + mapPixels[k3+j3] - mapPixels[k1+j1] - mapPixels[k2+j1] - mapPixels[k3+j1]; i++; } } mapPixels = null; dst = super.filter( src, dst ); xmap = ymap = null; return dst; } protected void transformInverse(int x, int y, float[] out) { float xDisplacement, yDisplacement; float nx = x; float ny = y; int i = (y % dh)*dw + x % dw; out[0] = x + amount * xmap[i]; out[1] = y + amount * ymap[i]; } public String toString() { return "Distort/Displace..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/MotionBlurOp.java0000644000175000017500000001050310521402274022177 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; public class MotionBlurOp extends AbstractBufferedImageOp { private float centreX = 0.5f, centreY = 0.5f; private float distance; private float angle; private float rotation; private float zoom; public MotionBlurOp() { } public MotionBlurOp( float distance, float angle, float rotation, float zoom ) { this.distance = distance; this.angle = angle; this.rotation = rotation; this.zoom = zoom; } public void setAngle( float angle ) { this.angle = angle; } public float getAngle() { return angle; } public void setDistance( float distance ) { this.distance = distance; } public float getDistance() { return distance; } public void setRotation( float rotation ) { this.rotation = rotation; } public float getRotation() { return rotation; } public void setZoom( float zoom ) { this.zoom = zoom; } public float getZoom() { return zoom; } public void setCentreX( float centreX ) { this.centreX = centreX; } public float getCentreX() { return centreX; } public void setCentreY( float centreY ) { this.centreY = centreY; } public float getCentreY() { return centreY; } public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } private int log2( int n ) { int m = 1; int log2n = 0; while (m < n) { m *= 2; log2n++; } return log2n; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { if ( dst == null ) dst = createCompatibleDestImage( src, null ); BufferedImage tsrc = src; float cx = (float)src.getWidth() * centreX; float cy = (float)src.getHeight() * centreY; float imageRadius = (float)Math.sqrt( cx*cx + cy*cy ); float translateX = (float)(distance * Math.cos( angle )); float translateY = (float)(distance * -Math.sin( angle )); float scale = zoom; float rotate = rotation; float maxDistance = distance + Math.abs(rotation*imageRadius) + zoom*imageRadius; int steps = log2((int)maxDistance); translateX /= maxDistance; translateY /= maxDistance; scale /= maxDistance; rotate /= maxDistance; if ( steps == 0 ) { Graphics2D g = dst.createGraphics(); g.drawRenderedImage( src, null ); g.dispose(); return dst; } BufferedImage tmp = createCompatibleDestImage( src, null ); for ( int i = 0; i < steps; i++ ) { Graphics2D g = tmp.createGraphics(); g.drawImage( tsrc, null, null ); g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR ); g.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f ) ); g.translate( cx+translateX, cy+translateY ); g.scale( 1.0001+scale, 1.0001+scale ); // The .0001 works round a bug on Windows where drawImage throws an ArrayIndexOutofBoundException if ( rotation != 0 ) g.rotate( rotate ); g.translate( -cx, -cy ); g.drawImage( dst, null, null ); g.dispose(); BufferedImage ti = dst; dst = tmp; tmp = ti; tsrc = dst; translateX *= 2; translateY *= 2; scale *= 2; rotate *= 2; } return dst; } public String toString() { return "Blur/Motion Blur..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/Spectrum.java0000644000175000017500000000404210521402274021411 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; public class Spectrum { private static int adjust(float color, float factor, float gamma) { if (color == 0.0) return 0; return (int)Math.round(255 * Math.pow(color * factor, gamma)); } /** * @param wavelength wavelength in nanometres */ public static int wavelengthToRGB(float wavelength) { float gamma = 0.80f; float r, g, b, factor; int w = (int)wavelength; if (w < 380) { r = 0.0f; g = 0.0f; b = 0.0f; } else if (w < 440) { r = -(wavelength - 440) / (440 - 380); g = 0.0f; b = 1.0f; } else if (w < 490) { r = 0.0f; g = (wavelength - 440) / (490 - 440); b = 1.0f; } else if (w < 510) { r = 0.0f; g = 1.0f; b = -(wavelength - 510) / (510 - 490); } else if (w < 580) { r = (wavelength - 510) / (580 - 510); g = 1.0f; b = 0.0f; } else if (w < 645) { r = 1.0f; g = -(wavelength - 645) / (645 - 580); b = 0.0f; } else if (w <= 780) { r = 1.0f; g = 0.0f; b = 0.0f; } else { r = 0.0f; g = 0.0f; b = 0.0f; } // Let the intensity fall off near the vision limits if (380 <= w && w <= 419) factor = 0.3f + 0.7f*(wavelength - 380) / (420 - 380); else if (420 <= w && w <= 700) factor = 1.0f; else if (701 <= w && w <= 780) factor = 0.3f + 0.7f*(780 - wavelength) / (780 - 700); else factor = 0.0f; int ir = adjust(r, factor, gamma); int ig = adjust(g, factor, gamma); int ib = adjust(b, factor, gamma); return 0xff000000 | (ir << 16) | (ig << 8) | ib; } } jhlabs-filters-2.0.235/com/jhlabs/image/DespeckleFilter.java0000644000175000017500000000560410521402272022657 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class DespeckleFilter extends WholeImageFilter { public DespeckleFilter() { } protected short pepperAndSalt( short c, short v1, short v2 ) { if ( c < v1 ) c++; if ( c < v2 ) c++; if ( c > v1 ) c--; if ( c > v2 ) c--; return c; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; short[][] r = new short[3][width]; short[][] g = new short[3][width]; short[][] b = new short[3][width]; int[] outPixels = new int[width * height]; for (int x = 0; x < width; x++) { int rgb = inPixels[x]; r[1][x] = (short)((rgb >> 16) & 0xff); g[1][x] = (short)((rgb >> 8) & 0xff); b[1][x] = (short)(rgb & 0xff); } for (int y = 0; y < height; y++) { boolean yIn = y > 0 && y < height-1; int nextRowIndex = index+width; if ( y < height-1) { for (int x = 0; x < width; x++) { int rgb = inPixels[nextRowIndex++]; r[2][x] = (short)((rgb >> 16) & 0xff); g[2][x] = (short)((rgb >> 8) & 0xff); b[2][x] = (short)(rgb & 0xff); } } for (int x = 0; x < width; x++) { boolean xIn = x > 0 && x < width-1; short or = r[1][x]; short og = g[1][x]; short ob = b[1][x]; int w = x-1; int e = x+1; if ( yIn ) { or = pepperAndSalt( or, r[0][x], r[2][x] ); og = pepperAndSalt( og, g[0][x], g[2][x] ); ob = pepperAndSalt( ob, b[0][x], b[2][x] ); } if ( xIn ) { or = pepperAndSalt( or, r[1][w], r[1][e] ); og = pepperAndSalt( og, g[1][w], g[1][e] ); ob = pepperAndSalt( ob, b[1][w], b[1][e] ); } if ( yIn && xIn ) { or = pepperAndSalt( or, r[0][w], r[2][e] ); og = pepperAndSalt( og, g[0][w], g[2][e] ); ob = pepperAndSalt( ob, b[0][w], b[2][e] ); or = pepperAndSalt( or, r[2][w], r[0][e] ); og = pepperAndSalt( og, g[2][w], g[0][e] ); ob = pepperAndSalt( ob, b[2][w], b[0][e] ); } outPixels[index] = (inPixels[index] & 0xff000000) | (or << 16) | (og << 8) | ob; index++; } short[] t; t = r[0]; r[0] = r[1]; r[1] = r[2]; r[2] = t; t = g[0]; g[0] = g[1]; g[1] = g[2]; g[2] = t; t = b[0]; b[0] = b[1]; b[1] = b[2]; b[2] = t; } return outPixels; } public String toString() { return "Blur/Despeckle..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/CheckFilter.java0000644000175000017500000000512310521402272021771 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A Filter to draw grids and check patterns. */ public class CheckFilter extends PointFilter { private int xScale = 8; private int yScale = 8; private int foreground = 0xffffffff; private int background = 0xff000000; private int fuzziness = 0; private float angle = 0.0f; private int operation; private float m00 = 1.0f; private float m01 = 0.0f; private float m10 = 0.0f; private float m11 = 1.0f; public CheckFilter() { } public void setForeground(int foreground) { this.foreground = foreground; } public int getForeground() { return foreground; } public void setBackground(int background) { this.background = background; } public int getBackground() { return background; } public void setXScale(int xScale) { this.xScale = xScale; } public int getXScale() { return xScale; } public void setYScale(int yScale) { this.yScale = yScale; } public int getYScale() { return yScale; } public void setFuzziness(int fuzziness) { this.fuzziness = fuzziness; } public int getFuzziness() { return fuzziness; } public void setOperation(int operation) { this.operation = operation; } public int getOperation() { return operation; } public void setAngle(float angle) { this.angle = angle; float cos = (float)Math.cos(angle); float sin = (float)Math.sin(angle); m00 = cos; m01 = sin; m10 = -sin; m11 = cos; } public float getAngle() { return angle; } public int filterRGB(int x, int y, int rgb) { float nx = (m00*x + m01*y) / xScale; float ny = (m10*x + m11*y) / yScale; float f = ((int)(nx+100000) % 2 != (int)(ny+100000) % 2) ? 1.0f : 0.0f; if (fuzziness != 0) { float fuzz = (fuzziness/100.0f); float fx = ImageMath.smoothPulse(0, fuzz, 1-fuzz, 1, ImageMath.mod(nx, 1)); float fy = ImageMath.smoothPulse(0, fuzz, 1-fuzz, 1, ImageMath.mod(ny, 1)); f *= fx*fy; } return ImageMath.mixColors(f, foreground, background); } public String toString() { return "Texture/Checkerboard..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/PointFilter.java0000644000175000017500000000401710521402274022050 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * An abstract superclass for point filters. The interface is the same as the old RGBImageFilter. */ public abstract class PointFilter extends AbstractBufferedImageOp { protected boolean canFilterIndexColorModel = false; public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int type = src.getType(); WritableRaster srcRaster = src.getRaster(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); WritableRaster dstRaster = dst.getRaster(); setDimensions( width, height); int[] inPixels = new int[width]; for ( int y = 0; y < height; y++ ) { // We try to avoid calling getRGB on images as it causes them to become unmanaged, causing horrible performance problems. if ( type == BufferedImage.TYPE_INT_ARGB ) { srcRaster.getDataElements( 0, y, width, 1, inPixels ); for ( int x = 0; x < width; x++ ) inPixels[x] = filterRGB( x, y, inPixels[x] ); dstRaster.setDataElements( 0, y, width, 1, inPixels ); } else { src.getRGB( 0, y, width, 1, inPixels, 0, width ); for ( int x = 0; x < width; x++ ) inPixels[x] = filterRGB( x, y, inPixels[x] ); dst.setRGB( 0, y, width, 1, inPixels, 0, width ); } } return dst; } public void setDimensions(int width, int height) { } public abstract int filterRGB(int x, int y, int rgb); } jhlabs-filters-2.0.235/com/jhlabs/image/PolarFilter.java0000644000175000017500000001067510521402274022043 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class PolarFilter extends TransformFilter { public final static int RECT_TO_POLAR = 0; public final static int POLAR_TO_RECT = 1; public final static int INVERT_IN_CIRCLE = 2; private int type; private float width, height; private float centreX, centreY; private float radius; public PolarFilter() { this(RECT_TO_POLAR); } public PolarFilter(int type) { this.type = type; setEdgeAction(CLAMP); } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { this.width = src.getWidth(); this.height = src.getHeight(); centreX = width/2; centreY = height/2; radius = Math.max(centreY, centreX); return super.filter( src, dst ); } public void setType(int type) { this.type = type; } public int getType() { return type; } private float sqr(float x) { return x*x; } protected void transformInverse(int x, int y, float[] out) { float theta, t; float m, xmax, ymax; float r = 0; switch (type) { case RECT_TO_POLAR: theta = 0; if (x >= centreX) { if (y > centreY) { theta = ImageMath.PI - (float)Math.atan(((float)(x - centreX))/((float)(y - centreY))); r = (float)Math.sqrt(sqr (x - centreX) + sqr (y - centreY)); } else if (y < centreY) { theta = (float)Math.atan (((float)(x - centreX))/((float)(centreY - y))); r = (float)Math.sqrt (sqr (x - centreX) + sqr (centreY - y)); } else { theta = ImageMath.HALF_PI; r = x - centreX; } } else if (x < centreX) { if (y < centreY) { theta = ImageMath.TWO_PI - (float)Math.atan (((float)(centreX -x))/((float)(centreY - y))); r = (float)Math.sqrt (sqr (centreX - x) + sqr (centreY - y)); } else if (y > centreY) { theta = ImageMath.PI + (float)Math.atan (((float)(centreX - x))/((float)(y - centreY))); r = (float)Math.sqrt (sqr (centreX - x) + sqr (y - centreY)); } else { theta = 1.5f * ImageMath.PI; r = centreX - x; } } if (x != centreX) m = Math.abs (((float)(y - centreY)) / ((float)(x - centreX))); else m = 0; if (m <= ((float)height / (float)width)) { if (x == centreX) { xmax = 0; ymax = centreY; } else { xmax = centreX; ymax = m * xmax; } } else { ymax = centreY; xmax = ymax / m; } out[0] = (width-1) - (width - 1)/ImageMath.TWO_PI * theta; out[1] = height * r / radius; break; case POLAR_TO_RECT: theta = x / width * ImageMath.TWO_PI; float theta2; if (theta >= 1.5f * ImageMath.PI) theta2 = ImageMath.TWO_PI - theta; else if (theta >= ImageMath.PI) theta2 = theta - ImageMath.PI; else if (theta >= 0.5f * ImageMath.PI) theta2 = ImageMath.PI - theta; else theta2 = theta; t = (float)Math.tan(theta2); if (t != 0) m = 1.0f / t; else m = 0; if (m <= ((float)(height) / (float)(width))) { if (theta2 == 0) { xmax = 0; ymax = centreY; } else { xmax = centreX; ymax = m * xmax; } } else { ymax = centreY; xmax = ymax / m; } r = radius * (float)(y / (float)(height)); float nx = -r * (float)Math.sin(theta2); float ny = r * (float)Math.cos(theta2); if (theta >= 1.5f * ImageMath.PI) { out[0] = (float)centreX - nx; out[1] = (float)centreY - ny; } else if (theta >= Math.PI) { out[0] = (float)centreX - nx; out[1] = (float)centreY + ny; } else if (theta >= 0.5 * Math.PI) { out[0] = (float)centreX + nx; out[1] = (float)centreY + ny; } else { out[0] = (float)centreX + nx; out[1] = (float)centreY - ny; } break; case INVERT_IN_CIRCLE: float dx = x-centreX; float dy = y-centreY; float distance2 = dx*dx+dy*dy; out[0] = centreX + centreX*centreX * dx/distance2; out[1] = centreY + centreY*centreY * dy/distance2; break; } } public String toString() { return "Distort/Polar Coordinates..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ArrayColormap.java0000644000175000017500000000563510521402272022371 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; /** * A colormap implemented with an array of colors. This corresponds to the IndexColorModel class. */ public class ArrayColormap implements Colormap, Cloneable, java.io.Serializable { static final long serialVersionUID = -7990431442314209043L; /** * The array of colors. */ protected int[] map; /** * Construct an all-black colormap */ public ArrayColormap() { this.map = new int[256]; } /** * Construct a colormap with the given map * @param map the array of ARGB colors */ public ArrayColormap(int[] map) { this.map = map; } public Object clone() { try { ArrayColormap g = (ArrayColormap)super.clone(); g.map = (int[])map.clone(); return g; } catch (CloneNotSupportedException e) { } return null; } public void setMap(int[] map) { this.map = map; } public int[] getMap() { return map; } /** * Convert a value in the range 0..1 to an RGB color. * @param v a value in the range 0..1 * @return an RGB color */ public int getColor(float v) { /* v *= 255; int n = (int)v; float f = v-n; if (n < 0) return map[0]; else if (n >= 255) return map[255]; return ImageMath.mixColors(f, map[n], map[n+1]); */ int n = (int)(v*255); if (n < 0) n = 0; else if (n > 255) n = 255; return map[n]; } /** * Set the color at "index" to "color". Entries are interpolated linearly from * the existing entries at "firstIndex" and "lastIndex" to the new entry. * firstIndex < index < lastIndex must hold. */ public void setColorInterpolated(int index, int firstIndex, int lastIndex, int color) { int firstColor = map[firstIndex]; int lastColor = map[lastIndex]; for (int i = firstIndex; i <= index; i++) map[i] = ImageMath.mixColors((float)(i-firstIndex)/(index-firstIndex), firstColor, color); for (int i = index; i < lastIndex; i++) map[i] = ImageMath.mixColors((float)(i-index)/(lastIndex-index), color, lastColor); } public void setColorRange(int firstIndex, int lastIndex, int color1, int color2) { for (int i = firstIndex; i <= lastIndex; i++) map[i] = ImageMath.mixColors((float)(i-firstIndex)/(lastIndex-firstIndex), color1, color2); } public void setColorRange(int firstIndex, int lastIndex, int color) { for (int i = firstIndex; i <= lastIndex; i++) map[i] = color; } public void setColor(int index, int color) { map[index] = color; } } jhlabs-filters-2.0.235/com/jhlabs/image/CircleFilter.java0000644000175000017500000000535510521402272022164 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; public class CircleFilter extends TransformFilter { private float radius = 10; private float height = 20; private float angle = 0; private float spreadAngle = (float)Math.PI; private float centreX = 0.5f; private float centreY = 0.5f; private float icentreX; private float icentreY; private float iWidth; private float iHeight; public CircleFilter() { setEdgeAction( ZERO ); } public void setHeight(float height) { this.height = height; } public float getHeight() { return height; } public void setAngle(float angle) { this.angle = angle; } public float getAngle() { return angle; } public void setSpreadAngle(float spreadAngle) { this.spreadAngle = spreadAngle; } public float getSpreadAngle() { return spreadAngle; } public void setRadius(float r) { this.radius = r; } public float getRadius() { return radius; } public void setCentreX( float centreX ) { this.centreX = centreX; } public float getCentreX() { return centreX; } public void setCentreY( float centreY ) { this.centreY = centreY; } public float getCentreY() { return centreY; } public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { iWidth = src.getWidth(); iHeight = src.getHeight(); icentreX = iWidth * centreX; icentreY = iHeight * centreY; iWidth--; return super.filter( src, dst ); } protected void transformInverse(int x, int y, float[] out) { float dx = x-icentreX; float dy = y-icentreY; float theta = (float)Math.atan2( -dy, -dx ) + angle; float r = (float)Math.sqrt( dx*dx + dy*dy ); /* if ( theta < 0 ) theta += 2*(float)Math.PI; else if ( theta > 2*(float)Math.PI ) theta -= 2*(float)Math.PI; */ theta = ImageMath.mod( theta, 2*(float)Math.PI ); out[0] = iWidth * theta/(spreadAngle+0.00001f); out[1] = iHeight * (1-(r-radius)/(height+0.00001f)); } public String toString() { return "Distort/Circle..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/FlipFilter.java0000644000175000017500000000703110521402272021646 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A filter which flips images or rotates by multiples of 90 degrees. */ public class FlipFilter extends AbstractBufferedImageOp { public static final int FLIP_H = 1; public static final int FLIP_V = 2; public static final int FLIP_HV = 3; public static final int FLIP_90CW = 4; public static final int FLIP_90CCW = 5; public static final int FLIP_180 = 6; private int operation; private int width, height; private int newWidth, newHeight; public FlipFilter() { this(FLIP_HV); } public FlipFilter(int operation) { this.operation = operation; } public void setOperation(int operation) { this.operation = operation; } public int getOperation() { return operation; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int type = src.getType(); WritableRaster srcRaster = src.getRaster(); int[] inPixels = getRGB( src, 0, 0, width, height, null ); int x = 0, y = 0; int w = width; int h = height; int newX = 0; int newY = 0; int newW = w; int newH = h; switch (operation) { case FLIP_H: newX = width - (x + w); break; case FLIP_V: newY = height - (y + h); break; case FLIP_HV: newW = h; newH = w; newX = y; newY = x; break; case FLIP_90CW: newW = h; newH = w; newX = height - (y + h); newY = x; break; case FLIP_90CCW: newW = h; newH = w; newX = y; newY = width - (x + w); break; case FLIP_180: newX = width - (x + w); newY = height - (y + h); break; } int[] newPixels = new int[newW * newH]; for (int row = 0; row < h; row++) { for (int col = 0; col < w; col++) { int index = row * width + col; int newRow = row; int newCol = col; switch (operation) { case FLIP_H: newCol = w - col - 1; break; case FLIP_V: newRow = h - row - 1; break; case FLIP_HV: newRow = col; newCol = row; break; case FLIP_90CW: newRow = col; newCol = h - row - 1;; break; case FLIP_90CCW: newRow = w - col - 1; newCol = row; break; case FLIP_180: newRow = h - row - 1; newCol = w - col - 1; break; } int newIndex = newRow * newW + newCol; newPixels[newIndex] = inPixels[index]; } } if ( dst == null ) { ColorModel dstCM = src.getColorModel(); dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(newW, newH), dstCM.isAlphaPremultiplied(), null); } WritableRaster dstRaster = dst.getRaster(); setRGB( dst, 0, 0, newW, newH, newPixels ); return dst; } public String toString() { switch (operation) { case FLIP_H: return "Flip Horizontal"; case FLIP_V: return "Flip Vertical"; case FLIP_HV: return "Flip Diagonal"; case FLIP_90CW: return "Rotate 90"; case FLIP_90CCW: return "Rotate -90"; case FLIP_180: return "Rotate 180"; } return "Flip"; } } jhlabs-filters-2.0.235/com/jhlabs/image/QuiltFilter.java0000644000175000017500000000736110521402274022062 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.util.*; import java.awt.*; import java.awt.image.*; import com.jhlabs.math.*; public class QuiltFilter extends WholeImageFilter implements java.io.Serializable { private Random randomGenerator; private long seed = 567; private int iterations = 25000; private float a = -0.59f; private float b = 0.2f; private float c = 0.1f; private float d = 0; private int k = 0; private Colormap colormap = new LinearColormap(); public QuiltFilter() { randomGenerator = new Random(); } public void randomize() { seed = new Date().getTime(); randomGenerator.setSeed(seed); a = randomGenerator.nextFloat(); b = randomGenerator.nextFloat(); c = randomGenerator.nextFloat(); d = randomGenerator.nextFloat(); k = randomGenerator.nextInt() % 20 - 10; } public void setIterations(int iterations) { this.iterations = iterations; } public int getIterations() { return iterations; } public void setA(float a) { this.a = a; } public float getA() { return a; } public void setB(float b) { this.b = b; } public float getB() { return b; } public void setC(float c) { this.c = c; } public float getC() { return c; } public void setD(float d) { this.d = d; } public float getD() { return d; } public void setK(int k) { this.k = k; } public int getK() { return k; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int[] outPixels = new int[width * height]; int i = 0; int max = 0; float x = 0.1f; float y = 0.3f; for (int n = 0; n < 20; n++) { float mx = ImageMath.PI*x; float my = ImageMath.PI*y; float smx2 = (float)Math.sin(2*mx); float smy2 = (float)Math.sin(2*my); float x1 = (float)(a*smx2 + b*smx2*Math.cos(2*my) + c*Math.sin(4*mx) + d*Math.sin(6*mx)*Math.cos(4*my) + k*x); x1 = x1 >= 0 ? x1 - (int)x1 : x1 - (int)x1 + 1; float y1 = (float)(a*smy2 + b*smy2*Math.cos(2*mx) + c*Math.sin(4*my) + d*Math.sin(6*my)*Math.cos(4*mx) + k*y); y1 = y1 >= 0 ? y1 - (int)y1 : y1 - (int)y1 + 1; x = x1; y = y1; } for (int n = 0; n < iterations; n++) { float mx = ImageMath.PI*x; float my = ImageMath.PI*y; float x1 = (float)(a*Math.sin(2*mx) + b*Math.sin(2*mx)*Math.cos(2*my) + c*Math.sin(4*mx) + d*Math.sin(6*mx)*Math.cos(4*my) + k*x); x1 = x1 >= 0 ? x1 - (int)x1 : x1 - (int)x1 + 1; float y1 = (float)(a*Math.sin(2*my) + b*Math.sin(2*my)*Math.cos(2*mx) + c*Math.sin(4*my) + d*Math.sin(6*my)*Math.cos(4*mx) + k*y); y1 = y1 >= 0 ? y1 - (int)y1 : y1 - (int)y1 + 1; x = x1; y = y1; int ix = (int)(width*x); int iy = (int)(height*y); if (ix >= 0 && ix < width && iy >= 0 && iy < height) { int t = outPixels[width*iy+ix]++; if (t > max) max = t; } } if (colormap != null) { int index = 0; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { outPixels[index] = colormap.getColor(outPixels[index] / (float)max); index++; } } } return outPixels; } public String toString() { return "Texture/Chaotic Quilt..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/GainFilter.java0000644000175000017500000000224010521402272021627 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class GainFilter extends TransferFilter { private float gain = 0.5f; private float bias = 0.5f; protected float transferFunction( float f ) { f = ImageMath.gain(f, gain); f = ImageMath.bias(f, bias); return f; } public void setGain(float gain) { this.gain = gain; initialized = false; } public float getGain() { return gain; } public void setBias(float bias) { this.bias = bias; initialized = false; } public float getBias() { return bias; } public String toString() { return "Colors/Gain..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/DitherFilter.java0000644000175000017500000001433310521402272022176 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class DitherFilter extends PointFilter implements java.io.Serializable { static final long serialVersionUID = 2408287445119636967L; protected final static int[] ditherMagic2x2Matrix = { 0, 2, 3, 1 }; protected final static int[] ditherMagic4x4Matrix = { 0, 14, 3, 13, 11, 5, 8, 6, 12, 2, 15, 1, 7, 9, 4, 10 }; public final static int[] ditherOrdered4x4Matrix = { 0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5 }; public final static int[] ditherLines4x4Matrix = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; public final static int[] dither90Halftone6x6Matrix = { 29, 18, 12, 19, 30, 34, 17, 7, 4, 8, 20, 28, 11, 3, 0, 1, 9, 27, 16, 6, 2, 5, 13, 26, 25, 15, 10, 14, 21, 31, 33, 25, 24, 23, 33, 36 }; /* * The following dithering matrices are taken from "Digital Halftoning" * by Robert Ulichney, MIT Press, ISBN 0-262-21009-6. */ /* Order-6 ordered dither */ public final static int[] ditherOrdered6x6Matrix = { 1, 59, 15, 55, 2, 56, 12, 52, 33, 17, 47, 31, 34, 18, 44, 28, 9, 49, 5, 63, 10, 50, 6, 60, 41, 25, 37, 21, 42, 26, 38, 22, 3, 57, 13, 53, 0, 58, 14, 54, 35, 19, 45, 29, 32, 16, 46, 30, 11, 51, 7, 61, 8, 48, 4, 62, 43, 27, 39, 23, 40, 24, 36, 20 }; /* Order-8 ordered dither */ public final static int[] ditherOrdered8x8Matrix = { 1,235, 59,219, 15,231, 55,215, 2,232, 56,216, 12,228, 52,212, 129, 65,187,123,143, 79,183,119,130, 66,184,120,140, 76,180,116, 33,193, 17,251, 47,207, 31,247, 34,194, 18,248, 44,204, 28,244, 161, 97,145, 81,175,111,159, 95,162, 98,146, 82,172,108,156, 92, 9,225, 49,209, 5,239, 63,223, 10,226, 50,210, 6,236, 60,220, 137, 73,177,113,133, 69,191,127,138, 74,178,114,134, 70,188,124, 41,201, 25,241, 37,197, 21,255, 42,202, 26,242, 38,198, 22,252, 169,105,153, 89,165,101,149, 85,170,106,154, 90,166,102,150, 86, 3,233, 57,217, 13,229, 53,213, 0,234, 58,218, 14,230, 54,214, 131, 67,185,121,141, 77,181,117,128, 64,186,122,142, 78,182,118, 35,195, 19,249, 45,205, 29,245, 32,192, 16,250, 46,206, 30,246, 163, 99,147, 83,173,109,157, 93,160, 96,144, 80,174,110,158, 94, 11,227, 51,211, 7,237, 61,221, 8,224, 48,208, 4,238, 62,222, 139, 75,179,115,135, 71,189,125,136, 72,176,112,132, 68,190,126, 43,203, 27,243, 39,199, 23,253, 40,200, 24,240, 36,196, 20,254, 171,107,155, 91,167,103,151, 87,168,104,152, 88,164,100,148, 84 }; /* Order-3 clustered dither */ public final static int[] ditherCluster3Matrix = { 9,11,10, 8, 6, 7, 12,17,16, 5, 0, 1, 13,14,15, 4, 3, 2, 8, 6, 7, 9,11,10, 5, 0, 1,12,17,16, 4, 3, 2,13,14,15 }; /* Order-4 clustered dither */ public final static int[] ditherCluster4Matrix = { 18,20,19,16,13,11,12,15, 27,28,29,22, 4, 3, 2, 9, 26,31,30,21, 5, 0, 1,10, 23,25,24,17, 8, 6, 7,14, 13,11,12,15,18,20,19,16, 4, 3, 2, 9,27,28,29,22, 5, 0, 1,10,26,31,30,21, 8, 6, 7,14,23,25,24,17 }; /* Order-8 clustered dither */ public final static int[] ditherCluster8Matrix = { 64, 69, 77, 87, 86, 76, 68, 67, 63, 58, 50, 40, 41, 51, 59, 60, 70, 94,100,109,108, 99, 93, 75, 57, 33, 27, 18, 19, 28, 34, 52, 78,101,114,116,115,112, 98, 83, 49, 26, 13, 11, 12, 15, 29, 44, 88,110,123,124,125,118,107, 85, 39, 17, 4, 3, 2, 9, 20, 42, 89,111,122,127,126,117,106, 84, 38, 16, 5, 0, 1, 10, 21, 43, 79,102,119,121,120,113, 97, 82, 48, 25, 8, 6, 7, 14, 30, 45, 71, 95,103,104,105, 96, 92, 74, 56, 32, 24, 23, 22, 31, 35, 53, 65, 72, 80, 90, 91, 81, 73, 66, 62, 55, 47, 37, 36, 46, 54, 61, 63, 58, 50, 40, 41, 51, 59, 60, 64, 69, 77, 87, 86, 76, 68, 67, 57, 33, 27, 18, 19, 28, 34, 52, 70, 94,100,109,108, 99, 93, 75, 49, 26, 13, 11, 12, 15, 29, 44, 78,101,114,116,115,112, 98, 83, 39, 17, 4, 3, 2, 9, 20, 42, 88,110,123,124,125,118,107, 85, 38, 16, 5, 0, 1, 10, 21, 43, 89,111,122,127,126,117,106, 84, 48, 25, 8, 6, 7, 14, 30, 45, 79,102,119,121,120,113, 97, 82, 56, 32, 24, 23, 22, 31, 35, 53, 71, 95,103,104,105, 96, 92, 74, 62, 55, 47, 37, 36, 46, 54, 61, 65, 72, 80, 90, 91, 81, 73, 66 }; public int[] matrix; public int rows, cols, levels; protected int[] mod; protected int[] div; protected int[] map; public boolean colorDither; private boolean initialized = false; public DitherFilter() { rows = 2; cols = 2; matrix = ditherMagic4x4Matrix; levels = 6; colorDither = true; } public void setMatrix(int[] matrix) { this.matrix = matrix; } public int[] getMatrix() { return matrix; } public void setLevels(int levels) { this.levels = levels; } public int getLevels() { return levels; } protected void initialize() { rows = cols = (int)Math.sqrt(matrix.length); map = new int[levels]; for (int i = 0; i < levels; i++) { int v = 255 * i / (levels-1); map[i] = v; } div = new int[256]; mod = new int[256]; int rc = (rows*cols+1); for (int i = 0; i < 256; i++) { div[i] = (levels-1)*i / 256; mod[i] = i*rc/256; } } public int filterRGB(int x, int y, int rgb) { if (!initialized) { initialized = true; initialize(); } int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; int col = x % cols; int row = y % rows; int v = matrix[row*cols+col]; if (colorDither) { r = map[mod[r] > v ? div[r] + 1 : div[r]]; g = map[mod[g] > v ? div[g] + 1 : div[g]]; b = map[mod[b] > v ? div[b] + 1 : div[b]]; } else { int value = (r+g+b)/3; r = g = b = map[mod[value] > v ? div[value] + 1 : div[value]]; } return a | (r << 16) | (g << 8) | b; } public String toString() { return "Colors/Dither..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ShadeFilter.java0000644000175000017500000002123610521402274022005 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import com.jhlabs.math.*; import com.jhlabs.vecmath.*; import java.awt.*; import java.io.*; import java.util.*; public class ShadeFilter extends WholeImageFilter implements Serializable { public final static int COLORS_FROM_IMAGE = 0; public final static int COLORS_CONSTANT = 1; public final static int BUMPS_FROM_IMAGE = 0; public final static int BUMPS_FROM_IMAGE_ALPHA = 1; public final static int BUMPS_FROM_MAP = 2; public final static int BUMPS_FROM_BEVEL = 3; private float bumpHeight; private float bumpSoftness; private float viewDistance = 10000.0f; private int colorSource = COLORS_FROM_IMAGE; private int bumpSource = BUMPS_FROM_IMAGE; private Function2D bumpFunction; private BufferedImage environmentMap; private int[] envPixels; private int envWidth = 1, envHeight = 1; private Vector3f l; private Vector3f v; private Vector3f n; private Color4f shadedColor; private Color4f diffuse_color; private Color4f specular_color; private Vector3f tmpv, tmpv2; public ShadeFilter() { bumpHeight = 1.0f; bumpSoftness = 5.0f; l = new Vector3f(); v = new Vector3f(); n = new Vector3f(); shadedColor = new Color4f(); diffuse_color = new Color4f(); specular_color = new Color4f(); tmpv = new Vector3f(); tmpv2 = new Vector3f(); } public void setBumpFunction(Function2D bumpFunction) { this.bumpFunction = bumpFunction; } public Function2D getBumpFunction() { return bumpFunction; } public void setBumpHeight(float bumpHeight) { this.bumpHeight = bumpHeight; } public float getBumpHeight() { return bumpHeight; } public void setBumpSoftness(float bumpSoftness) { this.bumpSoftness = bumpSoftness; } public float getBumpSoftness() { return bumpSoftness; } public void setEnvironmentMap(BufferedImage environmentMap) { this.environmentMap = environmentMap; if (environmentMap != null) { envWidth = environmentMap.getWidth(); envHeight = environmentMap.getHeight(); envPixels = getRGB( environmentMap, 0, 0, envWidth, envHeight, null ); } else { envWidth = envHeight = 1; envPixels = null; } } public BufferedImage getEnvironmentMap() { return environmentMap; } public void setBumpSource(int bumpSource) { this.bumpSource = bumpSource; } public int getBumpSource() { return bumpSource; } protected final static float r255 = 1.0f/255.0f; protected void setFromRGB( Color4f c, int argb ) { c.set( ((argb >> 16) & 0xff) * r255, ((argb >> 8) & 0xff) * r255, (argb & 0xff) * r255, ((argb >> 24) & 0xff) * r255 ); } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] outPixels = new int[width * height]; float width45 = Math.abs(6.0f * bumpHeight); boolean invertBumps = bumpHeight < 0; Vector3f position = new Vector3f(0.0f, 0.0f, 0.0f); Vector3f viewpoint = new Vector3f((float)width / 2.0f, (float)height / 2.0f, viewDistance); Vector3f normal = new Vector3f(); Color4f c = new Color4f(); Function2D bump = bumpFunction; if (bumpSource == BUMPS_FROM_IMAGE || bumpSource == BUMPS_FROM_IMAGE_ALPHA || bumpSource == BUMPS_FROM_MAP || bump == null) { if ( bumpSoftness != 0 ) { int bumpWidth = width; int bumpHeight = height; int[] bumpPixels = inPixels; if ( bumpSource == BUMPS_FROM_MAP && bumpFunction instanceof ImageFunction2D ) { ImageFunction2D if2d = (ImageFunction2D)bumpFunction; bumpWidth = if2d.getWidth(); bumpHeight = if2d.getHeight(); bumpPixels = if2d.getPixels(); } Kernel kernel = GaussianFilter.makeKernel( bumpSoftness ); int [] tmpPixels = new int[bumpWidth * bumpHeight]; int [] softPixels = new int[bumpWidth * bumpHeight]; GaussianFilter.convolveAndTranspose( kernel, bumpPixels, tmpPixels, bumpWidth, bumpHeight, true, ConvolveFilter.CLAMP_EDGES); GaussianFilter.convolveAndTranspose( kernel, tmpPixels, softPixels, bumpHeight, bumpWidth, true, ConvolveFilter.CLAMP_EDGES); bump = new ImageFunction2D(softPixels, bumpWidth, bumpHeight, ImageFunction2D.CLAMP, bumpSource == BUMPS_FROM_IMAGE_ALPHA); } else bump = new ImageFunction2D(inPixels, width, height, ImageFunction2D.CLAMP, bumpSource == BUMPS_FROM_IMAGE_ALPHA); } Vector3f v1 = new Vector3f(); Vector3f v2 = new Vector3f(); Vector3f n = new Vector3f(); // Loop through each source pixel for (int y = 0; y < height; y++) { float ny = y; position.y = y; for (int x = 0; x < width; x++) { float nx = x; // Calculate the normal at this point if (bumpSource != BUMPS_FROM_BEVEL) { // Complicated and slower method // Calculate four normals using the gradients in +/- X/Y directions int count = 0; normal.x = normal.y = normal.z = 0; float m0 = width45*bump.evaluate(nx, ny); float m1 = x > 0 ? width45*bump.evaluate(nx - 1.0f, ny)-m0 : -2; float m2 = y > 0 ? width45*bump.evaluate(nx, ny - 1.0f)-m0 : -2; float m3 = x < width-1 ? width45*bump.evaluate(nx + 1.0f, ny)-m0 : -2; float m4 = y < height-1 ? width45*bump.evaluate(nx, ny + 1.0f)-m0 : -2; if (m1 != -2 && m4 != -2) { v1.x = -1.0f; v1.y = 0.0f; v1.z = m1; v2.x = 0.0f; v2.y = 1.0f; v2.z = m4; n.cross(v1, v2); n.normalize(); if (n.z < 0.0) n.z = -n.z; normal.add(n); count++; } if (m1 != -2 && m2 != -2) { v1.x = -1.0f; v1.y = 0.0f; v1.z = m1; v2.x = 0.0f; v2.y = -1.0f; v2.z = m2; n.cross(v1, v2); n.normalize(); if (n.z < 0.0) n.z = -n.z; normal.add(n); count++; } if (m2 != -2 && m3 != -2) { v1.x = 0.0f; v1.y = -1.0f; v1.z = m2; v2.x = 1.0f; v2.y = 0.0f; v2.z = m3; n.cross(v1, v2); n.normalize(); if (n.z < 0.0) n.z = -n.z; normal.add(n); count++; } if (m3 != -2 && m4 != -2) { v1.x = 1.0f; v1.y = 0.0f; v1.z = m3; v2.x = 0.0f; v2.y = 1.0f; v2.z = m4; n.cross(v1, v2); n.normalize(); if (n.z < 0.0) n.z = -n.z; normal.add(n); count++; } // Average the four normals normal.x /= count; normal.y /= count; normal.z /= count; } /* For testing - generate a sphere bump map double dx = x-120; double dy = y-80; double r2 = dx*dx+dy*dy; // double r = Math.sqrt( r2 ); // double t = Math.atan2( dy, dx ); if ( r2 < 80*80 ) { double z = Math.sqrt( 80*80 - r2 ); normal.x = (float)dx; normal.y = (float)dy; normal.z = (float)z; normal.normalize(); } else { normal.x = 0; normal.y = 0; normal.z = 1; } */ if (invertBumps) { normal.x = -normal.x; normal.y = -normal.y; } position.x = x; if (normal.z >= 0) { // Get the material colour at this point if (environmentMap != null) { //FIXME-too much normalizing going on here tmpv2.set(viewpoint); tmpv2.sub(position); tmpv2.normalize(); tmpv.set(normal); tmpv.normalize(); // Reflect tmpv.scale( 2.0f*tmpv.dot(tmpv2) ); tmpv.sub(v); tmpv.normalize(); setFromRGB(c, getEnvironmentMapP(normal, inPixels, width, height));//FIXME-interpolate() int alpha = inPixels[index] & 0xff000000; int rgb = ((int)(c.x * 255) << 16) | ((int)(c.y * 255) << 8) | (int)(c.z * 255); outPixels[index++] = alpha | rgb; } else outPixels[index++] = 0; } else outPixels[index++] = 0; } } return outPixels; } private int getEnvironmentMapP(Vector3f normal, int[] inPixels, int width, int height) { if (environmentMap != null) { float x = 0.5f * (1 + normal.x); float y = 0.5f * (1 + normal.y); x = ImageMath.clamp(x * envWidth, 0, envWidth-1); y = ImageMath.clamp(y * envHeight, 0, envHeight-1); int ix = (int)x; int iy = (int)y; float xWeight = x-ix; float yWeight = y-iy; int i = envWidth*iy + ix; int dx = ix == envWidth-1 ? 0 : 1; int dy = iy == envHeight-1 ? 0 : envWidth; return ImageMath.bilinearInterpolate( xWeight, yWeight, envPixels[i], envPixels[i+dx], envPixels[i+dy], envPixels[i+dx+dy] ); } return 0; } public String toString() { return "Stylize/Shade..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/AbstractBufferedImageOp.java0000644000175000017500000000534010521402272024257 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; /** * A convenience class which implements those methods of BufferedImageOp which are rarely changed. */ public abstract class AbstractBufferedImageOp implements BufferedImageOp, Cloneable { public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) { if ( dstCM == null ) dstCM = src.getColorModel(); return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null); } public Rectangle2D getBounds2D( BufferedImage src ) { return new Rectangle(0, 0, src.getWidth(), src.getHeight()); } public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) { if ( dstPt == null ) dstPt = new Point2D.Double(); dstPt.setLocation( srcPt.getX(), srcPt.getY() ); return dstPt; } public RenderingHints getRenderingHints() { return null; } /** * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance * penalty of BufferedImage.getRGB unmanaging the image. */ public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { int type = image.getType(); if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) return (int [])image.getRaster().getDataElements( x, y, width, height, pixels ); return image.getRGB( x, y, width, height, pixels, 0, width ); } /** * A convenience method for setting ARGB pixels in an image. This tries to avoid the performance * penalty of BufferedImage.setRGB unmanaging the image. */ public void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { int type = image.getType(); if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) image.getRaster().setDataElements( x, y, width, height, pixels ); else image.setRGB( x, y, width, height, pixels, 0, width ); } public Object clone() { try { return super.clone(); } catch ( CloneNotSupportedException e ) { return null; } } } jhlabs-filters-2.0.235/com/jhlabs/image/WoodFilter.java0000644000175000017500000000574110521402274021674 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import com.jhlabs.math.*; public class WoodFilter extends PointFilter { private float scale = 200; private float stretch = 10.0f; private float angle = (float)Math.PI/2; public float rings = 0.5f; public float turbulence = 0.0f; public float fibres = 0.5f; public float gain = 0.8f; private float m00 = 1.0f; private float m01 = 0.0f; private float m10 = 0.0f; private float m11 = 1.0f; private Colormap colormap = new LinearColormap( 0xffe5c494, 0xff987b51 ); private Function2D function = new Noise(); public WoodFilter() { } public void setRings(float rings) { this.rings = rings; } public float getRings() { return rings; } public void setFunction(Function2D function) { this.function = function; } public Function2D getFunction() { return function; } public void setScale(float scale) { this.scale = scale; } public float getScale() { return scale; } public void setStretch(float stretch) { this.stretch = stretch; } public float getStretch() { return stretch; } public void setAngle(float angle) { this.angle = angle; float cos = (float)Math.cos(angle); float sin = (float)Math.sin(angle); m00 = cos; m01 = sin; m10 = -sin; m11 = cos; } public float getAngle() { return angle; } public void setTurbulence(float turbulence) { this.turbulence = turbulence; } public float getTurbulence() { return turbulence; } public void setFibres(float fibres) { this.fibres = fibres; } public float getFibres() { return fibres; } public void setgain(float gain) { this.gain = gain; } public float getGain() { return gain; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public int filterRGB(int x, int y, int rgb) { float nx = m00*x + m01*y; float ny = m10*x + m11*y; nx /= scale; ny /= scale * stretch; float f = Noise.noise2(nx, ny); f += 0.1f*turbulence * Noise.noise2(nx*0.05f, ny*20); f = (f * 0.5f) + 0.5f; f *= rings*50; f = f-(int)f; f *= 1-ImageMath.smoothStep(gain, 1.0f, f); f += fibres*Noise.noise2(nx*scale, ny*50); int a = rgb & 0xff000000; int v; if (colormap != null) v = colormap.getColor(f); else { v = PixelUtils.clamp((int)(f*255)); int r = v << 16; int g = v << 8; int b = v; v = a|r|g|b; } return v; } public String toString() { return "Texture/Wood..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/MarbleTexFilter.java0000644000175000017500000000741210521402274022644 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import java.util.*; import com.jhlabs.math.*; public class MarbleTexFilter extends PointFilter implements java.io.Serializable { private float scale = 32; private float stretch = 1.0f; private float angle = 0.0f; private float turbulence = 1; private float turbulenceFactor = 0.5f; private Colormap colormap; private float m00 = 1.0f; private float m01 = 0.0f; private float m10 = 0.0f; private float m11 = 1.0f; public MarbleTexFilter() { } public void setScale(float scale) { this.scale = scale; } public float getScale() { return scale; } public void setStretch(float stretch) { this.stretch = stretch; } public float getStretch() { return stretch; } public void setAngle(float angle) { this.angle = angle; float cos = (float)Math.cos(angle); float sin = (float)Math.sin(angle); m00 = cos; m01 = sin; m10 = -sin; m11 = cos; } public float getAngle() { return angle; } public void setTurbulence(float turbulence) { this.turbulence = turbulence; } public float getTurbulence() { return turbulence; } public void setTurbulenceFactor(float turbulenceFactor) { this.turbulenceFactor = turbulenceFactor; } public float getTurbulenceFactor() { return turbulenceFactor; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public int filterRGB(int x, int y, int rgb) { float nx = m00*x + m01*y; float ny = m10*x + m11*y; nx /= scale * stretch; ny /= scale; int a = rgb & 0xff000000; if (colormap != null) { // float f = Noise.turbulence2(nx, ny, turbulence); // f = 3*turbulenceFactor*f+ny; // f = Math.sin(f*Math.PI); float chaos = turbulenceFactor*Noise.turbulence2(nx, ny, turbulence); // float f = Math.sin(Math.sin(8.*chaos + 7*nx +3.*ny)); float f = 3*turbulenceFactor*chaos+ny; f = (float)Math.sin(f*Math.PI); float perturb = (float)Math.sin(40.*chaos); f += .2 * perturb; return colormap.getColor(f); } else { float red, grn, blu; float chaos, brownLayer, greenLayer; float perturb, brownPerturb, greenPerturb, grnPerturb; float t; chaos = turbulenceFactor*Noise.turbulence2(nx, ny, turbulence); t = (float)Math.sin(Math.sin(8.*chaos + 7*nx +3.*ny)); greenLayer = brownLayer = Math.abs(t); perturb = (float)Math.sin(40.*chaos); perturb = (float)Math.abs(perturb); brownPerturb = .6f*perturb + 0.3f; greenPerturb = .2f*perturb + 0.8f; grnPerturb = .15f*perturb + 0.85f; grn = 0.5f * (float)Math.pow(Math.abs(brownLayer), 0.3); brownLayer = (float)Math.pow(0.5 * (brownLayer+1.0), 0.6) * brownPerturb; greenLayer = (float)Math.pow(0.5 * (greenLayer+1.0), 0.6) * greenPerturb; red = (0.5f*brownLayer + 0.35f*greenLayer)*2.0f*grn; blu = (0.25f*brownLayer + 0.35f*greenLayer)*2.0f*grn; grn *= Math.max(brownLayer, greenLayer) * grnPerturb; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; r = PixelUtils.clamp((int)(r*red)); g = PixelUtils.clamp((int)(g*grn)); b = PixelUtils.clamp((int)(b*blu)); return (rgb & 0xff000000) | (r<<16) | (g<<8) | b; } } public String toString() { return "Texture/Marble Texture..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/MarbleFilter.java0000644000175000017500000000436610521402274022170 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import com.jhlabs.math.*; /** * This filter applies a marbling effect to an image, displacing pixels by random amounts. */ public class MarbleFilter extends TransformFilter { public float[] sinTable, cosTable; public float xScale = 4; public float yScale = 4; public float amount = 1; public float turbulence = 1; public MarbleFilter() { setEdgeAction(CLAMP); } public void setXScale(float xScale) { this.xScale = xScale; } public float getXScale() { return xScale; } public void setYScale(float yScale) { this.yScale = yScale; } public float getYScale() { return yScale; } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public void setTurbulence(float turbulence) { this.turbulence = turbulence; } public float getTurbulence() { return turbulence; } private void initialize() { sinTable = new float[256]; cosTable = new float[256]; for (int i = 0; i < 256; i++) { float angle = ImageMath.TWO_PI*i/256f*turbulence; sinTable[i] = (float)(-yScale*Math.sin(angle)); cosTable[i] = (float)(yScale*Math.cos(angle)); } } private int displacementMap(int x, int y) { return PixelUtils.clamp((int)(127 * (1+Noise.noise2(x / xScale, y / xScale)))); } protected void transformInverse(int x, int y, float[] out) { int displacement = displacementMap(x, y); out[0] = x + sinTable[displacement]; out[1] = y + cosTable[displacement]; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { initialize(); return super.filter( src, dst ); } public String toString() { return "Distort/Marble..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/HalftoneFilter.java0000644000175000017500000000550410521402274022521 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import java.util.*; /** * A filter which can be used to produce wipes by transferring the luma of a mask image into the alpha channel of the source. */ public class HalftoneFilter extends AbstractBufferedImageOp { private float density = 0; private float softness = 0; private boolean invert; private BufferedImage mask; public HalftoneFilter() { } /** * Set the density of the image in the range 0..1. * *arg density The density */ public void setDensity( float density ) { this.density = density; } public float getDensity() { return density; } public void setSoftness( float softness ) { this.softness = softness; } public float getSoftness() { return softness; } public void setMask( BufferedImage mask ) { this.mask = mask; } public BufferedImage getMask() { return mask; } public void setInvert( boolean invert ) { this.invert = invert; } public boolean getInvert() { return invert; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); if ( mask == null ) return dst; int maskWidth = mask.getWidth(); int maskHeight = mask.getHeight(); float d = density * (1+softness); float lower = 255 * (d-softness); float upper = 255 * d; float s = 255*softness; int[] inPixels = new int[width]; int[] maskPixels = new int[maskWidth]; for ( int y = 0; y < height; y++ ) { getRGB( src, 0, y, width, 1, inPixels ); getRGB( mask, 0, y % maskHeight, maskWidth, 1, maskPixels ); for ( int x = 0; x < width; x++ ) { int maskRGB = maskPixels[x % maskWidth]; int inRGB = inPixels[x]; int v = PixelUtils.brightness( maskRGB ); int iv = PixelUtils.brightness( inRGB ); float f = ImageMath.smoothStep( iv-s, iv+s, v ); int a = (int)(255 * f); if ( invert ) a = 255-a; // inPixels[x] = (a << 24) | (inRGB & 0x00ffffff); inPixels[x] = (inRGB & 0xff000000) | (a << 16) | (a << 8) | a; } setRGB( dst, 0, y, width, 1, inPixels ); } return dst; } public String toString() { return "Stylize/Halftone..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ImageUtils.java0000644000175000017500000001651310521402274021660 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.util.*; import com.jhlabs.image.*; public abstract class ImageUtils { public final static int SELECTED = 0xff000000; public final static int UNSELECTED = 0x00000000; public static BufferedImage backgroundImage = null; public static BufferedImage createImage(ImageProducer producer) { PixelGrabber pg = new PixelGrabber(producer, 0, 0, -1, -1, null, 0, 0); try { pg.grabPixels(); } catch (InterruptedException e) { throw new RuntimeException("Image fetch interrupted"); } if ((pg.status() & ImageObserver.ABORT) != 0) throw new RuntimeException("Image fetch aborted"); if ((pg.status() & ImageObserver.ERROR) != 0) throw new RuntimeException("Image fetch error"); BufferedImage p = new BufferedImage(pg.getWidth(), pg.getHeight(), BufferedImage.TYPE_INT_ARGB); p.setRGB(0, 0, pg.getWidth(), pg.getHeight(), (int[])pg.getPixels(), 0, pg.getWidth()); return p; } /** * Convert an Image into a TYPE_INT_ARGB BufferedImage. If the image is already of this type, the original image is returned unchanged. */ public static BufferedImage convertImageToARGB( Image image ) { if ( image instanceof BufferedImage && ((BufferedImage)image).getType() == BufferedImage.TYPE_INT_ARGB ) return (BufferedImage)image; BufferedImage p = new BufferedImage( image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); Graphics2D g = p.createGraphics(); g.drawImage( image, 0, 0, null ); g.dispose(); return p; } // Returns a *copy* of a subimage of image. This avoids the performance problems associated with BufferedImage.getSubimage. public static BufferedImage getSubimage( BufferedImage image, int x, int y, int w, int h ) { BufferedImage newImage = new BufferedImage( w, h, BufferedImage.TYPE_INT_ARGB ); Graphics2D g = newImage.createGraphics(); g.drawRenderedImage( image, AffineTransform.getTranslateInstance(-x, -y) ); g.dispose(); return newImage; } public static BufferedImage cloneImage( BufferedImage image ) { BufferedImage newImage = new BufferedImage( image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB ); Graphics2D g = newImage.createGraphics(); g.drawRenderedImage( image, null ); g.dispose(); return newImage; } public static void paintCheckedBackground(Component c, Graphics g, int x, int y, int width, int height) { if ( backgroundImage == null ) { backgroundImage = new BufferedImage( 64, 64, BufferedImage.TYPE_INT_ARGB ); Graphics bg = backgroundImage.createGraphics(); for ( int by = 0; by < 64; by += 8 ) { for ( int bx = 0; bx < 64; bx += 8 ) { bg.setColor( ((bx^by) & 8) != 0 ? Color.lightGray : Color.white ); bg.fillRect( bx, by, 8, 8 ); } } bg.dispose(); } if ( backgroundImage != null ) { Shape saveClip = g.getClip(); Rectangle r = g.getClipBounds(); if (r == null) r = new Rectangle(c.getSize()); r = r.intersection(new Rectangle(x, y, width, height)); g.setClip(r); int w = backgroundImage.getWidth(); int h = backgroundImage.getHeight(); if (w != -1 && h != -1) { int x1 = (r.x / w) * w; int y1 = (r.y / h) * h; int x2 = ((r.x + r.width + w - 1) / w) * w; int y2 = ((r.y + r.height + h - 1) / h) * h; for (y = y1; y < y2; y += h) for (x = x1; x < x2; x += w) g.drawImage(backgroundImage, x, y, c); } g.setClip(saveClip); } } public static Rectangle getSelectedBounds(BufferedImage p) { int width = p.getWidth(); int height = p.getHeight(); int maxX = 0, maxY = 0, minX = width, minY = height; boolean anySelected = false; int y1; int [] pixels = null; for (y1 = height-1; y1 >= 0; y1--) { pixels = getRGB( p, 0, y1, width, 1, pixels ); for (int x = 0; x < minX; x++) { if ((pixels[x] & 0xff000000) != 0) { minX = x; maxY = y1; anySelected = true; break; } } for (int x = width-1; x >= maxX; x--) { if ((pixels[x] & 0xff000000) != 0) { maxX = x; maxY = y1; anySelected = true; break; } } if ( anySelected ) break; } pixels = null; for (int y = 0; y < y1; y++) { pixels = getRGB( p, 0, y, width, 1, pixels ); for (int x = 0; x < minX; x++) { if ((pixels[x] & 0xff000000) != 0) { minX = x; if ( y < minY ) minY = y; anySelected = true; break; } } for (int x = width-1; x >= maxX; x--) { if ((pixels[x] & 0xff000000) != 0) { maxX = x; if ( y < minY ) minY = y; anySelected = true; break; } } } if ( anySelected ) return new Rectangle( minX, minY, maxX-minX+1, maxY-minY+1 ); return null; } /** * Compose src onto dst using the alpha of sel to interpolate between the two. * I can't think of a way to do this using AlphaComposite. */ public static void composeThroughMask(Raster src, WritableRaster dst, Raster sel) { int x = src.getMinX(); int y = src.getMinY(); int w = src.getWidth(); int h = src.getHeight(); int srcRGB[] = null; int selRGB[] = null; int dstRGB[] = null; for ( int i = 0; i < h; i++ ) { srcRGB = src.getPixels(x, y, w, 1, srcRGB); selRGB = sel.getPixels(x, y, w, 1, selRGB); dstRGB = dst.getPixels(x, y, w, 1, dstRGB); int k = x; for ( int j = 0; j < w; j++ ) { int sr = srcRGB[k]; int dir = dstRGB[k]; int sg = srcRGB[k+1]; int dig = dstRGB[k+1]; int sb = srcRGB[k+2]; int dib = dstRGB[k+2]; int sa = srcRGB[k+3]; int dia = dstRGB[k+3]; float a = selRGB[k+3]/255f; float ac = 1-a; dstRGB[k] = (int)(a*sr + ac*dir); dstRGB[k+1] = (int)(a*sg + ac*dig); dstRGB[k+2] = (int)(a*sb + ac*dib); dstRGB[k+3] = (int)(a*sa + ac*dia); k += 4; } dst.setPixels(x, y, w, 1, dstRGB); y++; } } /** * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance * penalty of BufferedImage.getRGB unmanaging the image. */ public static int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { int type = image.getType(); if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) return (int [])image.getRaster().getDataElements( x, y, width, height, pixels ); return image.getRGB( x, y, width, height, pixels, 0, width ); } /** * A convenience method for setting ARGB pixels in an image. This tries to avoid the performance * penalty of BufferedImage.setRGB unmanaging the image. */ public static void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { int type = image.getType(); if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) image.getRaster().setDataElements( x, y, width, height, pixels ); else image.setRGB( x, y, width, height, pixels, 0, width ); } } jhlabs-filters-2.0.235/com/jhlabs/image/GrayscaleFilter.java0000644000175000017500000000226610521402274022675 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /* * A filter which converts an image to grayscale using the NTSC calculation. */ public class GrayscaleFilter extends PointFilter { public GrayscaleFilter() { canFilterIndexColorModel = true; } public int filterRGB(int x, int y, int rgb) { int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; // rgb = (r + g + b) / 3; // simple average rgb = (r * 77 + g * 151 + b * 28) >> 8; // NTSC luma return a | (rgb << 16) | (rgb << 8) | rgb; } public String toString() { return "Colors/Grayscale"; } } jhlabs-filters-2.0.235/com/jhlabs/image/TransferFilter.java0000644000175000017500000000343010521402274022541 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public abstract class TransferFilter extends PointFilter { protected int[] rTable, gTable, bTable; protected boolean initialized = false; public TransferFilter() { canFilterIndexColorModel = true; } public int filterRGB(int x, int y, int rgb) { int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; r = rTable[r]; g = gTable[g]; b = bTable[b]; return a | (r << 16) | (g << 8) | b; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { if (!initialized) initialize(); return super.filter( src, dst ); } protected void initialize() { initialized = true; rTable = gTable = bTable = makeTable(); } protected int[] makeTable() { int[] table = new int[256]; for (int i = 0; i < 256; i++) table[i] = PixelUtils.clamp( (int)( 255 * transferFunction( i / 255.0f ) ) ); return table; } protected float transferFunction( float v ) { return 0; } public int[] getLUT() { if (!initialized) initialize(); int[] lut = new int[256]; for ( int i = 0; i < 256; i++ ) { lut[i] = filterRGB( 0, 0, (i << 24) | (i << 16) | (i << 8) | i ); } return lut; } } jhlabs-filters-2.0.235/com/jhlabs/image/WarpGrid.java0000644000175000017500000002132710521402274021333 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A warp grid. * From "A simplified approach to Image Processing" by Randy Crane */ public class WarpGrid implements java.io.Serializable { static final long serialVersionUID = 4312410199770201968L; public float[] xGrid = null; public float[] yGrid = null; public int rows, cols; public WarpGrid(int rows, int cols, int w, int h) { this.rows = rows; this.cols = cols; xGrid = new float[rows*cols]; yGrid = new float[rows*cols]; int index = 0; for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { xGrid[index] = (float)col*(w-1)/(cols-1); yGrid[index] = (float)row*(h-1)/(rows-1); index++; } } } /** * Add a new row to the grid. "before" must be in the range 1..rows-1. i.e. you can only add rows inside the grid. */ public void addRow( int before ) { int size = (rows+1) * cols; float[] x = new float[size]; float[] y = new float[size]; rows++; int i = 0; int j = 0; for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { int k = j+col; int l = i+col; if ( row == before ) { x[k] = (xGrid[l]+xGrid[k])/2; y[k] = (yGrid[l]+yGrid[k])/2; } else { x[k] = xGrid[l]; y[k] = yGrid[l]; } } if ( row != before-1 ) i += cols; j += cols; } xGrid = x; yGrid = y; } /** * Add a new column to the grid. "before" must be in the range 1..cols-1. i.e. you can only add columns inside the grid. */ public void addCol( int before ) { int size = rows * (cols+1); float[] x = new float[size]; float[] y = new float[size]; cols++; int i = 0; int j = 0; for (int row = 0; row < rows; row++) { // int i = row*(cols-1); // int j = row*cols; for (int col = 0; col < cols; col++) { if ( col == before ) { x[j] = (xGrid[i]+xGrid[i-1])/2; y[j] = (yGrid[i]+yGrid[i-1])/2; } else { x[j] = xGrid[i]; y[j] = yGrid[i]; i++; } j++; } } xGrid = x; yGrid = y; } /** * Remove a row from the grid. */ public void removeRow( int r ) { int size = (rows-1) * cols; float[] x = new float[size]; float[] y = new float[size]; rows--; int i = 0; int j = 0; for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { int k = j+col; int l = i+col; x[k] = xGrid[l]; y[k] = yGrid[l]; } if ( row == r-1 ) i += cols; i += cols; j += cols; } xGrid = x; yGrid = y; } /** * Remove a column from the grid. */ public void removeCol( int r ) { int size = rows * (cols+1); float[] x = new float[size]; float[] y = new float[size]; cols--; for (int row = 0; row < rows; row++) { int i = row*(cols+1); int j = row*cols; for (int col = 0; col < cols; col++) { x[j] = xGrid[i]; y[j] = yGrid[i]; if ( col == r-1 ) i++; i++; j++; } } xGrid = x; yGrid = y; } public void lerp(float t, WarpGrid destination, WarpGrid intermediate) { if (rows != destination.rows || cols != destination.cols) throw new IllegalArgumentException("source and destination are different sizes"); if (rows != intermediate.rows || cols != intermediate.cols) throw new IllegalArgumentException("source and intermediate are different sizes"); int index = 0; for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { intermediate.xGrid[index] = (float)ImageMath.lerp(t, xGrid[index], destination.xGrid[index]); intermediate.yGrid[index] = (float)ImageMath.lerp(t, yGrid[index], destination.yGrid[index]); index++; } } } public void warp(int[] inPixels, int cols, int rows, WarpGrid sourceGrid, WarpGrid destGrid, int[] outPixels) { try { int x, y; int u, v; int[] intermediate; WarpGrid splines; if (sourceGrid.rows != destGrid.rows || sourceGrid.cols != destGrid.cols) throw new IllegalArgumentException("source and destination grids are different sizes"); int size = Math.max(cols, rows); float[] xrow = new float[size]; float[] yrow = new float[size]; float[] scale = new float[size + 1]; float[] interpolated = new float[size + 1]; int gridCols = sourceGrid.cols; int gridRows = sourceGrid.rows; splines = new WarpGrid(rows, gridCols, 1, 1); for (u = 0; u < gridCols;u++) { int i = u; for (v = 0; v < gridRows;v++) { xrow[v] = sourceGrid.xGrid[i]; yrow[v] = sourceGrid.yGrid[i]; i += gridCols; } interpolateSpline(yrow, xrow, 0, gridRows, interpolated, 0, rows); i = u; for (y = 0;y < rows;y++) { splines.xGrid[i] = interpolated[y]; i += gridCols; } } for (u = 0; u < gridCols;u++) { int i = u; for (v = 0; v < gridRows;v++) { xrow[v] = destGrid.xGrid[i]; yrow[v] = destGrid.yGrid[i]; i += gridCols; } interpolateSpline(yrow, xrow, 0, gridRows, interpolated, 0, rows); i = u; for (y = 0;y < rows; y++) { splines.yGrid[i] = interpolated[y]; i += gridCols; } } /* first pass: warp x using splines */ intermediate = new int[rows*cols]; int offset = 0; for (y = 0; y < rows; y++) { /* fit spline to x-intercepts;resample over all cols */ interpolateSpline(splines.xGrid, splines.yGrid, offset, gridCols, scale, 0, cols); scale[cols] = cols; ImageMath.resample(inPixels, intermediate, cols, y*cols, 1, scale); offset += gridCols; } /* create table of y-intercepts for intermediate mesh's hor splines */ splines = new WarpGrid(gridRows, cols, 1, 1); offset = 0; int offset2 = 0; for (v = 0; v < gridRows; v++) { interpolateSpline(sourceGrid.xGrid, sourceGrid.yGrid, offset, gridCols, splines.xGrid, offset2, cols); offset += gridCols; offset2 += cols; } offset = 0; offset2 = 0; for (v = 0; v < gridRows; v++) { interpolateSpline(destGrid.xGrid, destGrid.yGrid, offset, gridCols, splines.yGrid, offset2, cols); offset += gridCols; offset2 += cols; } /* second pass: warp y */ for (x = 0; x < cols; x++) { int i = x; for (v = 0; v < gridRows; v++) { xrow[v] = splines.xGrid[i];; yrow[v] = splines.yGrid[i];; i += cols; } interpolateSpline(xrow, yrow, 0, gridRows, scale, 0, rows); scale[rows] = rows; ImageMath.resample(intermediate, outPixels, rows, x, cols, scale); } } catch (Exception e) { e.printStackTrace(); } } private final static float m00 = -0.5f; private final static float m01 = 1.5f; private final static float m02 = -1.5f; private final static float m03 = 0.5f; private final static float m10 = 1.0f; private final static float m11 = -2.5f; private final static float m12 = 2.0f; private final static float m13 = -0.5f; private final static float m20 = -0.5f; private final static float m22 = 0.5f; private final static float m31 = 1.0f; protected void interpolateSpline(float[] xKnots, float[] yKnots, int offset, int length, float[] splineY, int splineOffset, int splineLength) { int index = offset; int end = offset+length-1; float x0, x1; float k0, k1, k2, k3; float c0, c1, c2, c3; x0 = xKnots[index]; k0 = k1 = k2 = yKnots[index]; x1 = xKnots[index+1]; k3 = yKnots[index+1]; for (int i = 0;i < splineLength;i++) { if (index <= end && i > xKnots[index]) { k0 = k1; k1 = k2; k2 = k3; x0 = xKnots[index]; index++; if ( index <= end ) x1 = xKnots[index]; if ( index < end ) k3 = yKnots[index+1]; else k3 = k2; } float t = (i - x0) / (x1 - x0); c3 = m00*k0 + m01*k1 + m02*k2 + m03*k3; c2 = m10*k0 + m11*k1 + m12*k2 + m13*k3; c1 = m20*k0 + m22*k2; c0 = m31*k1; splineY[splineOffset+i] = ((c3*t + c2)*t + c1)*t + c0; } } protected void interpolateSpline2(float[] xKnots, float[] yKnots, int offset, float[] splineY, int splineOffset, int splineLength) { int index = offset; float leftX, rightX; float leftY, rightY; leftX = xKnots[index]; leftY = yKnots[index]; rightX = xKnots[index+1]; rightY = yKnots[index+1]; for (int i = 0;i < splineLength;i++) { if (i > xKnots[index]) { leftX = xKnots[index]; leftY = yKnots[index]; index++; rightX = xKnots[index]; rightY = yKnots[index]; } float f = (i - leftX) / (rightX - leftX); splineY[splineOffset+i] = leftY + f * (rightY - leftY); } } } jhlabs-filters-2.0.235/com/jhlabs/image/PointillizeFilter.java0000644000175000017500000000467410521402274023272 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.util.*; import com.jhlabs.math.*; public class PointillizeFilter extends CellularFilter { private float edgeThickness = 0.4f; private boolean fadeEdges = false; private int edgeColor = 0xff000000; private float fuzziness = 0.1f; public PointillizeFilter() { setScale(16); setRandomness(0.0f); } public void setEdgeThickness(float edgeThickness) { this.edgeThickness = edgeThickness; } public float getEdgeThickness() { return edgeThickness; } public void setFadeEdges(boolean fadeEdges) { this.fadeEdges = fadeEdges; } public boolean getFadeEdges() { return fadeEdges; } public void setEdgeColor(int edgeColor) { this.edgeColor = edgeColor; } public int getEdgeColor() { return edgeColor; } public void setFuzziness(float fuzziness) { this.fuzziness = fuzziness; } public float getFuzziness() { return fuzziness; } public int getPixel(int x, int y, int[] inPixels, int width, int height) { float nx = m00*x + m01*y; float ny = m10*x + m11*y; nx /= scale; ny /= scale * stretch; nx += 1000; ny += 1000; // Reduce artifacts around 0,0 float f = evaluate(nx, ny); float f1 = results[0].distance; int srcx = ImageMath.clamp((int)((results[0].x-1000)*scale), 0, width-1); int srcy = ImageMath.clamp((int)((results[0].y-1000)*scale), 0, height-1); int v = inPixels[srcy * width + srcx]; if (fadeEdges) { float f2 = results[1].distance; srcx = ImageMath.clamp((int)((results[1].x-1000)*scale), 0, width-1); srcy = ImageMath.clamp((int)((results[1].y-1000)*scale), 0, height-1); int v2 = inPixels[srcy * width + srcx]; v = ImageMath.mixColors(0.5f*f1/f2, v, v2); } else { f = 1-ImageMath.smoothStep(edgeThickness, edgeThickness+fuzziness, f1); v = ImageMath.mixColors(f, edgeColor, v); } return v; } public String toString() { return "Stylize/Pointillize..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/PixelUtils.java0000644000175000017500000001334110521402274021713 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.util.*; import java.awt.Color; /** * Some more useful math functions for image processing. * These are becoming obsolete as we move to Java2D. Use MiscComposite instead. */ public class PixelUtils { public final static int REPLACE = 0; public final static int NORMAL = 1; public final static int MIN = 2; public final static int MAX = 3; public final static int ADD = 4; public final static int SUBTRACT = 5; public final static int DIFFERENCE = 6; public final static int MULTIPLY = 7; public final static int HUE = 8; public final static int SATURATION = 9; public final static int VALUE = 10; public final static int COLOR = 11; public final static int SCREEN = 12; public final static int AVERAGE = 13; public final static int OVERLAY = 14; public final static int CLEAR = 15; public final static int EXCHANGE = 16; public final static int DISSOLVE = 17; public final static int DST_IN = 18; public final static int ALPHA = 19; public final static int ALPHA_TO_GRAY = 20; private static Random randomGenerator = new Random(); /** * Clamp a value to the range 0..255 */ public static int clamp(int c) { if (c < 0) return 0; if (c > 255) return 255; return c; } public static int interpolate(int v1, int v2, float f) { return clamp((int)(v1+f*(v2-v1))); } public static int brightness(int rgb) { int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; return (r+g+b)/3; } public static boolean nearColors(int rgb1, int rgb2, int tolerance) { int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; return Math.abs(r1-r2) <= tolerance && Math.abs(g1-g2) <= tolerance && Math.abs(b1-b2) <= tolerance; } private final static float hsb1[] = new float[3];//FIXME-not thread safe private final static float hsb2[] = new float[3];//FIXME-not thread safe // Return rgb1 painted onto rgb2 public static int combinePixels(int rgb1, int rgb2, int op) { return combinePixels(rgb1, rgb2, op, 0xff); } public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha, int channelMask) { return (rgb2 & ~channelMask) | combinePixels(rgb1 & channelMask, rgb2, op, extraAlpha); } public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha) { if (op == REPLACE) return rgb1; int a1 = (rgb1 >> 24) & 0xff; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; int a2 = (rgb2 >> 24) & 0xff; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; switch (op) { case NORMAL: break; case MIN: r1 = Math.min(r1, r2); g1 = Math.min(g1, g2); b1 = Math.min(b1, b2); break; case MAX: r1 = Math.max(r1, r2); g1 = Math.max(g1, g2); b1 = Math.max(b1, b2); break; case ADD: r1 = clamp(r1+r2); g1 = clamp(g1+g2); b1 = clamp(b1+b2); break; case SUBTRACT: r1 = clamp(r2-r1); g1 = clamp(g2-g1); b1 = clamp(b2-b1); break; case DIFFERENCE: r1 = clamp(Math.abs(r1-r2)); g1 = clamp(Math.abs(g1-g2)); b1 = clamp(Math.abs(b1-b2)); break; case MULTIPLY: r1 = clamp(r1*r2/255); g1 = clamp(g1*g2/255); b1 = clamp(b1*b2/255); break; case DISSOLVE: if ((randomGenerator.nextInt() & 0xff) <= a1) { r1 = r2; g1 = g2; b1 = b2; } break; case AVERAGE: r1 = (r1+r2)/2; g1 = (g1+g2)/2; b1 = (b1+b2)/2; break; case HUE: case SATURATION: case VALUE: case COLOR: Color.RGBtoHSB(r1, g1, b1, hsb1); Color.RGBtoHSB(r2, g2, b2, hsb2); switch (op) { case HUE: hsb2[0] = hsb1[0]; break; case SATURATION: hsb2[1] = hsb1[1]; break; case VALUE: hsb2[2] = hsb1[2]; break; case COLOR: hsb2[0] = hsb1[0]; hsb2[1] = hsb1[1]; break; } rgb1 = Color.HSBtoRGB(hsb2[0], hsb2[1], hsb2[2]); r1 = (rgb1 >> 16) & 0xff; g1 = (rgb1 >> 8) & 0xff; b1 = rgb1 & 0xff; break; case SCREEN: r1 = 255 - ((255 - r1) * (255 - r2)) / 255; g1 = 255 - ((255 - g1) * (255 - g2)) / 255; b1 = 255 - ((255 - b1) * (255 - b2)) / 255; break; case OVERLAY: int m, s; s = 255 - ((255 - r1) * (255 - r2)) / 255; m = r1 * r2 / 255; r1 = (s * r1 + m * (255 - r1)) / 255; s = 255 - ((255 - g1) * (255 - g2)) / 255; m = g1 * g2 / 255; g1 = (s * g1 + m * (255 - g1)) / 255; s = 255 - ((255 - b1) * (255 - b2)) / 255; m = b1 * b2 / 255; b1 = (s * b1 + m * (255 - b1)) / 255; break; case CLEAR: r1 = g1 = b1 = 0xff; break; case DST_IN: r1 = clamp((r2*a1)/255); g1 = clamp((g2*a1)/255); b1 = clamp((b2*a1)/255); a1 = clamp((a2*a1)/255); return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; case ALPHA: a1 = a1*a2/255; return (a1 << 24) | (r2 << 16) | (g2 << 8) | b2; case ALPHA_TO_GRAY: int na = 255-a1; return (a1 << 24) | (na << 16) | (na << 8) | na; } if (extraAlpha != 0xff || a1 != 0xff) { a1 = a1*extraAlpha/255; int a3 = (255-a1)*a2/255; r1 = clamp((r1*a1+r2*a3)/255); g1 = clamp((g1*a1+g2*a3)/255); b1 = clamp((b1*a1+b2*a3)/255); a1 = clamp(a1+a3); } return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; } } jhlabs-filters-2.0.235/com/jhlabs/image/BumpFilter.java0000644000175000017500000000174210521402272021662 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A simple embossing filter. */ public class BumpFilter extends ConvolveFilter { static final long serialVersionUID = 2528502820741699111L; protected static float[] embossMatrix = { -1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; public BumpFilter() { super(embossMatrix); } public String toString() { return "Blur/Emboss Edges"; } } jhlabs-filters-2.0.235/com/jhlabs/image/ChannelMixFilter.java0000644000175000017500000000420610521402272023003 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter which allows the red, grren and blue channels of an image to be mixed into each other. */ public class ChannelMixFilter extends PointFilter { public int blueGreen, redBlue, greenRed; public int intoR, intoG, intoB; public ChannelMixFilter() { canFilterIndexColorModel = true; } public void setBlueGreen(int blueGreen) { this.blueGreen = blueGreen; } public int getBlueGreen() { return blueGreen; } public void setRedBlue(int redBlue) { this.redBlue = redBlue; } public int getRedBlue() { return redBlue; } public void setGreenRed(int greenRed) { this.greenRed = greenRed; } public int getGreenRed() { return greenRed; } public void setIntoR(int intoR) { this.intoR = intoR; } public int getIntoR() { return intoR; } public void setIntoG(int intoG) { this.intoG = intoG; } public int getIntoG() { return intoG; } public void setIntoB(int intoB) { this.intoB = intoB; } public int getIntoB() { return intoB; } public int filterRGB(int x, int y, int rgb) { int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; int nr = PixelUtils.clamp((intoR * (blueGreen*g+(255-blueGreen)*b)/255 + (255-intoR)*r)/255); int ng = PixelUtils.clamp((intoG * (redBlue*b+(255-redBlue)*r)/255 + (255-intoG)*g)/255); int nb = PixelUtils.clamp((intoB * (greenRed*r+(255-greenRed)*g)/255 + (255-intoB)*b)/255); return a | (nr << 16) | (ng << 8) | nb; } public String toString() { return "Colors/Mix Channels..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/WholeImageFilter.java0000644000175000017500000000405010521402274022775 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter which acts as a superclass for filters which need to have the whole image in memory * to do their stuff. */ public abstract class WholeImageFilter extends AbstractBufferedImageOp implements java.io.Serializable { protected Rectangle transformedSpace; protected Rectangle originalSpace; /** * Construct a WholeImageFilter */ public WholeImageFilter() { } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int type = src.getType(); WritableRaster srcRaster = src.getRaster(); originalSpace = new Rectangle(0, 0, width, height); transformedSpace = new Rectangle(0, 0, width, height); transformSpace(transformedSpace); if ( dst == null ) { ColorModel dstCM = src.getColorModel(); dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(transformedSpace.width, transformedSpace.height), dstCM.isAlphaPremultiplied(), null); } WritableRaster dstRaster = dst.getRaster(); int[] inPixels = getRGB( src, 0, 0, width, height, null ); inPixels = filterPixels( width, height, inPixels, transformedSpace ); setRGB( dst, 0, 0, transformedSpace.width, transformedSpace.height, inPixels ); return dst; } protected void transformSpace(Rectangle rect) { } protected abstract int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ); } jhlabs-filters-2.0.235/com/jhlabs/image/Colormap.java0000644000175000017500000000170610521402272021365 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; /** * An interface for color maps. These are passed to filters which convert gray values to * colors. This is similar to the ColorModel class but works with floating point values. */ public interface Colormap { /** * Convert a value in the range 0..1 to an RGB color. * @param v a value in the range 0..1 * @return an RGB color */ public int getColor(float v); } jhlabs-filters-2.0.235/com/jhlabs/image/CellularFilter.java0000644000175000017500000003304110521402272022517 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.util.*; import com.jhlabs.math.*; public class CellularFilter extends WholeImageFilter implements Function2D, MutatableFilter, Cloneable, java.io.Serializable { protected float scale = 32; protected float stretch = 1.0f; protected float angle = 0.0f; public float amount = 1.0f; public float turbulence = 1.0f; public float gain = 0.5f; public float bias = 0.5f; public float distancePower = 2; public boolean useColor = false; protected Colormap colormap = new Gradient(); protected float[] coefficients = { 1, 0, 0, 0 }; protected float angleCoefficient; protected Random random = new Random(); protected float m00 = 1.0f; protected float m01 = 0.0f; protected float m10 = 0.0f; protected float m11 = 1.0f; protected Point[] results = null; protected float randomness = 0; protected int gridType = HEXAGONAL; private float min; private float max; private static byte[] probabilities; private float gradientCoefficient; public final static int RANDOM = 0; public final static int SQUARE = 1; public final static int HEXAGONAL = 2; public final static int OCTAGONAL = 3; public final static int TRIANGULAR = 4; public CellularFilter() { results = new Point[3]; for (int j = 0; j < results.length; j++) results[j] = new Point(); if (probabilities == null) { probabilities = new byte[8192]; float factorial = 1; float total = 0; float mean = 2.5f; for (int i = 0; i < 10; i++) { if (i > 1) factorial *= i; float probability = (float)Math.pow(mean, i) * (float)Math.exp(-mean) / factorial; int start = (int)(total * 8192); total += probability; int end = (int)(total * 8192); for (int j = start; j < end; j++) probabilities[j] = (byte)i; } } } public void setScale(float scale) { this.scale = scale; } public float getScale() { return scale; } public void setStretch(float stretch) { this.stretch = stretch; } public float getStretch() { return stretch; } public void setAngle(float angle) { this.angle = angle; float cos = (float)Math.cos(angle); float sin = (float)Math.sin(angle); m00 = cos; m01 = sin; m10 = -sin; m11 = cos; } public float getAngle() { return angle; } public void setCoefficient(int i, float v) { coefficients[i] = v; } public float getCoefficient(int i) { return coefficients[i]; } public void setAngleCoefficient(float angleCoefficient) { this.angleCoefficient = angleCoefficient; } public float getAngleCoefficient() { return angleCoefficient; } public void setGradientCoefficient(float gradientCoefficient) { this.gradientCoefficient = gradientCoefficient; } public float getGradientCoefficient() { return gradientCoefficient; } public void setF1( float v ) { coefficients[0] = v; } public float getF1() { return coefficients[0]; } public void setF2( float v ) { coefficients[1] = v; } public float getF2() { return coefficients[1]; } public void setF3( float v ) { coefficients[2] = v; } public float getF3() { return coefficients[2]; } public void setF4( float v ) { coefficients[3] = v; } public float getF4() { return coefficients[3]; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public void setRandomness(float randomness) { this.randomness = randomness; } public float getRandomness() { return randomness; } public void setGridType(int gridType) { this.gridType = gridType; } public int getGridType() { return gridType; } public void setDistancePower(float distancePower) { this.distancePower = distancePower; } public float getDistancePower() { return distancePower; } public void setTurbulence(float turbulence) { this.turbulence = turbulence; } public float getTurbulence() { return turbulence; } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public class Point { public int index; public float x, y; public float dx, dy; public float cubeX, cubeY; public float distance; } /* class Grid { public int setup(int x, int y); public int getNumPoints(); public int getX(); public int getY(); } class RandomGrid extends Grid { public int setup(int x, int y) { random.setSeed(571*cubeX + 23*cubeY); } public int getNumPoints() { return 3 + random.nextInt() % 4; } public int getX() { return random.nextfloat(); } public int getY() { return random.nextfloat(); } } */ private float checkCube(float x, float y, int cubeX, int cubeY, Point[] results) { int numPoints; random.setSeed(571*cubeX + 23*cubeY); switch (gridType) { case RANDOM: default: // numPoints = 3 + random.nextInt() % 4; numPoints = probabilities[random.nextInt() & 0x1fff]; // numPoints = 4; break; case SQUARE: numPoints = 1; break; case HEXAGONAL: numPoints = 1; break; case OCTAGONAL: numPoints = 2; break; case TRIANGULAR: numPoints = 2; break; } for (int i = 0; i < numPoints; i++) { float px = 0, py = 0; float weight = 1.0f; switch (gridType) { case RANDOM: px = random.nextFloat(); py = random.nextFloat(); break; case SQUARE: px = py = 0.5f; if (randomness != 0) { px += randomness * (random.nextFloat()-0.5); py += randomness * (random.nextFloat()-0.5); } break; case HEXAGONAL: if ((cubeX & 1) == 0) { px = 0.75f; py = 0; } else { px = 0.75f; py = 0.5f; } if (randomness != 0) { px += randomness * Noise.noise2(271*(cubeX+px), 271*(cubeY+py)); py += randomness * Noise.noise2(271*(cubeX+px)+89, 271*(cubeY+py)+137); } break; case OCTAGONAL: switch (i) { case 0: px = 0.207f; py = 0.207f; break; case 1: px = 0.707f; py = 0.707f; weight = 1.6f; break; } if (randomness != 0) { px += randomness * Noise.noise2(271*(cubeX+px), 271*(cubeY+py)); py += randomness * Noise.noise2(271*(cubeX+px)+89, 271*(cubeY+py)+137); } break; case TRIANGULAR: if ((cubeY & 1) == 0) { if (i == 0) { px = 0.25f; py = 0.35f; } else { px = 0.75f; py = 0.65f; } } else { if (i == 0) { px = 0.75f; py = 0.35f; } else { px = 0.25f; py = 0.65f; } } if (randomness != 0) { px += randomness * Noise.noise2(271*(cubeX+px), 271*(cubeY+py)); py += randomness * Noise.noise2(271*(cubeX+px)+89, 271*(cubeY+py)+137); } break; } float dx = (float)Math.abs(x-px); float dy = (float)Math.abs(y-py); float d; dx *= weight; dy *= weight; if (distancePower == 1.0f) d = dx + dy; else if (distancePower == 2.0f) d = (float)Math.sqrt(dx*dx + dy*dy); else d = (float)Math.pow((float)Math.pow(dx, distancePower) + (float)Math.pow(dy, distancePower), 1/distancePower); // Insertion sort the long way round to speed it up a bit if (d < results[0].distance) { Point p = results[2]; results[2] = results[1]; results[1] = results[0]; results[0] = p; p.distance = d; p.dx = dx; p.dy = dy; p.x = cubeX+px; p.y = cubeY+py; } else if (d < results[1].distance) { Point p = results[2]; results[2] = results[1]; results[1] = p; p.distance = d; p.dx = dx; p.dy = dy; p.x = cubeX+px; p.y = cubeY+py; } else if (d < results[2].distance) { Point p = results[2]; p.distance = d; p.dx = dx; p.dy = dy; p.x = cubeX+px; p.y = cubeY+py; } } return results[2].distance; } public float evaluate(float x, float y) { for (int j = 0; j < results.length; j++) results[j].distance = Float.POSITIVE_INFINITY; int ix = (int)x; int iy = (int)y; float fx = x-ix; float fy = y-iy; float d = checkCube(fx, fy, ix, iy, results); if (d > fy) d = checkCube(fx, fy+1, ix, iy-1, results); if (d > 1-fy) d = checkCube(fx, fy-1, ix, iy+1, results); if (d > fx) { checkCube(fx+1, fy, ix-1, iy, results); if (d > fy) d = checkCube(fx+1, fy+1, ix-1, iy-1, results); if (d > 1-fy) d = checkCube(fx+1, fy-1, ix-1, iy+1, results); } if (d > 1-fx) { d = checkCube(fx-1, fy, ix+1, iy, results); if (d > fy) d = checkCube(fx-1, fy+1, ix+1, iy-1, results); if (d > 1-fy) d = checkCube(fx-1, fy-1, ix+1, iy+1, results); } float t = 0; for (int i = 0; i < 3; i++) t += coefficients[i] * results[i].distance; if (angleCoefficient != 0) { float angle = (float)Math.atan2(y-results[0].y, x-results[0].x); if (angle < 0) angle += 2*(float)Math.PI; angle /= 4*(float)Math.PI; t += angleCoefficient * angle; } if (gradientCoefficient != 0) { float a = 1/(results[0].dy+results[0].dx); t += gradientCoefficient * a; } return t; } public float turbulence2(float x, float y, float freq) { float t = 0.0f; for (float f = 1.0f; f <= freq; f *= 2) t += evaluate(f*x, f*y) / f; return t; } public int getPixel(int x, int y, int[] inPixels, int width, int height) { try { float nx = m00*x + m01*y; float ny = m10*x + m11*y; nx /= scale; ny /= scale * stretch; nx += 1000; ny += 1000; // Reduce artifacts around 0,0 float f = turbulence == 1.0f ? evaluate(nx, ny) : turbulence2(nx, ny, turbulence); // Normalize to 0..1 // f = (f-min)/(max-min); f *= 2; f *= amount; int a = 0xff000000; int v; if (colormap != null) { v = colormap.getColor(f); if (useColor) { int srcx = ImageMath.clamp((int)((results[0].x-1000)*scale), 0, width-1); int srcy = ImageMath.clamp((int)((results[0].y-1000)*scale), 0, height-1); v = inPixels[srcy * width + srcx]; f = (results[1].distance - results[0].distance) / (results[1].distance + results[0].distance); f = ImageMath.smoothStep(coefficients[1], coefficients[0], f); v = ImageMath.mixColors(f, 0xff000000, v); } return v; } else { v = PixelUtils.clamp((int)(f*255)); int r = v << 16; int g = v << 8; int b = v; return a|r|g|b; } } catch (Exception e) { e.printStackTrace(); return 0; } } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { // float[] minmax = Noise.findRange(this, null); // min = minmax[0]; // max = minmax[1]; int index = 0; int[] outPixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { outPixels[index++] = getPixel(x, y, inPixels, width, height); } } return outPixels; } public void mutate(float mutationLevel, BufferedImageOp d, boolean keepShape, boolean keepColors) { CellularFilter dst = (CellularFilter)d; random.setSeed((int)System.currentTimeMillis()); if (keepShape || amount == 0) { dst.setGridType(getGridType()); dst.setRandomness(getRandomness()); dst.setScale(getScale()); dst.setAngle(getAngle()); dst.setStretch(getStretch()); dst.setAmount(getAmount()); dst.setTurbulence(getTurbulence()); dst.setColormap(getColormap()); dst.setDistancePower(getDistancePower()); dst.setAngleCoefficient(getAngleCoefficient()); for (int i = 0; i < 4; i++) dst.setCoefficient(i, getCoefficient(i)); } else { dst.scale = mutate(scale, mutationLevel, 0.4f, 5, 3, 200); dst.setAngle(mutate(angle, mutationLevel, 0.3f, (float)Math.PI/2)); dst.stretch = mutate(stretch, mutationLevel, 0.3f, 3, 1, 10); dst.amount = mutate(amount, mutationLevel, 0.3f, 0.2f, 0, 1); dst.turbulence = mutate(turbulence, mutationLevel, 0.3f, 0.5f, 1, 8); dst.distancePower = mutate(distancePower, mutationLevel, 0.2f, 0.5f, 1, 3); dst.randomness = mutate(randomness, mutationLevel, 0.4f, 0.2f, 0, 1); for (int i = 0; i < coefficients.length; i++) dst.coefficients[i] = mutate(coefficients[i], mutationLevel, 0.3f, 0.2f, -1, 1); if (random.nextFloat() <= mutationLevel*0.2) dst.gridType = random.nextInt() % 5; dst.angleCoefficient = mutate(angleCoefficient, mutationLevel, 0.2f, 0.5f, -1, 1); } if (keepColors || mutationLevel == 0) dst.setColormap(getColormap()); else if ( random.nextFloat() <= mutationLevel ) { if ( random.nextFloat() <= mutationLevel ) dst.setColormap(Gradient.randomGradient()); else ((Gradient)dst.getColormap()).mutate(mutationLevel); } } private float mutate(float n, float mutationLevel, float probability, float amount, float lower, float upper) { if (random.nextFloat() <= mutationLevel*probability) return n; return ImageMath.clamp(n + mutationLevel*amount * (float)random.nextGaussian(), lower, upper); } private float mutate(float n, float mutationLevel, float probability, float amount) { if (random.nextFloat() <= mutationLevel*probability) return n; return n + mutationLevel*amount * (float)random.nextGaussian(); } public Object clone() { CellularFilter f = (CellularFilter)super.clone(); f.coefficients = (float[])coefficients.clone(); f.results = (Point[])results.clone(); f.random = new Random(); // if (colormap != null) // f.colormap = (Colormap)colormap.clone(); return f; } public String toString() { return "Texture/Cellular..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/OpacityFilter.java0000644000175000017500000000317010521402274022366 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * Sets the opacity (alpha) of every pixel in an image to a constant value. */ public class OpacityFilter extends PointFilter implements java.io.Serializable { static final long serialVersionUID = 5644263685527598345L; private int opacity; private int opacity24; /** * Construct an OpacityFilter with 50% opacity. */ public OpacityFilter() { this(0x88); } /** * Construct an OpacityFilter with the given opacity (alpha). */ public OpacityFilter(int opacity) { setOpacity(opacity); } /** * Set the opacity. * @param opacity the opacity (alpha) in the range 0..255 */ public void setOpacity(int opacity) { this.opacity = opacity; opacity24 = opacity << 24; } /** * Get the opacity setting. * @return the opacity */ public int getOpacity() { return opacity; } public int filterRGB(int x, int y, int rgb) { if ((rgb & 0xff000000) != 0) return (rgb & 0xffffff) | opacity24; return rgb; } public String toString() { return "Colors/Transparency..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/BinaryFilter.java0000644000175000017500000000266210521402272022205 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import com.jhlabs.math.*; public abstract class BinaryFilter extends WholeImageFilter { protected int newColor = 0xff000000; protected BinaryFunction blackFunction = new BlackFunction(); protected int iterations = 1; protected Colormap colormap; public void setIterations(int iterations) { this.iterations = iterations; } public int getIterations() { return iterations; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public void setNewColor(int newColor) { this.newColor = newColor; } public int getNewColor() { return newColor; } public void setBlackFunction(BinaryFunction blackFunction) { this.blackFunction = blackFunction; } public BinaryFunction getBlackFunction() { return blackFunction; } } jhlabs-filters-2.0.235/com/jhlabs/image/VariableBlurFilter.java0000644000175000017500000001273410521402274023336 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.awt.geom.*; public class VariableBlurFilter extends AbstractBufferedImageOp { private int hRadius = 1; private int vRadius = 1; private int iterations = 1; private BufferedImage blurMask; public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; getRGB( src, 0, 0, width, height, inPixels ); for (int i = 0; i < iterations; i++ ) { blur( inPixels, outPixels, width, height, hRadius, 1 ); blur( outPixels, inPixels, height, width, vRadius, 2 ); } setRGB( dst, 0, 0, width, height, inPixels ); return dst; } public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) { if ( dstCM == null ) dstCM = src.getColorModel(); return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null); } public Rectangle2D getBounds2D( BufferedImage src ) { return new Rectangle(0, 0, src.getWidth(), src.getHeight()); } public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) { if ( dstPt == null ) dstPt = new Point2D.Double(); dstPt.setLocation( srcPt.getX(), srcPt.getY() ); return dstPt; } public RenderingHints getRenderingHints() { return null; } public void blur( int[] in, int[] out, int width, int height, int radius, int pass ) { int widthMinus1 = width-1; int[] r = new int[width]; int[] g = new int[width]; int[] b = new int[width]; int[] a = new int[width]; int[] mask = new int[width]; int inIndex = 0; for ( int y = 0; y < height; y++ ) { int outIndex = y; if ( blurMask != null ) { if ( pass == 1 ) getRGB( blurMask, 0, y, width, 1, mask ); else getRGB( blurMask, y, 0, 1, width, mask ); } for ( int x = 0; x < width; x++ ) { int argb = in[inIndex+x]; a[x] = (argb >> 24) & 0xff; r[x] = (argb >> 16) & 0xff; g[x] = (argb >> 8) & 0xff; b[x] = argb & 0xff; if ( x != 0 ) { a[x] += a[x-1]; r[x] += r[x-1]; g[x] += g[x-1]; b[x] += b[x-1]; } } for ( int x = 0; x < width; x++ ) { // Get the blur radius at x, y int ra; if ( blurMask != null ) { if ( pass == 1 ) ra = (int)((mask[x] & 0xff)*hRadius/255f); else ra = (int)((mask[x] & 0xff)*vRadius/255f); } else { if ( pass == 1 ) ra = (int)(blurRadiusAt( x, y, width, height ) * hRadius); else ra = (int)(blurRadiusAt( y, x, height, width ) * vRadius); } int divisor = 2*ra+1; int ta = 0, tr = 0, tg = 0, tb = 0; int i1 = x+ra; if ( i1 > widthMinus1 ) { int f = i1-widthMinus1; int l = widthMinus1; ta += (a[l]-a[l-1]) * f; tr += (r[l]-r[l-1]) * f; tg += (g[l]-g[l-1]) * f; tb += (b[l]-b[l-1]) * f; i1 = widthMinus1; } int i2 = x-ra-1; if ( i2 < 0 ) { ta -= a[0] * i2; tr -= r[0] * i2; tg -= g[0] * i2; tb -= b[0] * i2; i2 = 0; } ta += a[i1] - a[i2]; tr += r[i1] - r[i2]; tg += g[i1] - g[i2]; tb += b[i1] - b[i2]; //if ( y == 0 && pass == 1 )System.out.println(x+": "+i1+" "+i2+" "+r[i1]+" "+r[i2]+" "+tr); out[ outIndex ] = ((ta/divisor) << 24) | ((tr/divisor) << 16) | ((tg/divisor) << 8) | (tb/divisor); outIndex += height; } inIndex += width; } } // Override this to get a different blur radius protected float blurRadiusAt( int x, int y, int width, int height ) { return (float)x/width; } public void setHRadius(int hRadius) { this.hRadius = hRadius; } public int getHRadius() { return hRadius; } public void setVRadius(int vRadius) { this.vRadius = vRadius; } public int getVRadius() { return vRadius; } public void setRadius(int radius) { this.hRadius = this.vRadius = radius; } public int getRadius() { return hRadius; } public void setIterations(int iterations) { this.iterations = iterations; } public int getIterations() { return iterations; } public void setBlurMask(BufferedImage blurMask) { this.blurMask = blurMask; } public BufferedImage getBlurMask() { return blurMask; } public String toString() { return "Blur/Variable Blur..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/GammaFilter.java0000644000175000017500000000351510521402272022001 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter for changing the gamma of an image. */ public class GammaFilter extends TransferFilter { private float rGamma, gGamma, bGamma; public GammaFilter() { this(1.0f); } public GammaFilter(float gamma) { this(gamma, gamma, gamma); } public GammaFilter(float rGamma, float gGamma, float bGamma) { setGamma(rGamma, gGamma, bGamma); } public void setGamma(float rGamma, float gGamma, float bGamma) { this.rGamma = rGamma; this.gGamma = gGamma; this.bGamma = bGamma; initialized = false; } public void setGamma(float gamma) { setGamma(gamma, gamma, gamma); } public float getGamma() { return rGamma; } protected void initialize() { rTable = makeTable(rGamma); if (gGamma == rGamma) gTable = rTable; else gTable = makeTable(gGamma); if (bGamma == rGamma) bTable = rTable; else if (bGamma == gGamma) bTable = gTable; else bTable = makeTable(bGamma); } protected int[] makeTable(float gamma) { int[] table = new int[256]; for (int i = 0; i < 256; i++) { int v = (int) ((255.0 * Math.pow(i/255.0, 1.0 / gamma)) + 0.5); if (v > 255) v = 255; table[i] = v; } return table; } public String toString() { return "Colors/Gamma..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/GradientWipeFilter.java0000644000175000017500000000530510521402274023342 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import java.util.*; /** * A filter which can be used to produce wipes by transferring the luma of a mask image into the alpha channel of the source. */ public class GradientWipeFilter extends AbstractBufferedImageOp { private float density = 0; private float softness = 0; private boolean invert; private BufferedImage mask; public GradientWipeFilter() { } /** * Set the density of the image in the range 0..1. * *arg density The density */ public void setDensity( float density ) { this.density = density; } public float getDensity() { return density; } public void setSoftness( float softness ) { this.softness = softness; } public float getSoftness() { return softness; } public void setMask( BufferedImage mask ) { this.mask = mask; } public BufferedImage getMask() { return mask; } public void setInvert( boolean invert ) { this.invert = invert; } public boolean getInvert() { return invert; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); if ( mask == null ) return dst; int maskWidth = mask.getWidth(); int maskHeight = mask.getHeight(); float d = density * (1+softness); float lower = 255 * (d-softness); float upper = 255 * d; int[] inPixels = new int[width]; int[] maskPixels = new int[maskWidth]; for ( int y = 0; y < height; y++ ) { getRGB( src, 0, y, width, 1, inPixels ); getRGB( mask, 0, y % maskHeight, maskWidth, 1, maskPixels ); for ( int x = 0; x < width; x++ ) { int maskRGB = maskPixels[x % maskWidth]; int inRGB = inPixels[x]; int v = PixelUtils.brightness( maskRGB ); float f = ImageMath.smoothStep( lower, upper, v ); int a = (int)(255 * f); if ( invert ) a = 255-a; inPixels[x] = (a << 24) | (inRGB & 0x00ffffff); } setRGB( dst, 0, y, width, 1, inPixels ); } return dst; } public String toString() { return "Transitions/Gradient Wipe..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/SwimFilter.java0000644000175000017500000000453210521402274021700 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import com.jhlabs.math.*; public class SwimFilter extends TransformFilter { private float scale = 32; private float stretch = 1.0f; private float angle = 0.0f; private float amount = 1.0f; private float turbulence = 1.0f; private float time = 0.0f; private float m00 = 1.0f; private float m01 = 0.0f; private float m10 = 0.0f; private float m11 = 1.0f; public SwimFilter() { } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public void setScale(float scale) { this.scale = scale; } public float getScale() { return scale; } public void setStretch(float stretch) { this.stretch = stretch; } public float getStretch() { return stretch; } public void setAngle(float angle) { this.angle = angle; float cos = (float)Math.cos(angle); float sin = (float)Math.sin(angle); m00 = cos; m01 = sin; m10 = -sin; m11 = cos; } public float getAngle() { return angle; } public void setTurbulence(float turbulence) { this.turbulence = turbulence; } public float getTurbulence() { return turbulence; } public void setTime(float time) { this.time = time; } public float getTime() { return time; } protected void transformInverse(int x, int y, float[] out) { float nx = m00*x + m01*y; float ny = m10*x + m11*y; nx /= scale; ny /= scale * stretch; if ( turbulence == 1.0f ) { out[0] = x + amount * Noise.noise3(nx+0.5f, ny, time); out[1] = y + amount * Noise.noise3(nx, ny+0.5f, time); } else { out[0] = x + amount * Noise.turbulence3(nx+0.5f, ny, turbulence, time); out[1] = y + amount * Noise.turbulence3(nx, ny+0.5f, turbulence, time); } } public String toString() { return "Distort/Swim..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/InterpolateFilter.java0000644000175000017500000000512610521402274023247 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.util.*; public class InterpolateFilter extends AbstractBufferedImageOp { private BufferedImage destination; private float interpolation; public InterpolateFilter() { } public void setDestination( BufferedImage destination ) { this.destination = destination; } public BufferedImage getDestination() { return destination; } public void setInterpolation( float interpolation ) { this.interpolation = interpolation; } public float getInterpolation() { return interpolation; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int type = src.getType(); WritableRaster srcRaster = src.getRaster(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); WritableRaster dstRaster = dst.getRaster(); if ( destination != null ) { width = Math.min( width, destination.getWidth() ); height = Math.min( height, destination.getWidth() ); int[] pixels1 = null; int[] pixels2 = null; for (int y = 0; y < height; y++) { pixels1 = getRGB( src, 0, y, width, 1, pixels1 ); pixels2 = getRGB( destination, 0, y, width, 1, pixels2 ); for (int x = 0; x < width; x++) { int rgb1 = pixels1[x]; int rgb2 = pixels2[x]; int a1 = (rgb1 >> 24) & 0xff; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; int a2 = (rgb2 >> 24) & 0xff; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; r1 = PixelUtils.clamp( ImageMath.lerp( interpolation, r1, r2 ) ); g1 = PixelUtils.clamp( ImageMath.lerp( interpolation, g1, g2 ) ); b1 = PixelUtils.clamp( ImageMath.lerp( interpolation, b1, b2 ) ); pixels1[x] = (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; } setRGB( dst, 0, y, width, 1, pixels1 ); } } return dst; } public String toString() { return "Effects/Interpolate..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/GrayscaleColormap.java0000644000175000017500000000213110521402274023213 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; /** * A grayscale colormap. Black is 0, white is 1. */ public class GrayscaleColormap implements Colormap, java.io.Serializable { static final long serialVersionUID = -6015170137060961021L; public GrayscaleColormap() { } /** * Convert a value in the range 0..1 to an RGB color. * @param v a value in the range 0..1 * @return an RGB color */ public int getColor(float v) { int n = (int)(v*255); if (n < 0) n = 0; else if (n > 255) n = 255; return 0xff000000 | (n << 16) | (n << 8) | n; } } jhlabs-filters-2.0.235/com/jhlabs/image/Quantizer.java0000644000175000017500000000334010521402274021571 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; /** * The interface for an image quantizer. The addColor method is called (repeatedly * if necessary) with all the image pixels. A color table can then be returned by * calling the buildColorTable method. */ public interface Quantizer { /** * Initialize the quantizer. This should be called before adding any pixels. * @param numColors the number of colors we're quantizing to. */ public void setup(int numColors); /** * Add pixels to the quantizer. * @param pixels the array of ARGB pixels * @param offset the offset into the array * @param count the count of pixels */ public void addPixels(int[] pixels, int offset, int count); /* * Build a color table from the added pixels. * @param * @return an array of ARGB pixels representing a color table */ public int[] buildColorTable(); /* * Using the previously-built color table, return the index into that table for a pixel. * This is guaranteed to return a valid index - returning the index of a color closer * to that requested if necessary. * @param rgb the pixel to find * @return the pixel's index in the color table */ public int getIndexForColor(int rgb); } jhlabs-filters-2.0.235/com/jhlabs/image/UnsharpFilter.java0000644000175000017500000000535310521402274022403 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A filter which subtracts Gaussian blur from an image, sharpening it. * @author Jerry Huxtable */ public class UnsharpFilter extends GaussianFilter { static final long serialVersionUID = 5377089073023183684L; private float amount = 0.5f; private int threshold = 1; public UnsharpFilter() { radius = 2; } public void setThreshold( int threshold ) { this.threshold = threshold; } public int getThreshold() { return threshold; } public void setAmount( float amount ) { this.amount = amount; } public float getAmount() { return amount; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; src.getRGB( 0, 0, width, height, inPixels, 0, width ); if ( radius > 0 ) { convolveAndTranspose(kernel, inPixels, outPixels, width, height, alpha, CLAMP_EDGES); convolveAndTranspose(kernel, outPixels, inPixels, height, width, alpha, CLAMP_EDGES); } src.getRGB( 0, 0, width, height, outPixels, 0, width ); float a = 4*amount; int index = 0; for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++ ) { int rgb1 = outPixels[index]; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; int rgb2 = inPixels[index]; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; if ( Math.abs( r1 - r2 ) >= threshold ) r1 = PixelUtils.clamp( (int)((a+1) * (r1-r2) + r2) ); if ( Math.abs( g1 - g2 ) >= threshold ) g1 = PixelUtils.clamp( (int)((a+1) * (g1-g2) + g2) ); if ( Math.abs( b1 - b2 ) >= threshold ) b1 = PixelUtils.clamp( (int)((a+1) * (b1-b2) + b2) ); inPixels[index] = (rgb1 & 0xff000000) | (r1 << 16) | (g1 << 8) | b1; index++; } } dst.setRGB( 0, 0, width, height, inPixels, 0, width ); return dst; } public String toString() { return "Blur/Unsharp Mask..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/BoxBlurFilter.java0000644000175000017500000000764010521402272022337 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.awt.geom.*; /** * A filter which performs a box blur on an image. The horizontal and vertical blurs can be specified separately * and a number of iterations can be given which allows an approximation to Gaussian blur. */ public class BoxBlurFilter extends AbstractBufferedImageOp { private int hRadius; private int vRadius; private int iterations = 1; public BoxBlurFilter() { } public BoxBlurFilter( int hRadius, int vRadius, int iterations ) { this.hRadius = hRadius; this.vRadius = vRadius; this.iterations = iterations; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; getRGB( src, 0, 0, width, height, inPixels ); for (int i = 0; i < iterations; i++ ) { blur( inPixels, outPixels, width, height, hRadius ); blur( outPixels, inPixels, height, width, vRadius ); } setRGB( dst, 0, 0, width, height, inPixels ); return dst; } public static void blur( int[] in, int[] out, int width, int height, int radius ) { int widthMinus1 = width-1; int tableSize = 2*radius+1; int divide[] = new int[256*tableSize]; for ( int i = 0; i < 256*tableSize; i++ ) divide[i] = i/tableSize; int inIndex = 0; for ( int y = 0; y < height; y++ ) { int outIndex = y; int ta = 0, tr = 0, tg = 0, tb = 0; for ( int i = -radius; i <= radius; i++ ) { int rgb = in[inIndex + ImageMath.clamp(i, 0, width-1)]; ta += (rgb >> 24) & 0xff; tr += (rgb >> 16) & 0xff; tg += (rgb >> 8) & 0xff; tb += rgb & 0xff; } for ( int x = 0; x < width; x++ ) { out[ outIndex ] = (divide[ta] << 24) | (divide[tr] << 16) | (divide[tg] << 8) | divide[tb]; int i1 = x+radius+1; if ( i1 > widthMinus1 ) i1 = widthMinus1; int i2 = x-radius; if ( i2 < 0 ) i2 = 0; int rgb1 = in[inIndex+i1]; int rgb2 = in[inIndex+i2]; ta += ((rgb1 >> 24) & 0xff)-((rgb2 >> 24) & 0xff); tr += ((rgb1 & 0xff0000)-(rgb2 & 0xff0000)) >> 16; tg += ((rgb1 & 0xff00)-(rgb2 & 0xff00)) >> 8; tb += (rgb1 & 0xff)-(rgb2 & 0xff); outIndex += height; } inIndex += width; } } public void setHRadius(int hRadius) { this.hRadius = hRadius; } public int getHRadius() { return hRadius; } public void setVRadius(int vRadius) { this.vRadius = vRadius; } public int getVRadius() { return vRadius; } public void setRadius(int radius) { this.hRadius = this.vRadius = radius; } public int getRadius() { return hRadius; } public void setIterations(int iterations) { this.iterations = iterations; } public int getIterations() { return iterations; } public String toString() { return "Blur/Box Blur..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/KeyFilter.java0000644000175000017500000000777310521402274021523 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.util.*; /** * A filter which can be used to produce wipes by transferring the luma of a Destination image into the alpha channel of the source. */ public class KeyFilter extends AbstractBufferedImageOp { private float hTolerance = 0; private float sTolerance = 0; private float bTolerance = 0; private BufferedImage destination; private BufferedImage cleanImage; public KeyFilter() { } /** * Set the tolerance of the image in the range 0..1. * *arg tolerance The tolerance */ public void setHTolerance( float hTolerance ) { this.hTolerance = hTolerance; } public float getHTolerance() { return hTolerance; } public void setSTolerance( float sTolerance ) { this.sTolerance = sTolerance; } public float getSTolerance() { return sTolerance; } public void setBTolerance( float bTolerance ) { this.bTolerance = bTolerance; } public float getBTolerance() { return bTolerance; } public void setDestination( BufferedImage destination ) { this.destination = destination; } public BufferedImage getDestination() { return destination; } public void setCleanImage( BufferedImage cleanImage ) { this.cleanImage = cleanImage; } public BufferedImage getCleanImage() { return cleanImage; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int type = src.getType(); WritableRaster srcRaster = src.getRaster(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); WritableRaster dstRaster = dst.getRaster(); if ( destination != null && cleanImage != null ) { float[] hsb1 = null; float[] hsb2 = null; int[] inPixels = null; int[] outPixels = null; int[] cleanPixels = null; for ( int y = 0; y < height; y++ ) { inPixels = getRGB( src, 0, y, width, 1, inPixels ); outPixels = getRGB( destination, 0, y, width, 1, outPixels ); cleanPixels = getRGB( cleanImage, 0, y, width, 1, cleanPixels ); for ( int x = 0; x < width; x++ ) { int rgb1 = inPixels[x]; int out = outPixels[x]; int rgb2 = cleanPixels[x]; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; hsb1 = Color.RGBtoHSB( r1, b1, g1, hsb1 ); hsb2 = Color.RGBtoHSB( r2, b2, g2, hsb2 ); // int tolerance = (int)(255*tolerance); // return Math.abs(r1-r2) <= tolerance && Math.abs(g1-g2) <= tolerance && Math.abs(b1-b2) <= tolerance; // if ( PixelUtils.nearColors( in, clean, (int)(255*tolerance) ) ) if ( Math.abs( hsb1[0] - hsb2[0] ) < hTolerance && Math.abs( hsb1[1] - hsb2[1] ) < sTolerance && Math.abs( hsb1[2] - hsb2[2] ) < bTolerance ) inPixels[x] = out; else inPixels[x] = rgb1; } setRGB( dst, 0, y, width, 1, inPixels ); } } return dst; } public String toString() { return "Keying/Key..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/MotionBlurFilter.java0000644000175000017500000001012210521402274023043 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import java.awt.geom.*; /** * A filter which produces motion blur the slow, but higher-quality way. */ public class MotionBlurFilter extends AbstractBufferedImageOp { public final static int LINEAR = 0; public final static int RADIAL = 1; public final static int ZOOM = 2; private float angle = 0.0f; private float falloff = 1.0f; private float distance = 1.0f; private float zoom = 0.0f; private float rotation = 0.0f; private boolean wrapEdges = false; public MotionBlurFilter() { } public void setAngle( float angle ) { this.angle = angle; } public float getAngle() { return angle; } public void setDistance( float distance ) { this.distance = distance; } public float getDistance() { return distance; } public void setRotation( float rotation ) { this.rotation = rotation; } public float getRotation() { return rotation; } public void setZoom( float zoom ) { this.zoom = zoom; } public float getZoom() { return zoom; } public void setWrapEdges(boolean wrapEdges) { this.wrapEdges = wrapEdges; } public boolean getWrapEdges() { return wrapEdges; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; getRGB( src, 0, 0, width, height, inPixels ); float sinAngle = (float)Math.sin(angle); float cosAngle = (float)Math.cos(angle); float total; int cx = width/2; int cy = height/2; int index = 0; float imageRadius = (float)Math.sqrt( cx*cx + cy*cy ); float translateX = (float)(distance * Math.cos( angle )); float translateY = (float)(distance * -Math.sin( angle )); float maxDistance = distance + Math.abs(rotation*imageRadius) + zoom*imageRadius; int repetitions = (int)maxDistance; AffineTransform t = new AffineTransform(); Point2D.Float p = new Point2D.Float(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int a = 0, r = 0, g = 0, b = 0; int count = 0; for (int i = 0; i < repetitions; i++) { int newX = x, newY = y; float f = (float)i/repetitions; p.x = x; p.y = y; t.setToIdentity(); t.translate( cx+f*translateX, cy+f*translateY ); float s = 1-zoom*f; t.scale( s, s ); if ( rotation != 0 ) t.rotate( -rotation*f ); t.translate( -cx, -cy ); t.transform( p, p ); newX = (int)p.x; newY = (int)p.y; if (newX < 0 || newX >= width) { if ( wrapEdges ) newX = ImageMath.mod( newX, width ); else break; } if (newY < 0 || newY >= height) { if ( wrapEdges ) newY = ImageMath.mod( newY, height ); else break; } count++; int rgb = inPixels[newY*width+newX]; a += (rgb >> 24) & 0xff; r += (rgb >> 16) & 0xff; g += (rgb >> 8) & 0xff; b += rgb & 0xff; } if (count == 0) { outPixels[index] = inPixels[index]; } else { a = PixelUtils.clamp((int)(a/count)); r = PixelUtils.clamp((int)(r/count)); g = PixelUtils.clamp((int)(g/count)); b = PixelUtils.clamp((int)(b/count)); outPixels[index] = (a << 24) | (r << 16) | (g << 8) | b; } index++; } } setRGB( dst, 0, 0, width, height, outPixels ); return dst; } public String toString() { return "Blur/Motion Blur..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/SmearFilter.java0000644000175000017500000001461110521402274022027 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.util.*; import java.awt.*; import java.awt.image.*; import com.jhlabs.math.*; public class SmearFilter extends WholeImageFilter implements java.io.Serializable { static final long serialVersionUID = 6491871753122667752L; public final static int CROSSES = 0; public final static int LINES = 1; public final static int CIRCLES = 2; public final static int SQUARES = 3; private Colormap colormap = new LinearColormap(); private float angle = 0; private float density = 0.5f; private float scatter = 0.0f; private int distance = 8; private Random randomGenerator; private long seed = 567; private int shape = LINES; private float mix = 0.5f; private int fadeout = 0; private boolean background = false; public SmearFilter() { randomGenerator = new Random(); } public void setShape(int shape) { this.shape = shape; } public int getShape() { return shape; } public void setDistance(int distance) { this.distance = distance; } public int getDistance() { return distance; } public void setDensity(float density) { this.density = density; } public float getDensity() { return density; } public void setScatter(float scatter) { this.scatter = scatter; } public float getScatter() { return scatter; } public void setAngle(float angle) { this.angle = angle; } public float getAngle() { return angle; } public void setMix(float mix) { this.mix = mix; } public float getMix() { return mix; } public void setFadeout(int fadeout) { this.fadeout = fadeout; } public int getFadeout() { return fadeout; } public void setBackground(boolean background) { this.background = background; } public boolean getBackground() { return background; } public void randomize() { seed = new Date().getTime(); } private float random(float low, float high) { return low+(high-low) * randomGenerator.nextFloat(); } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int[] outPixels = new int[width * height]; randomGenerator.setSeed(seed); float sinAngle = (float)Math.sin(angle); float cosAngle = (float)Math.cos(angle); int i = 0; int numShapes; for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { outPixels[i] = background ? 0xffffffff : inPixels[i]; i++; } switch (shape) { case CROSSES: //Crosses numShapes = (int)(2*density*width * height / (distance + 1)); for (i = 0; i < numShapes; i++) { int x = (randomGenerator.nextInt() & 0x7fffffff) % width; int y = (randomGenerator.nextInt() & 0x7fffffff) % height; int length = randomGenerator.nextInt() % distance + 1; int rgb = inPixels[y*width+x]; for (int x1 = x - length; x1 < x + length + 1; x1++) { if (x1 >= 0 && x1 < width) { int rgb2 = background ? 0xffffffff : outPixels[y*width+x1]; outPixels[y*width+x1] = ImageMath.mixColors(mix, rgb2, rgb); } } for (int y1 = y - length; y1 < y + length + 1; y1++) { if (y1 >= 0 && y1 < height) { int rgb2 = background ? 0xffffffff : outPixels[y1*width+x]; outPixels[y1*width+x] = ImageMath.mixColors(mix, rgb2, rgb); } } } break; case LINES: numShapes = (int)(2*density*width * height / 2); for (i = 0; i < numShapes; i++) { int sx = (randomGenerator.nextInt() & 0x7fffffff) % width; int sy = (randomGenerator.nextInt() & 0x7fffffff) % height; int rgb = inPixels[sy*width+sx]; int length = (randomGenerator.nextInt() & 0x7fffffff) % distance; int dx = (int)(length*cosAngle); int dy = (int)(length*sinAngle); int x0 = sx-dx; int y0 = sy-dy; int x1 = sx+dx; int y1 = sy+dy; int x, y, d, incrE, incrNE, ddx, ddy; if (x1 < x0) ddx = -1; else ddx = 1; if (y1 < y0) ddy = -1; else ddy = 1; dx = x1-x0; dy = y1-y0; dx = Math.abs(dx); dy = Math.abs(dy); x = x0; y = y0; if (x < width && x >= 0 && y < height && y >= 0) { int rgb2 = background ? 0xffffffff : outPixels[y*width+x]; outPixels[y*width+x] = ImageMath.mixColors(mix, rgb2, rgb); } if (Math.abs(dx) > Math.abs(dy)) { d = 2*dy-dx; incrE = 2*dy; incrNE = 2*(dy-dx); while (x != x1) { if (d <= 0) d += incrE; else { d += incrNE; y += ddy; } x += ddx; if (x < width && x >= 0 && y < height && y >= 0) { int rgb2 = background ? 0xffffffff : outPixels[y*width+x]; outPixels[y*width+x] = ImageMath.mixColors(mix, rgb2, rgb); } } } else { d = 2*dx-dy; incrE = 2*dx; incrNE = 2*(dx-dy); while (y != y1) { if (d <= 0) d += incrE; else { d += incrNE; x += ddx; } y += ddy; if (x < width && x >= 0 && y < height && y >= 0) { int rgb2 = background ? 0xffffffff : outPixels[y*width+x]; outPixels[y*width+x] = ImageMath.mixColors(mix, rgb2, rgb); } } } } break; case SQUARES: case CIRCLES: int radius = distance+1; int radius2 = radius * radius; numShapes = (int)(2*density*width * height / radius); for (i = 0; i < numShapes; i++) { int sx = (randomGenerator.nextInt() & 0x7fffffff) % width; int sy = (randomGenerator.nextInt() & 0x7fffffff) % height; int rgb = inPixels[sy*width+sx]; for (int x = sx - radius; x < sx + radius + 1; x++) { for (int y = sy - radius; y < sy + radius + 1; y++) { int f; if (shape == CIRCLES) f = (x - sx) * (x - sx) + (y - sy) * (y - sy); else f = 0; if (x >= 0 && x < width && y >= 0 && y < height && f <= radius2) { int rgb2 = background ? 0xffffffff : outPixels[y*width+x]; outPixels[y*width+x] = ImageMath.mixColors(mix, rgb2, rgb); } } } } } return outPixels; } public String toString() { return "Effects/Smear..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/WarpFilter.java0000644000175000017500000001030510521402274021665 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.event.*; import java.awt.image.*; /** * A filter for warping images using the gridwarp algorithm. * You need to supply two warp grids, one for the source image and * one for the destination image. The image will be warped so that * a point in the source grid moves to its counterpart in the destination * grid. */ public class WarpFilter extends WholeImageFilter { static final long serialVersionUID = 1299148944426051330L; private WarpGrid sourceGrid; private WarpGrid destGrid; private int frames = 1; private BufferedImage morphImage; private float time; /** * Create a WarpFilter. */ public WarpFilter() { } /** * Create a WarpFilter with two warp grids. * @param sourceGrid the source grid * @param destGrid the destination grid */ public WarpFilter(WarpGrid sourceGrid, WarpGrid destGrid) { this.sourceGrid = sourceGrid; this.destGrid = destGrid; } /** * Set the source warp grid. * @param sourceGrid the source grid */ public void setSourceGrid(WarpGrid sourceGrid) { this.sourceGrid = sourceGrid; } /** * Get the source warp grid. * @return the source grid */ public WarpGrid getSourceGrid() { return sourceGrid; } /** * Set the destination warp grid. * @param destGrid the destination grid */ public void setDestGrid(WarpGrid destGrid) { this.destGrid = destGrid; } /** * Get the destination warp grid. * @return the destination grid */ public WarpGrid getDestGrid() { return destGrid; } public void setFrames(int frames) { this.frames = frames; } public int getFrames() { return frames; } /** * For morphing, sets the image we're morphing to. If not, set then we're just warping. */ public void setMorphImage(BufferedImage morphImage) { this.morphImage = morphImage; } public BufferedImage getMorphImage() { return morphImage; } public void setTime(float time) { this.time = time; } public float getTime() { return time; } protected void transformSpace(Rectangle r) { r.width *= frames; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int[] outPixels = new int[width * height]; if ( morphImage != null ) { int[] morphPixels = getRGB( morphImage, 0, 0, width, height, null ); morph( inPixels, morphPixels, outPixels, sourceGrid, destGrid, width, height, time ); } else if (frames <= 1) { sourceGrid.warp(inPixels, width, height, sourceGrid, destGrid, outPixels); } else { WarpGrid newGrid = new WarpGrid(sourceGrid.rows, sourceGrid.cols, width, height); for (int i = 0; i < frames; i++) { float t = (float)i/(frames-1); sourceGrid.lerp(t, destGrid, newGrid); sourceGrid.warp(inPixels, width, height, sourceGrid, newGrid, outPixels); } } return outPixels; } public void morph(int[] srcPixels, int[] destPixels, int[] outPixels, WarpGrid srcGrid, WarpGrid destGrid, int width, int height, float t) { WarpGrid newGrid = new WarpGrid(srcGrid.rows, srcGrid.cols, width, height); srcGrid.lerp(t, destGrid, newGrid); srcGrid.warp(srcPixels, width, height, srcGrid, newGrid, outPixels); int[] destPixels2 = new int[width * height]; destGrid.warp(destPixels, width, height, destGrid, newGrid, destPixels2); crossDissolve(outPixels, destPixels2, width, height, t); } public void crossDissolve(int[] pixels1, int[] pixels2, int width, int height, float t) { int index = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { pixels1[index] = ImageMath.mixColors(t, pixels1[index], pixels2[index]); index++; } } } public String toString() { return "Distort/Mesh Warp..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/FieldWarpFilter.java0000644000175000017500000001040210521402272022625 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A class which warps an image using a field Warp algorithm. */ public class FieldWarpFilter extends TransformFilter { public static class Line { public int x1, y1, x2, y2; public int dx, dy; public float length, lengthSquared; public Line(int x1, int y1, int x2, int y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } public void setup() { dx = x2-x1; dy = y2-y1; lengthSquared = dx*dx + dy*dy; length = (float)Math.sqrt(lengthSquared); } } private float amount = 1.0f; private float power = 1.0f; private float strength = 2.0f; private Line[] inLines; private Line[] outLines; private Line[] intermediateLines; private float width, height; public FieldWarpFilter() { } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public void setPower(float power) { this.power = power; } public float getPower() { return power; } public void setStrength(float strength) { this.strength = strength; } public float getStrength() { return strength; } public void setInLines( Line[] inLines ) { this.inLines = inLines; } public Line[] getInLines() { return inLines; } public void setOutLines( Line[] outLines ) { this.outLines = outLines; } public Line[] getOutLines() { return outLines; } protected void transform(int x, int y, Point out) { } protected void transformInverse(int x, int y, float[] out) { float u = 0, v = 0; float fraction = 0; float distance; float fdist; float weight; float a = 0.001f; float b = 1.5f*strength + 0.5f; float p = power; float totalWeight = 0.0f; float sumX = 0.0f; float sumY = 0.0f; for (int line = 0; line < inLines.length; line++) { Line l1 = inLines[line]; Line l = intermediateLines[line]; float dx = x - l.x1; float dy = y - l.y1; fraction = (dx * l.dx + dy * l.dy) / l.lengthSquared; fdist = (dy * l.dx - dx * l.dy) / l.length; if (fraction <= 0) distance = (float)Math.sqrt(dx*dx + dy*dy); else if (fraction >= 1) { dx = x - l.x2; dy = y - l.y2; distance = (float)Math.sqrt(dx*dx + dy*dy); } else if (fdist >= 0) distance = fdist; else distance = -fdist; u = l1.x1 + fraction * l1.dx - fdist * l1.dy / l1.length; v = l1.y1 + fraction * l1.dy + fdist * l1.dx / l1.length; weight = (float)Math.pow(Math.pow(l.length, p) / (a + distance), b); sumX += (u - x) * weight; sumY += (v - y) * weight; //if (x % 10 == 0&&y == 20)System.out.println("distance="+distance+" weight="+weight+" sumX="+sumX+" sumY="+sumY+" u="+u+" v="+v); totalWeight += weight; } // out[0] = ImageMath.clamp(x + sumX / totalWeight + 0.5f, 0, width-1); // out[1] = ImageMath.clamp(y + sumY / totalWeight + 0.5f, 0, height-1); out[0] = x + sumX / totalWeight + 0.5f; out[1] = y + sumY / totalWeight + 0.5f; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { this.width = width; this.height = height; if ( inLines != null && outLines != null ) { intermediateLines = new Line[inLines.length]; for (int line = 0; line < inLines.length; line++) { Line l = intermediateLines[line] = new Line( ImageMath.lerp(amount, inLines[line].x1, outLines[line].x1), ImageMath.lerp(amount, inLines[line].y1, outLines[line].y1), ImageMath.lerp(amount, inLines[line].x2, outLines[line].x2), ImageMath.lerp(amount, inLines[line].y2, outLines[line].y2) ); l.setup(); inLines[line].setup(); } dst = super.filter( src, dst ); intermediateLines = null; return dst; } return src; } public String toString() { return "Distort/Field Warp..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ContrastFilter.java0000644000175000017500000000234210521402272022551 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class ContrastFilter extends TransferFilter { private float brightness = 1.0f; private float contrast = 1.0f; protected float transferFunction( float f ) { f = f*brightness; f = (f-0.5f)*contrast+0.5f; return f; } public void setBrightness(float brightness) { this.brightness = brightness; initialized = false; } public float getBrightness() { return brightness; } public void setContrast(float contrast) { this.contrast = contrast; initialized = false; } public float getContrast() { return contrast; } public String toString() { return "Colors/Contrast..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/KaleidoscopeFilter.java0000644000175000017500000000545710521402274023372 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; /** * A Filter which produces the effect of looking into a kaleidoscope. */ public class KaleidoscopeFilter extends TransformFilter { private float angle = 0; private float angle2 = 0; private float centreX = 0.5f; private float centreY = 0.5f; private int sides = 3; private float radius = 0; private float icentreX; private float icentreY; /** * Construct a KaleidoscopeFilter with no distortion. */ public KaleidoscopeFilter() { setEdgeAction( CLAMP ); } public void setSides(int sides) { this.sides = sides; } public int getSides() { return sides; } public void setAngle(float angle) { this.angle = angle; } public float getAngle() { return angle; } public void setAngle2(float angle2) { this.angle2 = angle2; } public float getAngle2() { return angle2; } public void setCentreX( float centreX ) { this.centreX = centreX; } public float getCentreX() { return centreX; } public void setCentreY( float centreY ) { this.centreY = centreY; } public float getCentreY() { return centreY; } public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } public void setRadius( float radius ) { this.radius = radius; } public float getRadius() { return radius; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { icentreX = src.getWidth() * centreX; icentreY = src.getHeight() * centreY; return super.filter( src, dst ); } protected void transformInverse(int x, int y, float[] out) { double dx = x-icentreX; double dy = y-icentreY; double r = Math.sqrt( dx*dx + dy*dy ); double theta = Math.atan2( dy, dx ) - angle - angle2; theta = ImageMath.triangle( (float)( theta/Math.PI*sides*.5 ) ); if ( radius != 0 ) { double c = Math.cos(theta); double radiusc = radius/c; r = radiusc * ImageMath.triangle( (float)(r/radiusc) ); } theta += angle; out[0] = (float)(icentreX + r*Math.cos(theta)); out[1] = (float)(icentreY + r*Math.sin(theta)); } public String toString() { return "Distort/Kaleidoscope..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/InvertAlphaFilter.java0000644000175000017500000000202310521402274023167 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A Filter to invert the alpha channel of an image. This is really only useful for inverting selections, where we only use the alpha channel. */ public class InvertAlphaFilter extends PointFilter { public InvertAlphaFilter() { canFilterIndexColorModel = true; } public int filterRGB(int x, int y, int rgb) { return rgb ^ 0xff000000; } public String toString() { return "Alpha/Invert"; } } jhlabs-filters-2.0.235/com/jhlabs/image/ShadowFilter.java0000644000175000017500000001077610521402274022215 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; public class ShadowFilter extends AbstractBufferedImageOp { static final long serialVersionUID = 6310370419462785691L; private float radius = 5; private float angle = (float)Math.PI*6/4; private float distance = 5; private float opacity = 0.5f; private boolean addMargins = false; private boolean shadowOnly = false; private int shadowColor = 0xff000000; public ShadowFilter() { } public ShadowFilter(float radius, float xOffset, float yOffset, float opacity) { this.radius = radius; this.angle = (float)Math.atan2(yOffset, xOffset); this.distance = (float)Math.sqrt(xOffset*xOffset + yOffset*yOffset); this.opacity = opacity; } public void setAngle(float angle) { this.angle = angle; } public float getAngle() { return angle; } public void setDistance(float distance) { this.distance = distance; } public float getDistance() { return distance; } /** * Set the radius of the kernel, and hence the amount of blur. The bigger the radius, the longer this filter will take. * @param radius the radius of the blur in pixels. */ public void setRadius(float radius) { this.radius = radius; } /** * Get the radius of the kernel. * @return the radius */ public float getRadius() { return radius; } public void setOpacity(float opacity) { this.opacity = opacity; } public float getOpacity() { return opacity; } public void setShadowColor(int shadowColor) { this.shadowColor = shadowColor; } public int getShadowColor() { return shadowColor; } public void setAddMargins(boolean addMargins) { this.addMargins = addMargins; } public boolean getAddMargins() { return addMargins; } public void setShadowOnly(boolean shadowOnly) { this.shadowOnly = shadowOnly; } public boolean getShadowOnly() { return shadowOnly; } protected void transformSpace(Rectangle r) { if ( addMargins ) { float xOffset = distance*(float)Math.cos(angle); float yOffset = -distance*(float)Math.sin(angle); r.width += (int)(Math.abs(xOffset)+2*radius); r.height += (int)(Math.abs(yOffset)+2*radius); } } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) { if ( addMargins ) { ColorModel cm = src.getColorModel(); dst = new BufferedImage(cm, cm.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), cm.isAlphaPremultiplied(), null); } else dst = createCompatibleDestImage( src, null ); } float shadowR = ((shadowColor >> 16) & 0xff) / 255f; float shadowG = ((shadowColor >> 8) & 0xff) / 255f; float shadowB = (shadowColor & 0xff) / 255f; // Make a black mask from the image's alpha channel float[][] extractAlpha = { { 0, 0, 0, shadowR }, { 0, 0, 0, shadowG }, { 0, 0, 0, shadowB }, { 0, 0, 0, opacity } }; BufferedImage shadow = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); new BandCombineOp( extractAlpha, null ).filter( src.getRaster(), shadow.getRaster() ); shadow = new GaussianFilter( radius ).filter( shadow, null ); float xOffset = distance*(float)Math.cos(angle); float yOffset = -distance*(float)Math.sin(angle); Graphics2D g = dst.createGraphics(); g.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, opacity ) ); if ( addMargins ) { float radius2 = radius/2; float topShadow = Math.max( 0, radius-yOffset ); float leftShadow = Math.max( 0, radius-xOffset ); g.translate( topShadow, leftShadow ); } g.drawRenderedImage( shadow, AffineTransform.getTranslateInstance( xOffset, yOffset ) ); if ( !shadowOnly ) { g.setComposite( AlphaComposite.SrcOver ); g.drawRenderedImage( src, null ); } g.dispose(); return dst; } public String toString() { return "Stylize/Drop Shadow..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ApplyMaskFilter.java0000644000175000017500000000537210521402272022663 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.util.*; /** * A filter which uses the alpha channel of a "mask" image to interpolate between two source images. */ public class ApplyMaskFilter extends AbstractBufferedImageOp { private BufferedImage destination; private BufferedImage maskImage; public ApplyMaskFilter() { } public void setDestination( BufferedImage destination ) { this.destination = destination; } public BufferedImage getDestination() { return destination; } public void setMaskImage( BufferedImage maskImage ) { this.maskImage = maskImage; } public BufferedImage getMaskImage() { return maskImage; } public static void composeThroughMask(Raster src, WritableRaster dst, Raster sel) { int x = src.getMinX(); int y = src.getMinY(); int w = src.getWidth(); int h = src.getHeight(); int srcRGB[] = null; int selRGB[] = null; int dstRGB[] = null; for ( int i = 0; i < h; i++ ) { srcRGB = src.getPixels(x, y, w, 1, srcRGB); selRGB = sel.getPixels(x, y, w, 1, selRGB); dstRGB = dst.getPixels(x, y, w, 1, dstRGB); int k = x; for ( int j = 0; j < w; j++ ) { int sr = srcRGB[k]; int dir = dstRGB[k]; int sg = srcRGB[k+1]; int dig = dstRGB[k+1]; int sb = srcRGB[k+2]; int dib = dstRGB[k+2]; int sa = srcRGB[k+3]; int dia = dstRGB[k+3]; float a = selRGB[k+3]/255f; float ac = 1-a; dstRGB[k] = (int)(a*sr + ac*dir); dstRGB[k+1] = (int)(a*sg + ac*dig); dstRGB[k+2] = (int)(a*sb + ac*dib); dstRGB[k+3] = (int)(a*sa + ac*dia); k += 4; } dst.setPixels(x, y, w, 1, dstRGB); y++; } } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int type = src.getType(); WritableRaster srcRaster = src.getRaster(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); WritableRaster dstRaster = dst.getRaster(); if ( destination != null && maskImage != null ) composeThroughMask( src.getRaster(), dst.getRaster(), maskImage.getRaster() ); return dst; } public String toString() { return "Keying/Key..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/RenderTextFilter.java0000644000175000017500000000416410521402274023046 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; /** * A filter which renders text onto an image. */ public class RenderTextFilter extends AbstractBufferedImageOp { private String text; private Font font; private Paint paint; private Composite composite; private AffineTransform transform; public RenderTextFilter() { } public RenderTextFilter( String text, Font font, Paint paint, Composite composite, AffineTransform transform ) { this.text = text; this.font = font; this.composite = composite; this.paint = paint; this.transform = transform; } public void setComposite( String text ) { this.text = text; } public String getText() { return text; } public void setComposite( Composite composite ) { this.composite = composite; } public Composite getComposite() { return composite; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { if ( dst == null ) dst = createCompatibleDestImage( src, null ); Graphics2D g = dst.createGraphics(); g.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON ); if ( font != null ) g.setFont( font ); if ( transform != null ) g.setTransform( transform ); if ( composite != null ) g.setComposite( composite ); if ( paint != null ) g.setPaint( paint ); if ( text != null ) g.drawString( text, 10, 100 ); g.dispose(); return dst; } } jhlabs-filters-2.0.235/com/jhlabs/image/CrystallizeFilter.java0000644000175000017500000000446510521402272023271 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.util.*; import com.jhlabs.math.*; public class CrystallizeFilter extends CellularFilter { private float edgeThickness = 0.4f; private boolean fadeEdges = false; private int edgeColor = 0xff000000; public CrystallizeFilter() { setScale(16); setRandomness(0.0f); } public void setEdgeThickness(float edgeThickness) { this.edgeThickness = edgeThickness; } public float getEdgeThickness() { return edgeThickness; } public void setFadeEdges(boolean fadeEdges) { this.fadeEdges = fadeEdges; } public boolean getFadeEdges() { return fadeEdges; } public void setEdgeColor(int edgeColor) { this.edgeColor = edgeColor; } public int getEdgeColor() { return edgeColor; } public int getPixel(int x, int y, int[] inPixels, int width, int height) { float nx = m00*x + m01*y; float ny = m10*x + m11*y; nx /= scale; ny /= scale * stretch; nx += 1000; ny += 1000; // Reduce artifacts around 0,0 float f = evaluate(nx, ny); float f1 = results[0].distance; float f2 = results[1].distance; int srcx = ImageMath.clamp((int)((results[0].x-1000)*scale), 0, width-1); int srcy = ImageMath.clamp((int)((results[0].y-1000)*scale), 0, height-1); int v = inPixels[srcy * width + srcx]; f = (f2 - f1) / edgeThickness; f = ImageMath.smoothStep(0, edgeThickness, f); if (fadeEdges) { srcx = ImageMath.clamp((int)((results[1].x-1000)*scale), 0, width-1); srcy = ImageMath.clamp((int)((results[1].y-1000)*scale), 0, height-1); int v2 = inPixels[srcy * width + srcx]; v2 = ImageMath.mixColors(0.5f, v2, v); v = ImageMath.mixColors(f, v2, v); } else v = ImageMath.mixColors(f, edgeColor, v); return v; } public String toString() { return "Stylize/Crystallize..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ChromeFilter.java0000644000175000017500000000271510521402272022175 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A filter which simulates chrome. */ public class ChromeFilter extends LightFilter { private float amount = 0.5f; private float exposure = 1.0f; public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public void setExposure(float exposure) { this.exposure = exposure; } public float getExposure() { return exposure; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { setColorSource( LightFilter.COLORS_CONSTANT ); dst = super.filter( src, dst ); TransferFilter tf = new TransferFilter() { protected float transferFunction( float v ) { v += amount * (float)Math.sin( v * 2 * Math.PI ); return 1 - (float)Math.exp(-v * exposure); } }; return tf.filter( dst, dst ); } public String toString() { return "Effects/Chrome..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/RaysFilter.java0000644000175000017500000000703310521402274021676 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import com.jhlabs.composite.*; public class RaysFilter extends MotionBlurOp { private float opacity = 1.0f; private float threshold = 0.0f; private float strength = 0.5f; private boolean raysOnly = false; private Colormap colormap; public RaysFilter() { } public void setOpacity(float opacity) { this.opacity = opacity; } public float getOpacity() { return opacity; } public void setThreshold( float threshold ) { this.threshold = threshold; } public float getThreshold() { return threshold; } public void setStrength( float strength ) { this.strength = strength; } public float getStrength() { return strength; } public void setRaysOnly(boolean raysOnly) { this.raysOnly = raysOnly; } public boolean getRaysOnly() { return raysOnly; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int[] pixels = new int[width]; int[] srcPixels = new int[width]; BufferedImage rays = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); int threshold3 = (int)(threshold*3*255); for ( int y = 0; y < height; y++ ) { getRGB( src, 0, y, width, 1, pixels ); for ( int x = 0; x < width; x++ ) { int rgb = pixels[x]; int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; int l = r + g + b; if (l < threshold3) pixels[x] = 0xff000000; else { l /= 3; pixels[x] = a | (l << 16) | (l << 8) | l; } } setRGB( rays, 0, y, width, 1, pixels ); } rays = super.filter( rays, null ); for ( int y = 0; y < height; y++ ) { getRGB( rays, 0, y, width, 1, pixels ); getRGB( src, 0, y, width, 1, srcPixels ); for ( int x = 0; x < width; x++ ) { int rgb = pixels[x]; int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; if ( colormap != null ) { int l = r + g + b; rgb = colormap.getColor( l * strength * (1/3f) ); } else { r = PixelUtils.clamp((int)(r * strength)); g = PixelUtils.clamp((int)(g * strength)); b = PixelUtils.clamp((int)(b * strength)); rgb = a | (r << 16) | (g << 8) | b; } pixels[x] = rgb; } setRGB( rays, 0, y, width, 1, pixels ); } if ( dst == null ) dst = createCompatibleDestImage( src, null ); Graphics2D g = dst.createGraphics(); if ( !raysOnly ) { g.setComposite( AlphaComposite.SrcOver ); g.drawRenderedImage( src, null ); } g.setComposite( MiscComposite.getInstance( MiscComposite.ADD, opacity ) ); g.drawRenderedImage( rays, null ); g.dispose(); return dst; } public String toString() { return "Stylize/Rays..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/EmbossFilter.java0000644000175000017500000000667310521402272022217 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A class to emboss an image. */ public class EmbossFilter extends WholeImageFilter { private final static float pixelScale = 255.9f; private float azimuth = 135.0f * ImageMath.PI / 180.0f, elevation = 30.0f * ImageMath.PI / 180f; private boolean emboss = false; private float width45 = 3.0f; public EmbossFilter() { } public void setAzimuth(float azimuth) { this.azimuth = azimuth; } public float getAzimuth() { return azimuth; } public void setElevation(float elevation) { this.elevation = elevation; } public float getElevation() { return elevation; } public void setBumpHeight(float bumpHeight) { this.width45 = 3 * bumpHeight; } public float getBumpHeight() { return width45 / 3; } public void setEmboss(boolean emboss) { this.emboss = emboss; } public boolean getEmboss() { return emboss; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] outPixels = new int[width * height]; int[] bumpPixels; int bumpMapWidth, bumpMapHeight; bumpMapWidth = width; bumpMapHeight = height; bumpPixels = new int[bumpMapWidth * bumpMapHeight]; for (int i = 0; i < inPixels.length; i++) bumpPixels[i] = PixelUtils.brightness(inPixels[i]); int Nx, Ny, Nz, Lx, Ly, Lz, Nz2, NzLz, NdotL; int shade, background; Lx = (int)(Math.cos(azimuth) * Math.cos(elevation) * pixelScale); Ly = (int)(Math.sin(azimuth) * Math.cos(elevation) * pixelScale); Lz = (int)(Math.sin(elevation) * pixelScale); Nz = (int)(6 * 255 / width45); Nz2 = Nz * Nz; NzLz = Nz * Lz; background = Lz; int bumpIndex = 0; for (int y = 0; y < height; y++, bumpIndex += bumpMapWidth) { int s1 = bumpIndex; int s2 = s1 + bumpMapWidth; int s3 = s2 + bumpMapWidth; for (int x = 0; x < width; x++, s1++, s2++, s3++) { if (y != 0 && y < height-2 && x != 0 && x < width-2) { Nx = bumpPixels[s1-1] + bumpPixels[s2-1] + bumpPixels[s3-1] - bumpPixels[s1+1] - bumpPixels[s2+1] - bumpPixels[s3+1]; Ny = bumpPixels[s3-1] + bumpPixels[s3] + bumpPixels[s3+1] - bumpPixels[s1-1] - bumpPixels[s1] - bumpPixels[s1+1]; if (Nx == 0 && Ny == 0) shade = background; else if ((NdotL = Nx*Lx + Ny*Ly + NzLz) < 0) shade = 0; else shade = (int)(NdotL / Math.sqrt(Nx*Nx + Ny*Ny + Nz2)); } else shade = background; if (emboss) { int rgb = inPixels[index]; int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; r = (r*shade) >> 8; g = (g*shade) >> 8; b = (b*shade) >> 8; outPixels[index++] = a | (r << 16) | (g << 8) | b; } else outPixels[index++] = 0xff000000 | (shade << 16) | (shade << 8) | shade; } } return outPixels; } public String toString() { return "Stylize/Emboss..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ReduceNoiseFilter.java0000644000175000017500000000443210521402274023165 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter which performs reduces noise by looking at each pixel's 8 neighbours, and if it's a minimum or maximum, * replacing it by the next minimum or maximum of the neighbours. */ public class ReduceNoiseFilter extends WholeImageFilter { public ReduceNoiseFilter() { } private int smooth(int[] v) { int minindex = 0, maxindex = 0, min = Integer.MAX_VALUE, max = Integer.MIN_VALUE; for (int i = 0; i < 9; i++) { if ( i != 4 ) { if (v[i] < min) { min = v[i]; minindex = i; } if (v[i] > max) { max = v[i]; maxindex = i; } } } if ( v[4] < min ) return v[minindex]; if ( v[4] > max ) return v[maxindex]; return v[4]; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] r = new int[9]; int[] g = new int[9]; int[] b = new int[9]; int[] outPixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int k = 0; for (int dy = -1; dy <= 1; dy++) { int iy = y+dy; if (0 <= iy && iy < height) { int ioffset = iy*width; for (int dx = -1; dx <= 1; dx++) { int ix = x+dx; if (0 <= ix && ix < width) { int rgb = inPixels[ioffset+ix]; r[k] = (rgb >> 16) & 0xff; g[k] = (rgb >> 8) & 0xff; b[k] = rgb & 0xff; k++; } } } } while (k < 9) { r[k] = g[k] = b[k] = 0; k++; } outPixels[index] = (inPixels[index] & 0xff000000) | (smooth(r) << 16) | (smooth(g) << 8) | smooth(b); index++; } } return outPixels; } public String toString() { return "Blur/Smooth"; } } jhlabs-filters-2.0.235/com/jhlabs/image/NoiseFilter.java0000644000175000017500000000457710521402274022047 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import java.util.*; /** * A filter which adds random noise into an image. */ public class NoiseFilter extends PointFilter { public final static int GAUSSIAN = 0; public final static int UNIFORM = 1; private int amount = 25; private int distribution = UNIFORM; private boolean monochrome = false; private float density = 1; private Random randomNumbers = new Random(); public NoiseFilter() { } public void setAmount(int amount) { this.amount = amount; } public int getAmount() { return amount; } public void setDistribution( int distribution ) { this.distribution = distribution; } public int getDistribution() { return distribution; } public void setMonochrome(boolean monochrome) { this.monochrome = monochrome; } public boolean getMonochrome() { return monochrome; } public void setDensity( float density ) { this.density = density; } public float getDensity() { return density; } private int random(int x) { x += (int)(((distribution == GAUSSIAN ? randomNumbers.nextGaussian() : 2*randomNumbers.nextFloat() - 1)) * amount); if (x < 0) x = 0; else if (x > 0xff) x = 0xff; return x; } public int filterRGB(int x, int y, int rgb) { if ( randomNumbers.nextFloat() <= density ) { int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; if (monochrome) { int n = (int)(((distribution == GAUSSIAN ? randomNumbers.nextGaussian() : 2*randomNumbers.nextFloat() - 1)) * amount); r = PixelUtils.clamp(r+n); g = PixelUtils.clamp(g+n); b = PixelUtils.clamp(b+n); } else { r = random(r); g = random(g); b = random(b); } return a | (r << 16) | (g << 8) | b; } return rgb; } public String toString() { return "Stylize/Add Noise..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/JavaLnFFilter.java0000644000175000017500000000203310521402274022234 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter which produces the stipple effect for Swing icons specified in the Java Look and Feel Guidelines. */ public class JavaLnFFilter extends PointFilter { public JavaLnFFilter() { } public int filterRGB(int x, int y, int rgb) { if ((x & 1) == (y & 1)) return rgb; return ImageMath.mixColors(0.25f, 0xff999999, rgb); } public String toString() { return "Stylize/Java L&F Stipple"; } } jhlabs-filters-2.0.235/com/jhlabs/image/StampFilter.java0000644000175000017500000000432210521402274022042 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; public class StampFilter extends PointFilter { private float threshold; private float softness = 0; protected float radius = 5; private float lowerThreshold3; private float upperThreshold3; private int white = 0xffffffff; private int black = 0xff000000; public StampFilter() { this(0.5f); } public StampFilter( float threshold ) { setThreshold( threshold ); } public void setRadius(float radius) { this.radius = radius; } public float getRadius() { return radius; } public void setThreshold(float threshold) { this.threshold = threshold; } public float getThreshold() { return threshold; } public void setSoftness(float softness) { this.softness = softness; } public float getSoftness() { return softness; } public void setWhite(int white) { this.white = white; } public int getWhite() { return white; } public void setBlack(int black) { this.black = black; } public int getBlack() { return black; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { dst = new GaussianFilter( (int)radius ).filter( src, null ); lowerThreshold3 = 255*3*(threshold - softness*0.5f); upperThreshold3 = 255*3*(threshold + softness*0.5f); return super.filter(dst, dst); } public int filterRGB(int x, int y, int rgb) { int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; int l = r + g + b; float f = ImageMath.smoothStep(lowerThreshold3, upperThreshold3, l); return ImageMath.mixColors(f, black, white); } public String toString() { return "Stylize/Stamp..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/RippleFilter.java0000644000175000017500000000733710521402274022222 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import com.jhlabs.math.*; /** * A filter which distorts an image by rippling it in the X or Y directions. * The amplitude and wavelength of rippling can be specified as well as whether * pixels going off the edges are wrapped or not. */ public class RippleFilter extends TransformFilter { static final long serialVersionUID = 5101667633854087384L; public final static int SINE = 0; public final static int SAWTOOTH = 1; public final static int TRIANGLE = 2; public final static int NOISE = 3; public float xAmplitude, yAmplitude; public float xWavelength, yWavelength; private int waveType; /** * Construct a RIppleFIlter */ public RippleFilter() { xAmplitude = 5.0f; yAmplitude = 0.0f; xWavelength = yWavelength = 16.0f; } /** * Set the amplitude of ripple in the X direction. * @param xAmplitude the amplitude (in pixels). */ public void setXAmplitude(float xAmplitude) { this.xAmplitude = xAmplitude; } /** * Get the amplitude of ripple in the X direction. * @return the amplitude (in pixels). */ public float getXAmplitude() { return xAmplitude; } /** * Set the wavelength of ripple in the X direction. * @param xWavelength the wavelength (in pixels). */ public void setXWavelength(float xWavelength) { this.xWavelength = xWavelength; } /** * Get the wavelength of ripple in the X direction. * @return the wavelength (in pixels). */ public float getXWavelength() { return xWavelength; } /** * Set the amplitude of ripple in the Y direction. * @param yAmplitude the amplitude (in pixels). */ public void setYAmplitude(float yAmplitude) { this.yAmplitude = yAmplitude; } /** * Get the amplitude of ripple in the Y direction. * @return the amplitude (in pixels). */ public float getYAmplitude() { return yAmplitude; } /** * Set the wavelength of ripple in the Y direction. * @param yWavelength the wavelength (in pixels). */ public void setYWavelength(float yWavelength) { this.yWavelength = yWavelength; } /** * Get the wavelength of ripple in the Y direction. * @return the wavelength (in pixels). */ public float getYWavelength() { return yWavelength; } public void setWaveType(int waveType) { this.waveType = waveType; } public int getWaveType() { return waveType; } protected void transformSpace(Rectangle r) { if (edgeAction == ZERO) { r.x -= (int)xAmplitude; r.width += (int)(2*xAmplitude); r.y -= (int)yAmplitude; r.height += (int)(2*yAmplitude); } } protected void transformInverse(int x, int y, float[] out) { float nx = (float)y / xWavelength; float ny = (float)x / yWavelength; float fx, fy; switch (waveType) { case SINE: default: fx = (float)Math.sin(nx); fy = (float)Math.sin(ny); break; case SAWTOOTH: fx = ImageMath.mod(nx, 1); fy = ImageMath.mod(ny, 1); break; case TRIANGLE: fx = ImageMath.triangle(nx); fy = ImageMath.triangle(ny); break; case NOISE: fx = Noise.noise1(nx); fy = Noise.noise1(ny); break; } out[0] = x + xAmplitude * fx; out[1] = y + yAmplitude * fy; } public String toString() { return "Distort/Ripple..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/TransitionFilter.java0000644000175000017500000000722310521402274023113 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.lang.reflect.*; import java.beans.*; import java.util.*; /** * A filter which uses another filter to perform a transition. * e.g. to create a blur transition, you could write: new TransitionFilter( new BoxBlurFilter(), "radius", 0, 100 ); */ public class TransitionFilter extends AbstractBufferedImageOp { private float transition = 0; private BufferedImage destination; protected BufferedImageOp filter; private String property; private Method method; protected float minValue, maxValue; private TransitionFilter() { } public TransitionFilter( BufferedImageOp filter, String property, float minValue, float maxValue ) { this.filter = filter; this.property = property; this.minValue = minValue; this.maxValue = maxValue; try { BeanInfo info = Introspector.getBeanInfo( filter.getClass() ); PropertyDescriptor[] pds = info.getPropertyDescriptors(); for ( int i = 0; i < pds.length; i++ ) { PropertyDescriptor pd = pds[i]; if ( property.equals( pd.getName() ) ) { method = pd.getWriteMethod(); break; } } if ( method == null ) throw new IllegalArgumentException( "No such property in object: "+property ); } catch (IntrospectionException e) { throw new IllegalArgumentException( e.toString() ); } } /** * Set the transition of the image in the range 0..1. * *arg transition The transition */ public void setTransition( float transition ) { this.transition = transition; } public float getTransition() { return transition; } public void setDestination( BufferedImage destination ) { this.destination = destination; } public BufferedImage getDestination() { return destination; } /* public void setFilter( BufferedImageOp filter ) { this.filter = filter; } public int getFilter() { return filter; } */ public void prepareFilter( float transition ) { try { method.invoke( filter, new Object[] { new Float( transition ) } ); } catch ( Exception e ) { throw new IllegalArgumentException("Error setting value for property: "+property); } } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { if ( dst == null ) dst = createCompatibleDestImage( src, null ); if ( destination == null ) return dst; float itransition = 1-transition; Graphics2D g = dst.createGraphics(); if ( transition != 1 ) { float t = minValue + transition * ( maxValue-minValue ); prepareFilter( t ); g.drawImage( src, filter, 0, 0 ); } if ( transition != 0 ) { g.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, transition ) ); float t = minValue + itransition * ( maxValue-minValue ); prepareFilter( t ); g.drawImage( destination, filter, 0, 0 ); } g.dispose(); return dst; } public String toString() { return "Transitions/Transition..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/SkyFilter.java0000644000175000017500000002270210521402274021526 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.util.*; import com.jhlabs.math.*; public class SkyFilter extends PointFilter { private float scale = 0.1f; private float stretch = 1.0f; private float angle = 0.0f; private float amount = 1.0f; private float H = 1.0f; private float octaves = 8.0f; private float lacunarity = 2.0f; private float gain = 1.0f; private float bias = 0.6f; private int operation; private float min; private float max; private boolean ridged; private FBM fBm; protected Random random = new Random(); private Function2D basis; private float cloudCover = 0.5f; private float cloudSharpness = 0.5f; private float time = 0.3f; private float glow = 0.5f; private float glowFalloff = 0.5f; private float haziness = 0.96f; private float t = 0.0f; private float sunRadius = 10f; private int sunColor = 0xffffffff; private float sunR, sunG, sunB; private float sunAzimuth = 0.5f; private float sunElevation = 0.5f; private float windSpeed = 0.0f; private float cameraAzimuth = 0.0f; private float cameraElevation = 0.0f; private float fov = 1.0f; private float[] exponents; private float[] tan; private BufferedImage skyColors; private int[] skyPixels; private final static float r255 = 1.0f/255.0f; private float width, height; public SkyFilter() { if ( skyColors == null ) { skyColors = ImageUtils.createImage( Toolkit.getDefaultToolkit().getImage( getClass().getResource("SkyColors.png") ).getSource() ); } } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public void setOperation(int operation) { this.operation = operation; } public int getOperation() { return operation; } public void setScale(float scale) { this.scale = scale; } public float getScale() { return scale; } public void setStretch(float stretch) { this.stretch = stretch; } public float getStretch() { return stretch; } public void setT(float t) { this.t = t; } public float getT() { return t; } public void setFOV(float fov) { this.fov = fov; } public float getFOV() { return fov; } public void setCloudCover(float cloudCover) { this.cloudCover = cloudCover; } public float getCloudCover() { return cloudCover; } public void setCloudSharpness(float cloudSharpness) { this.cloudSharpness = cloudSharpness; } public float getCloudSharpness() { return cloudSharpness; } public void setTime(float time) { this.time = time; } public float getTime() { return time; } public void setGlow(float glow) { this.glow = glow; } public float getGlow() { return glow; } public void setGlowFalloff(float glowFalloff) { this.glowFalloff = glowFalloff; } public float getGlowFalloff() { return glowFalloff; } public void setAngle(float angle) { this.angle = angle; } public float getAngle() { return angle; } public void setOctaves(float octaves) { this.octaves = octaves; } public float getOctaves() { return octaves; } public void setH(float H) { this.H = H; } public float getH() { return H; } public void setLacunarity(float lacunarity) { this.lacunarity = lacunarity; } public float getLacunarity() { return lacunarity; } public void setGain(float gain) { this.gain = gain; } public float getGain() { return gain; } public void setBias(float bias) { this.bias = bias; } public float getBias() { return bias; } public void setHaziness(float haziness) { this.haziness = haziness; } public float getHaziness() { return haziness; } public void setSunElevation(float sunElevation) { this.sunElevation = sunElevation; } public float getSunElevation() { return sunElevation; } public void setSunAzimuth(float sunAzimuth) { this.sunAzimuth = sunAzimuth; } public float getSunAzimuth() { return sunAzimuth; } public void setSunColor(int sunColor) { this.sunColor = sunColor; } public int getSunColor() { return sunColor; } public void setCameraElevation(float cameraElevation) { this.cameraElevation = cameraElevation; } public float getCameraElevation() { return cameraElevation; } public void setCameraAzimuth(float cameraAzimuth) { this.cameraAzimuth = cameraAzimuth; } public float getCameraAzimuth() { return cameraAzimuth; } public void setWindSpeed(float windSpeed) { this.windSpeed = windSpeed; } public float getWindSpeed() { return windSpeed; } float mn, mx; public BufferedImage filter( BufferedImage src, BufferedImage dst ) { long start = System.currentTimeMillis(); sunR = (float)((sunColor >> 16) & 0xff) * r255; sunG = (float)((sunColor >> 8) & 0xff) * r255; sunB = (float)(sunColor & 0xff) * r255; mn = 10000; mx = -10000; exponents = new float[(int)octaves+1]; float frequency = 1.0f; for (int i = 0; i <= (int)octaves; i++) { exponents[i] = (float)Math.pow(2, -i); frequency *= lacunarity; } min = -1; max = 1; //min = -1.2f; //max = 1.2f; width = src.getWidth(); height = src.getHeight(); int h = src.getHeight(); tan = new float[h]; for (int i = 0; i < h; i++) tan[i] = (float)Math.tan( fov * (float)i/h * Math.PI * 0.5 ); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int t = (int)(63*time); // skyPixels = getRGB( skyColors, t, 0, 1, 64, skyPixels ); Graphics2D g = dst.createGraphics(); g.drawImage( skyColors, 0, 0, dst.getWidth(), dst.getHeight(), t, 0, t+1, 64, null ); g.dispose(); BufferedImage clouds = super.filter( dst, dst ); // g.drawRenderedImage( clouds, null ); // g.dispose(); long finish = System.currentTimeMillis(); System.out.println(mn+" "+mx+" "+(finish-start)*0.001f); exponents = null; tan = null; return dst; } public float evaluate(float x, float y) { float value = 0.0f; float remainder; int i; // to prevent "cascading" effects x += 371; y += 529; for (i = 0; i < (int)octaves; i++) { value += Noise.noise3(x, y, t) * exponents[i]; x *= lacunarity; y *= lacunarity; } remainder = octaves - (int)octaves; if (remainder != 0) value += remainder * Noise.noise3(x, y, t) * exponents[i]; return value; } public int filterRGB(int x, int y, int rgb) { // Curvature float fx = (float)x / width; //y += 20*Math.sin( fx*Math.PI*0.5 ); float fy = y / height; float haze = (float)Math.pow( haziness, 100*fy*fy ); // int argb = skyPixels[(int)fy]; float r = (float)((rgb >> 16) & 0xff) * r255; float g = (float)((rgb >> 8) & 0xff) * r255; float b = (float)(rgb & 0xff) * r255; float cx = width*0.5f; float nx = x-cx; float ny = y; // FOV //ny = (float)Math.tan( fov * fy * Math.PI * 0.5 ); ny = tan[y]; nx = (fx-0.5f) * (1+ny); ny += t*windSpeed;// Wind towards the camera // float xscale = scale/(1+y*bias*0.1f); nx /= scale; ny /= scale * stretch; float f = evaluate(nx, ny); float fg = f;//FIXME-bump map // Normalize to 0..1 // f = (f-min)/(max-min); f = (f+1.23f)/2.46f; // f *= amount; int a = rgb & 0xff000000; int v; // Work out cloud cover float c = f - cloudCover; if (c < 0) c = 0; float cloudAlpha = 1 - (float)Math.pow(cloudSharpness, c); //cloudAlpha *= amount; //if ( cloudAlpha > 1 ) // cloudAlpha = 1; mn = Math.min(mn, cloudAlpha); mx = Math.max(mx, cloudAlpha); // Sun glow float centreX = width*sunAzimuth; float centreY = height*sunElevation; float dx = x-centreX; float dy = y-centreY; float distance2 = dx*dx+dy*dy; // float sun = 0; //distance2 = (float)Math.sqrt(distance2); distance2 = (float)Math.pow(distance2, glowFalloff); float sun = /*amount**/10*(float)Math.exp(-distance2*glow*0.1f); // sun = glow*10*(float)Math.exp(-distance2); // Sun glow onto sky r += sun * sunR; g += sun * sunG; b += sun * sunB; // float cloudColor = cloudAlpha *sun; // Bump map /* float nnx = x-cx; float nny = y-1; nnx /= xscale; nny /= xscale * stretch; float gf = evaluate(nnx, nny); float gradient = fg-gf; if (y == 100)System.out.println(fg+" "+gf+gradient); cloudColor += amount * gradient; */ // ... /* r += (cloudColor-r) * cloudAlpha; g += (cloudColor-g) * cloudAlpha; b += (cloudColor-b) * cloudAlpha; */ // Clouds get darker as they get thicker float ca = (1-cloudAlpha*cloudAlpha*cloudAlpha*cloudAlpha) /** (1 + sun)*/ * amount; float cloudR = sunR * ca; float cloudG = sunG * ca; float cloudB = sunB * ca; // Apply the haziness as we move further away cloudAlpha *= haze; // Composite the clouds on the sky float iCloudAlpha = (1-cloudAlpha); r = iCloudAlpha*r + cloudAlpha*cloudR; g = iCloudAlpha*g + cloudAlpha*cloudG; b = iCloudAlpha*b + cloudAlpha*cloudB; // Exposure float exposure = gain; r = 1 - (float)Math.exp(-r * exposure); g = 1 - (float)Math.exp(-g * exposure); b = 1 - (float)Math.exp(-b * exposure); int ir = (int)(255*r) << 16; int ig = (int)(255*g) << 8; int ib = (int)(255*b); v = 0xff000000|ir|ig|ib; return v; } public String toString() { return "Texture/Sky..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/IteratedFilter.java0000644000175000017500000000205610521402274022521 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; public class IteratedFilter extends AbstractBufferedImageOp { private BufferedImageOp filter; private int iterations; public IteratedFilter( BufferedImageOp filter, int iterations ) { this.filter = filter; this.iterations = iterations; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { BufferedImage image = src; for ( int i = 0; i < iterations; i++ ) image = filter.filter( image, dst ); return image; } } jhlabs-filters-2.0.235/com/jhlabs/image/BlockFilter.java0000644000175000017500000000275610521402272022017 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A Filter to pixellate images. */ public class BlockFilter extends TransformFilter { static final long serialVersionUID = 8077109551486196569L; private int blockSize = 2; /** * Set the pixel block size * @param blockSize the number of pixels along each block edge */ public void setBlockSize(int blockSize) { this.blockSize = blockSize; } /** * Get the pixel block size * @return the number of pixels along each block edge */ public int getBlockSize() { return blockSize; } public BlockFilter() { } protected void transform(int x, int y, Point out) { out.x = (x / blockSize) * blockSize; out.y = (y / blockSize) * blockSize; } protected void transformInverse(int x, int y, float[] out) { out[0] = (x / blockSize) * blockSize; out[1] = (y / blockSize) * blockSize; } public String toString() { return "Stylize/Mosaic..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ThresholdFilter.java0000644000175000017500000000377510521402274022725 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; public class ThresholdFilter extends PointFilter implements java.io.Serializable { static final long serialVersionUID = -1899610620205446828L; private int lowerThreshold; private int lowerThreshold3; private int upperThreshold; private int upperThreshold3; private int white = 0xffffff; private int black = 0x000000; public ThresholdFilter() { this(127); } public ThresholdFilter(int t) { setLowerThreshold(t); setUpperThreshold(t); } public void setLowerThreshold(int lowerThreshold) { this.lowerThreshold = lowerThreshold; lowerThreshold3 = lowerThreshold*3; } public int getLowerThreshold() { return lowerThreshold; } public void setUpperThreshold(int upperThreshold) { this.upperThreshold = upperThreshold; upperThreshold3 = upperThreshold*3; } public int getUpperThreshold() { return upperThreshold; } public void setWhite(int white) { this.white = white; } public int getWhite() { return white; } public void setBlack(int black) { this.black = black; } public int getBlack() { return black; } public int filterRGB(int x, int y, int rgb) { int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; int l = r + g + b; if (l < lowerThreshold3) return a | black; else if (l > upperThreshold3) return a | white; return rgb; } public String toString() { return "Stylize/Threshold..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/FeedbackFilter.java0000644000175000017500000001021310521402272022434 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; public class FeedbackFilter extends AbstractBufferedImageOp { private float centreX = 0.5f, centreY = 0.5f; private float distance; private float angle; private float rotation; private float zoom; private float startAlpha = 1; private float endAlpha = 1; private int iterations; public FeedbackFilter() { } public FeedbackFilter( float distance, float angle, float rotation, float zoom ) { this.distance = distance; this.angle = angle; this.rotation = rotation; this.zoom = zoom; } public void setAngle( float angle ) { this.angle = angle; } public float getAngle() { return angle; } public void setDistance( float distance ) { this.distance = distance; } public float getDistance() { return distance; } public void setRotation( float rotation ) { this.rotation = rotation; } public float getRotation() { return rotation; } public void setZoom( float zoom ) { this.zoom = zoom; } public float getZoom() { return zoom; } public void setStartAlpha( float startAlpha ) { this.startAlpha = startAlpha; } public float getStartAlpha() { return startAlpha; } public void setEndAlpha( float endAlpha ) { this.endAlpha = endAlpha; } public float getEndAlpha() { return endAlpha; } public void setCentreX( float centreX ) { this.centreX = centreX; } public float getCentreX() { return centreX; } public void setCentreY( float centreY ) { this.centreY = centreY; } public float getCentreY() { return centreY; } public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } public void setIterations( int iterations ) { this.iterations = iterations; } public int getIterations() { return iterations; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { if ( dst == null ) dst = createCompatibleDestImage( src, null ); float cx = (float)src.getWidth() * centreX; float cy = (float)src.getHeight() * centreY; float imageRadius = (float)Math.sqrt( cx*cx + cy*cy ); float translateX = (float)(distance * Math.cos( angle )); float translateY = (float)(distance * -Math.sin( angle )); float scale = (float)Math.exp(zoom); float rotate = rotation; if ( iterations == 0 ) { Graphics2D g = dst.createGraphics(); g.drawRenderedImage( src, null ); g.dispose(); return dst; } Graphics2D g = dst.createGraphics(); g.drawImage( src, null, null ); for ( int i = 0; i < iterations; i++ ) { g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR ); g.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, ImageMath.lerp( (float)i/(iterations-1), startAlpha, endAlpha ) ) ); g.translate( cx+translateX, cy+translateY ); g.scale( scale, scale ); // The .0001 works round a bug on Windows where drawImage throws an ArrayIndexOutofBoundException if ( rotation != 0 ) g.rotate( rotate ); g.translate( -cx, -cy ); g.drawImage( src, null, null ); } g.dispose(); return dst; } public String toString() { return "Effects/Feedback..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/Gradient.java0000644000175000017500000002304010521402274021343 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.Color; import java.util.Vector; import java.io.*; /** * A Colormap implemented using Catmull-Rom colour splines. The map has a variable number * of knots with a minimum of four. The first and last knots give the tangent at the end * of the spline, and colours are interpolated from the second to the second-last knots. * Each knot can be given a type of interpolation. These are: * */ public class Gradient extends ArrayColormap implements Cloneable, Serializable { static final long serialVersionUID = 1479681703781917357L; // Color types public final static int RGB = 0x00; public final static int HUE_CW = 0x01; public final static int HUE_CCW = 0x02; // Blending functions public final static int LINEAR = 0x10; public final static int SPLINE = 0x20; public final static int CIRCLE_UP = 0x30; public final static int CIRCLE_DOWN = 0x40; public final static int CONSTANT = 0x50; private final static int COLOR_MASK = 0x03; private final static int BLEND_MASK = 0x70; public int numKnots = 4; public int[] xKnots = { -1, 0, 255, 256 }; public int[] yKnots = { 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, }; public byte[] knotTypes = { RGB|SPLINE, RGB|SPLINE, RGB|SPLINE, RGB|SPLINE }; public Gradient() { rebuildGradient(); } public Gradient(int[] rgb) { this(null, rgb, null); } public Gradient(int[] x, int[] rgb) { this(x, rgb, null); } public Gradient(int[] x, int[] rgb, byte[] types) { setKnots(x, rgb, types); } public Object clone() { Gradient g = (Gradient)super.clone(); g.map = (int[])map.clone(); g.xKnots = (int[])xKnots.clone(); g.yKnots = (int[])yKnots.clone(); g.knotTypes = (byte[])knotTypes.clone(); return g; } public void copyTo(Gradient g) { g.numKnots = numKnots; g.map = (int[])map.clone(); g.xKnots = (int[])xKnots.clone(); g.yKnots = (int[])yKnots.clone(); g.knotTypes = (byte[])knotTypes.clone(); } public void setColor(int n, int color) { int firstColor = map[0]; int lastColor = map[256-1]; if (n > 0) for (int i = 0; i < n; i++) map[i] = ImageMath.mixColors((float)i/n, firstColor, color); if (n < 256-1) for (int i = n; i < 256; i++) map[i] = ImageMath.mixColors((float)(i-n)/(256-n), color, lastColor); } public int getKnot(int n) { return yKnots[n]; } public void setKnot(int n, int color) { yKnots[n] = color; rebuildGradient(); } public void setKnotType(int n, int type) { knotTypes[n] = (byte)((knotTypes[n] & ~COLOR_MASK) | type); rebuildGradient(); } public int getKnotType(int n) { return (byte)(knotTypes[n] & COLOR_MASK); } public void setKnotBlend(int n, int type) { knotTypes[n] = (byte)((knotTypes[n] & ~BLEND_MASK) | type); rebuildGradient(); } public byte getKnotBlend(int n) { return (byte)(knotTypes[n] & BLEND_MASK); } public void addKnot(int x, int color, int type) { int[] nx = new int[numKnots+1]; int[] ny = new int[numKnots+1]; byte[] nt = new byte[numKnots+1]; System.arraycopy(xKnots, 0, nx, 0, numKnots); System.arraycopy(yKnots, 0, ny, 0, numKnots); System.arraycopy(knotTypes, 0, nt, 0, numKnots); xKnots = nx; yKnots = ny; knotTypes = nt; // Insert one position before the end so the sort works correctly xKnots[numKnots] = xKnots[numKnots-1]; yKnots[numKnots] = yKnots[numKnots-1]; knotTypes[numKnots] = knotTypes[numKnots-1]; xKnots[numKnots-1] = x; yKnots[numKnots-1] = color; knotTypes[numKnots-1] = (byte)type; numKnots++; sortKnots(); rebuildGradient(); } public void removeKnot(int n) { if (numKnots <= 4) return; if (n < numKnots-1) { System.arraycopy(xKnots, n+1, xKnots, n, numKnots-n-1); System.arraycopy(yKnots, n+1, yKnots, n, numKnots-n-1); System.arraycopy(knotTypes, n+1, knotTypes, n, numKnots-n-1); } numKnots--; if (xKnots[1] > 0) xKnots[1] = 0; rebuildGradient(); } // This version does not require the "extra" knots at -1 and 256 public void setKnots(int[] x, int[] rgb, byte[] types) { numKnots = rgb.length+2; xKnots = new int[numKnots]; yKnots = new int[numKnots]; knotTypes = new byte[numKnots]; if (x != null) System.arraycopy(x, 0, xKnots, 1, numKnots-2); else for (int i = 1; i > numKnots-1; i++) xKnots[i] = 255*i/(numKnots-2); System.arraycopy(rgb, 0, yKnots, 1, numKnots-2); if (types != null) System.arraycopy(types, 0, knotTypes, 1, numKnots-2); else for (int i = 0; i > numKnots; i++) knotTypes[i] = RGB|SPLINE; sortKnots(); rebuildGradient(); } public void setKnots(int[] x, int[] y, byte[] types, int offset, int count) { numKnots = count; xKnots = new int[numKnots]; yKnots = new int[numKnots]; knotTypes = new byte[numKnots]; System.arraycopy(x, offset, xKnots, 0, numKnots); System.arraycopy(y, offset, yKnots, 0, numKnots); System.arraycopy(types, offset, knotTypes, 0, numKnots); sortKnots(); rebuildGradient(); } public void splitSpan(int n) { int x = (xKnots[n] + xKnots[n+1])/2; addKnot(x, getColor(x/256.0f), knotTypes[n]); rebuildGradient(); } public void setKnotPosition(int n, int x) { xKnots[n] = ImageMath.clamp(x, 0, 255); sortKnots(); rebuildGradient(); } public int knotAt(int x) { for (int i = 1; i < numKnots-1; i++) if (xKnots[i+1] > x) return i; return 1; } private void rebuildGradient() { xKnots[0] = -1; xKnots[numKnots-1] = 256; yKnots[0] = yKnots[1]; yKnots[numKnots-1] = yKnots[numKnots-2]; int knot = 0; for (int i = 1; i < numKnots-1; i++) { float spanLength = xKnots[i+1]-xKnots[i]; int end = xKnots[i+1]; if (i == numKnots-2) end++; for (int j = xKnots[i]; j < end; j++) { int rgb1 = yKnots[i]; int rgb2 = yKnots[i+1]; float hsb1[] = Color.RGBtoHSB((rgb1 >> 16) & 0xff, (rgb1 >> 8) & 0xff, rgb1 & 0xff, null); float hsb2[] = Color.RGBtoHSB((rgb2 >> 16) & 0xff, (rgb2 >> 8) & 0xff, rgb2 & 0xff, null); float t = (float)(j-xKnots[i])/spanLength; int type = getKnotType(i); int blend = getKnotBlend(i); if (j >= 0 && j <= 255) { switch (blend) { case CONSTANT: t = 0; break; case LINEAR: break; case SPLINE: // map[i] = ImageMath.colorSpline(j, numKnots, xKnots, yKnots); t = ImageMath.smoothStep(0.15f, 0.85f, t); break; case CIRCLE_UP: t = t-1; t = (float)Math.sqrt(1-t*t); break; case CIRCLE_DOWN: t = 1-(float)Math.sqrt(1-t*t); break; } // if (blend != SPLINE) { switch (type) { case RGB: map[j] = ImageMath.mixColors(t, rgb1, rgb2); break; case HUE_CW: case HUE_CCW: if (type == HUE_CW) { if (hsb2[0] <= hsb1[0]) hsb2[0] += 1.0f; } else { if (hsb1[0] <= hsb2[1]) hsb1[0] += 1.0f; } float h = ImageMath.lerp(t, hsb1[0], hsb2[0]) % (ImageMath.TWO_PI); float s = ImageMath.lerp(t, hsb1[1], hsb2[1]); float b = ImageMath.lerp(t, hsb1[2], hsb2[2]); map[j] = 0xff000000 | Color.HSBtoRGB((float)h, (float)s, (float)b);//FIXME-alpha break; } // } } } } } private void sortKnots() { for (int i = 1; i < numKnots-1; i++) { for (int j = 1; j < i; j++) { if (xKnots[i] < xKnots[j]) { int t = xKnots[i]; xKnots[i] = xKnots[j]; xKnots[j] = t; t = yKnots[i]; yKnots[i] = yKnots[j]; yKnots[j] = t; byte bt = knotTypes[i]; knotTypes[i] = knotTypes[j]; knotTypes[j] = bt; } } } } public void rebuild() { sortKnots(); rebuildGradient(); } public void randomize() { numKnots = 4 + (int)(6*Math.random()); xKnots = new int[numKnots]; yKnots = new int[numKnots]; knotTypes = new byte[numKnots]; for (int i = 0; i < numKnots; i++) { xKnots[i] = (int)(255 * Math.random()); yKnots[i] = 0xff000000 | ((int)(255 * Math.random()) << 16) | ((int)(255 * Math.random()) << 8) | (int)(255 * Math.random()); knotTypes[i] = RGB|SPLINE; } xKnots[0] = -1; xKnots[1] = 0; xKnots[numKnots-2] = 255; xKnots[numKnots-1] = 256; sortKnots(); rebuildGradient(); } public void mutate(float amount) { for (int i = 0; i < numKnots; i++) { // xKnots[i] = (int)(255 * Math.random()); int rgb = yKnots[i]; int r = ((rgb >> 16) & 0xff); int g = ((rgb >> 8) & 0xff); int b = (rgb & 0xff); r = PixelUtils.clamp( (int)(r + amount * 255 * (Math.random()-0.5)) ); g = PixelUtils.clamp( (int)(g + amount * 255 * (Math.random()-0.5)) ); b = PixelUtils.clamp( (int)(b + amount * 255 * (Math.random()-0.5)) ); yKnots[i] = 0xff000000 | (r << 16) | (g << 8) | b; knotTypes[i] = RGB|SPLINE; } sortKnots(); rebuildGradient(); } public static Gradient randomGradient() { Gradient g = new Gradient(); g.randomize(); return g; } } jhlabs-filters-2.0.235/com/jhlabs/image/CausticsFilter.java0000644000175000017500000001404210521402272022532 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.util.*; import com.jhlabs.math.*; /** * A filter which simulates underwater caustics. This can be animated to get a bottom-of-the-swimming-pool effect. */ public class CausticsFilter extends WholeImageFilter { private float scale = 32; private float angle = 0.0f; public int brightness = 10; public float amount = 1.0f; public float turbulence = 1.0f; public float dispersion = 0.0f; public float time = 0.0f; private int samples = 2; private int bgColor = 0xff799fff; private float s, c; public CausticsFilter() { } public void setScale(float scale) { this.scale = scale; } public float getScale() { return scale; } public void setBrightness(int brightness) { this.brightness = brightness; } public int getBrightness() { return brightness; } public void setTurbulence(float turbulence) { this.turbulence = turbulence; } public float getTurbulence() { return turbulence; } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public void setDispersion(float dispersion) { this.dispersion = dispersion; } public float getDispersion() { return dispersion; } public void setTime(float time) { this.time = time; } public float getTime() { return time; } public void setSamples(int samples) { this.samples = samples; } public int getSamples() { return samples; } public void setBgColor(int c) { bgColor = c; } public int getBgColor() { return bgColor; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { Random random = new Random(0); s = (float)Math.sin(0.1); c = (float)Math.cos(0.1); int srcWidth = originalSpace.width; int srcHeight = originalSpace.height; int outWidth = transformedSpace.width; int outHeight = transformedSpace.height; int index = 0; int[] pixels = new int[outWidth * outHeight]; for (int y = 0; y < outHeight; y++) { for (int x = 0; x < outWidth; x++) { pixels[index++] = bgColor; } } int v = brightness/samples; if (v == 0) v = 1; float rs = 1.0f/scale; float d = 0.95f; index = 0; for (int y = 0; y < outHeight; y++) { for (int x = 0; x < outWidth; x++) { for (int s = 0; s < samples; s++) { float sx = x+random.nextFloat(); float sy = y+random.nextFloat(); float nx = sx*rs; float ny = sy*rs; float xDisplacement, yDisplacement; float focus = 0.1f+amount; xDisplacement = evaluate(nx-d, ny) - evaluate(nx+d, ny); yDisplacement = evaluate(nx, ny+d) - evaluate(nx, ny-d); if (dispersion > 0) { for (int c = 0; c < 3; c++) { float ca = (1+c*dispersion); float srcX = sx + scale*focus * xDisplacement*ca; float srcY = sy + scale*focus * yDisplacement*ca; if (srcX < 0 || srcX >= outWidth-1 || srcY < 0 || srcY >= outHeight-1) { } else { int i = ((int)srcY)*outWidth+(int)srcX; int rgb = pixels[i]; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; if (c == 2) r += v; else if (c == 1) g += v; else b += v; if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; pixels[i] = 0xff000000 | (r << 16) | (g << 8) | b; } } } else { float srcX = sx + scale*focus * xDisplacement; float srcY = sy + scale*focus * yDisplacement; if (srcX < 0 || srcX >= outWidth-1 || srcY < 0 || srcY >= outHeight-1) { } else { int i = ((int)srcY)*outWidth+(int)srcX; int rgb = pixels[i]; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; r += v; g += v; b += v; if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; pixels[i] = 0xff000000 | (r << 16) | (g << 8) | b; } } } } } return pixels; } private static int add(int rgb, float brightness) { int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; r += brightness; g += brightness; b += brightness; if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; return 0xff000000 | (r << 16) | (g << 8) | b; } private static int add(int rgb, float brightness, int c) { int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; if (c == 2) r += brightness; else if (c == 1) g += brightness; else b += brightness; if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; return 0xff000000 | (r << 16) | (g << 8) | b; } public static float turbulence2(float x, float y, float time, float octaves) { float value = 0.0f; float remainder; float lacunarity = 2.0f; float f = 1.0f; int i; // to prevent "cascading" effects x += 371; y += 529; for (i = 0; i < (int)octaves; i++) { value += Noise.noise3(x, y, time) / f; x *= lacunarity; y *= lacunarity; f *= 2; } remainder = octaves - (int)octaves; if (remainder != 0) value += remainder * Noise.noise3(x, y, time) / f; return value; } protected float evaluate(float x, float y) { float xt = s*x + c*time; float tt = c*x - c*time; float f = turbulence == 0.0 ? Noise.noise3(xt, y, tt) : turbulence2(xt, y, tt, turbulence); return f; } public String toString() { return "Texture/Caustics..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/TileImageFilter.java0000644000175000017500000000457010521402274022623 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class TileImageFilter extends AbstractBufferedImageOp implements java.io.Serializable { static final long serialVersionUID = 4926390225069192478L; public static final int FLIP_NONE = 0; public static final int FLIP_H = 1; public static final int FLIP_V = 2; public static final int FLIP_HV = 3; public static final int FLIP_180 = 4; private int width; private int height; private int tileWidth; private int tileHeight; public TileImageFilter() { this(32, 32); } public TileImageFilter(int width, int height) { this.width = width; this.height = height; } public void setWidth(int width) { this.width = width; } public int getWidth() { return width; } public void setHeight(int height) { this.height = height; } public int getHeight() { return height; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int tileWidth = src.getWidth(); int tileHeight = src.getHeight(); if ( dst == null ) { ColorModel dstCM = src.getColorModel(); dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(width, height), dstCM.isAlphaPremultiplied(), null); } Graphics2D g = dst.createGraphics(); for ( int y = 0; y < height; y += tileHeight) { for ( int x = 0; x < width; x += tileWidth ) { g.drawImage( src, null, x, y ); } } g.dispose(); return dst; } private int[][] symmetryMatrix = null; private int symmetryRows = 2, symmetryCols = 2; public void setSymmetryMatrix(int[][] symmetryMatrix) { this.symmetryMatrix = symmetryMatrix; symmetryRows = symmetryMatrix.length; symmetryCols = symmetryMatrix[0].length; } public int[][] getSymmetryMatrix() { return symmetryMatrix; } public String toString() { return "Tile"; } } jhlabs-filters-2.0.235/com/jhlabs/image/LensBlurFilter.java0000644000175000017500000002216210521402274022506 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.awt.color.*; import com.jhlabs.math.*; /** * A filter which use FFTs to simulate lens blur on an image */ public class LensBlurFilter extends AbstractBufferedImageOp { private float radius = 10; private float bloom = 2; private float bloomThreshold = 192; private float angle = 0; private int sides = 5; /** * Set the radius of the kernel, and hence the amount of blur. * @param radius the radius of the blur in pixels. */ public void setRadius(float radius) { this.radius = radius; } /** * Get the radius of the kernel. * @return the radius */ public float getRadius() { return radius; } public void setSides(int sides) { this.sides = sides; } public int getSides() { return sides; } public void setBloom(float bloom) { this.bloom = bloom; } public float getBloom() { return bloom; } public void setBloomThreshold(float bloomThreshold) { this.bloomThreshold = bloomThreshold; } public float getBloomThreshold() { return bloomThreshold; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int rows = 1, cols = 1; int log2rows = 0, log2cols = 0; int iradius = (int)Math.ceil(radius); int tileWidth = 128; int tileHeight = tileWidth; int adjustedWidth = (int)(width + iradius*2); int adjustedHeight = (int)(height + iradius*2); tileWidth = iradius < 32 ? Math.min(128, width+2*iradius) : Math.min(256, width+2*iradius); tileHeight = iradius < 32 ? Math.min(128, height+2*iradius) : Math.min(256, height+2*iradius); if ( dst == null ) dst = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); while (rows < tileHeight) { rows *= 2; log2rows++; } while (cols < tileWidth) { cols *= 2; log2cols++; } int w = cols; int h = rows; tileWidth = w; tileHeight = h;//FIXME-tileWidth, w, and cols are always all the same FFT fft = new FFT( Math.max(log2rows, log2cols) ); int[] rgb = new int[w*h]; float[][] mask = new float[2][w*h]; float[][] gb = new float[2][w*h]; float[][] ar = new float[2][w*h]; // Create the kernel double polyAngle = Math.PI/sides; double polyScale = 1.0f / Math.cos(polyAngle); double r2 = radius*radius; double rangle = Math.toRadians(angle); float total = 0; int i = 0; for ( int y = 0; y < h; y++ ) { for ( int x = 0; x < w; x++ ) { double dx = x-w/2f; double dy = y-h/2f; double r = dx*dx+dy*dy; double f = r < r2 ? 1 : 0; if (f != 0) { r = Math.sqrt(r); if ( sides != 0 ) { double a = Math.atan2(dy, dx)+rangle; a = ImageMath.mod(a, polyAngle*2)-polyAngle; f = Math.cos(a) * polyScale; } else f = 1; f = f*r < radius ? 1 : 0; } total += (float)f; mask[0][i] = (float)f; mask[1][i] = 0; i++; } } // Normalize the kernel i = 0; for ( int y = 0; y < h; y++ ) { for ( int x = 0; x < w; x++ ) { mask[0][i] /= total; i++; } } fft.transform2D( mask[0], mask[1], w, h, true ); for ( int tileY = -iradius; tileY < height; tileY += tileHeight-2*iradius ) { for ( int tileX = -iradius; tileX < width; tileX += tileWidth-2*iradius ) { // System.out.println("Tile: "+tileX+" "+tileY+" "+tileWidth+" "+tileHeight); // Clip the tile to the image bounds int tx = tileX, ty = tileY, tw = tileWidth, th = tileHeight; int fx = 0, fy = 0; if ( tx < 0 ) { tw += tx; fx -= tx; tx = 0; } if ( ty < 0 ) { th += ty; fy -= ty; ty = 0; } if ( tx+tw > width ) tw = width-tx; if ( ty+th > height ) th = height-ty; src.getRGB( tx, ty, tw, th, rgb, fy*w+fx, w ); // Create a float array from the pixels. Any pixels off the edge of the source image get duplicated from the edge. i = 0; for ( int y = 0; y < h; y++ ) { int imageY = y+tileY; int j; if ( imageY < 0 ) j = fy; else if ( imageY > height ) j = fy+th-1; else j = y; j *= w; for ( int x = 0; x < w; x++ ) { int imageX = x+tileX; int k; if ( imageX < 0 ) k = fx; else if ( imageX > width ) k = fx+tw-1; else k = x; k += j; ar[0][i] = ((rgb[k] >> 24) & 0xff); float r = ((rgb[k] >> 16) & 0xff); float g = ((rgb[k] >> 8) & 0xff); float b = (rgb[k] & 0xff); // Bloom... if ( r > bloomThreshold ) r *= bloom; // r = bloomThreshold + (r-bloomThreshold) * bloom; if ( g > bloomThreshold ) g *= bloom; // g = bloomThreshold + (g-bloomThreshold) * bloom; if ( b > bloomThreshold ) b *= bloom; // b = bloomThreshold + (b-bloomThreshold) * bloom; ar[1][i] = r; gb[0][i] = g; gb[1][i] = b; i++; k++; } } // Transform into frequency space fft.transform2D( ar[0], ar[1], cols, rows, true ); fft.transform2D( gb[0], gb[1], cols, rows, true ); // Multiply the transformed pixels by the transformed kernel i = 0; for ( int y = 0; y < h; y++ ) { for ( int x = 0; x < w; x++ ) { float re = ar[0][i]; float im = ar[1][i]; float rem = mask[0][i]; float imm = mask[1][i]; ar[0][i] = re*rem-im*imm; ar[1][i] = re*imm+im*rem; re = gb[0][i]; im = gb[1][i]; gb[0][i] = re*rem-im*imm; gb[1][i] = re*imm+im*rem; i++; } } // Transform back fft.transform2D( ar[0], ar[1], cols, rows, false ); fft.transform2D( gb[0], gb[1], cols, rows, false ); // Convert back to RGB pixels, with quadrant remapping int row_flip = w >> 1; int col_flip = h >> 1; int index = 0; //FIXME-don't bother converting pixels off image edges for ( int y = 0; y < w; y++ ) { int ym = y ^ row_flip; int yi = ym*cols; for ( int x = 0; x < w; x++ ) { int xm = yi + (x ^ col_flip); int a = (int)ar[0][xm]; int r = (int)ar[1][xm]; int g = (int)gb[0][xm]; int b = (int)gb[1][xm]; // Clamp high pixels due to blooming if ( r > 255 ) r = 255; if ( g > 255 ) g = 255; if ( b > 255 ) b = 255; int argb = (a << 24) | (r << 16) | (g << 8) | b; rgb[index++] = argb; } } // Clip to the output image tx = tileX+iradius; ty = tileY+iradius; tw = tileWidth-2*iradius; th = tileHeight-2*iradius; if ( tx+tw > width ) tw = width-tx; if ( ty+th > height ) th = height-ty; dst.setRGB( tx, ty, tw, th, rgb, iradius*w+iradius, w ); } } return dst; } public String toString() { return "Blur/Lens Blur..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/LevelsFilter.java0000644000175000017500000000552110521402274022212 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter which allows levels adjustment on an image. */ public class LevelsFilter extends WholeImageFilter { protected int[][] lut; protected float lowLevel = 0; protected float highLevel = 1; protected float lowOutputLevel = 0; protected float highOutputLevel = 1; public LevelsFilter() { } public void setLowLevel( float lowLevel ) { this.lowLevel = lowLevel; } public float getLowLevel() { return lowLevel; } public void setHighLevel( float highLevel ) { this.highLevel = highLevel; } public float getHighLevel() { return highLevel; } public void setLowOutputLevel( float lowOutputLevel ) { this.lowOutputLevel = lowOutputLevel; } public float getLowOutputLevel() { return lowOutputLevel; } public void setHighOutputLevel( float highOutputLevel ) { this.highOutputLevel = highOutputLevel; } public float getHighOutputLevel() { return highOutputLevel; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { Histogram histogram = new Histogram(inPixels, width, height, 0, width); int i, j; if (histogram.getNumSamples() > 0) { float scale = 255.0f / histogram.getNumSamples(); lut = new int[3][256]; float low = lowLevel * 255; float high = highLevel * 255; if ( low == high ) high++; for (i = 0; i < 3; i++) { for (j = 0; j < 256; j++) lut[i][j] = PixelUtils.clamp( (int)(255 * (lowOutputLevel + (highOutputLevel-lowOutputLevel) * (j-low)/(high-low))) ); } } else lut = null; i = 0; for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { inPixels[i] = filterRGB(x, y, inPixels[i]); i++; } lut = null; return inPixels; } public int filterRGB(int x, int y, int rgb) { if (lut != null) { int a = rgb & 0xff000000; int r = lut[Histogram.RED][(rgb >> 16) & 0xff]; int g = lut[Histogram.GREEN][(rgb >> 8) & 0xff]; int b = lut[Histogram.BLUE][rgb & 0xff]; return a | (r << 16) | (g << 8) | b; } return rgb; } public String toString() { return "Colors/Levels..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/PosterizeFilter.java0000644000175000017500000000304110521402274022737 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class PosterizeFilter extends PointFilter implements java.io.Serializable { private int numLevels; private int[] levels; private boolean initialized = false; public PosterizeFilter() { setNumLevels(6); } public void setNumLevels(int numLevels) { this.numLevels = numLevels; initialized = false; } public int getNumLevels() { return numLevels; } protected void initialize() { levels = new int[256]; if (numLevels != 1) for (int i = 0; i < 256; i++) levels[i] = 255 * (numLevels*i / 256) / (numLevels-1); } public int filterRGB(int x, int y, int rgb) { if (!initialized) { initialized = true; initialize(); } int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; r = levels[r]; g = levels[g]; b = levels[b]; return a | (r << 16) | (g << 8) | b; } public String toString() { return "Colors/Posterize..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ImageMath.java0000644000175000017500000004054410521402274021452 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; /** * A class containing static math methods useful for image processing. */ public class ImageMath { public final static float PI = (float)Math.PI; public final static float HALF_PI = (float)Math.PI/2.0f; public final static float QUARTER_PI = (float)Math.PI/4.0f; public final static float TWO_PI = (float)Math.PI*2.0f; /** * Apply a bias to a number in the unit interval, moving numbers towards 0 or 1 * according to the bias parameter. * @param a the number to bias * @param b the bias parameter. 0.5 means no change, smaller values bias towards 0, larger towards 1. * @return the output value */ public static float bias(float a, float b) { // return (float)Math.pow(a, Math.log(b) / Math.log(0.5)); return a/((1.0f/b-2)*(1.0f-a)+1); } /** * A variant of the gamma function. * @param a the number to apply gain to * @param b the gain parameter. 0.5 means no change, smaller values reduce gain, larger values increase gain. * @return the output value */ public static float gain(float a, float b) { /* float p = (float)Math.log(1.0 - b) / (float)Math.log(0.5); if (a < .001) return 0.0f; else if (a > .999) return 1.0f; if (a < 0.5) return (float)Math.pow(2 * a, p) / 2; else return 1.0f - (float)Math.pow(2 * (1. - a), p) / 2; */ float c = (1.0f/b-2.0f) * (1.0f-2.0f*a); if (a < 0.5) return a/(c+1.0f); else return (c-a)/(c-1.0f); } /** * The step function. Returns 0 below a threshold, 1 above. * @param a the threshold position * @param x the input parameter * @return the output value - 0 or 1 */ public static float step(float a, float x) { return (x < a) ? 0.0f : 1.0f; } /** * The pulse function. Returns 1 between two thresholds, 0 outside. * @param a the lower threshold position * @param b the upper threshold position * @param x the input parameter * @return the output value - 0 or 1 */ public static float pulse(float a, float b, float x) { return (x < a || x >= b) ? 0.0f : 1.0f; } /** * A smoothed pulse function. A cubic function is used to smooth the step between two thresholds. * @param a1 the lower threshold position for the start of the pulse * @param a2 the upper threshold position for the start of the pulse * @param b1 the lower threshold position for the end of the pulse * @param b2 the upper threshold position for the end of the pulse * @param x the input parameter * @return the output value */ public static float smoothPulse(float a1, float a2, float b1, float b2, float x) { if (x < a1 || x >= b2) return 0; if (x >= a2) { if (x < b1) return 1.0f; x = (x - b1) / (b2 - b1); return 1.0f - (x*x * (3.0f - 2.0f*x)); } x = (x - a1) / (a2 - a1); return x*x * (3.0f - 2.0f*x); } /** * A smoothed step function. A cubic function is used to smooth the step between two thresholds. * @param a the lower threshold position * @param b the upper threshold position * @param x the input parameter * @return the output value */ public static float smoothStep(float a, float b, float x) { if (x < a) return 0; if (x >= b) return 1; x = (x - a) / (b - a); return x*x * (3 - 2*x); } /** * A "circle up" function. Returns y on a unit circle given 1-x. Useful for forming bevels. * @param x the input parameter in the range 0..1 * @return the output value */ public static float circleUp(float x) { x = 1-x; return (float)Math.sqrt(1-x*x); } /** * A "circle down" function. Returns 1-y on a unit circle given x. Useful for forming bevels. * @param x the input parameter in the range 0..1 * @return the output value */ public static float circleDown(float x) { return 1.0f-(float)Math.sqrt(1-x*x); } /** * Clamp a value to an interval. * @param a the lower clamp threshold * @param b the upper clamp threshold * @param x the input parameter * @return the clamped value */ public static float clamp(float x, float a, float b) { return (x < a) ? a : (x > b) ? b : x; } /** * Clamp a value to an interval. * @param a the lower clamp threshold * @param b the upper clamp threshold * @param x the input parameter * @return the clamped value */ public static int clamp(int x, int a, int b) { return (x < a) ? a : (x > b) ? b : x; } /** * Return a mod b. This differs from the % operator with respect to negative numbers. * @param a the dividend * @param b the divisor * @return a mod b */ public static double mod(double a, double b) { int n = (int)(a/b); a -= n*b; if (a < 0) return a + b; return a; } /** * Return a mod b. This differs from the % operator with respect to negative numbers. * @param a the dividend * @param b the divisor * @return a mod b */ public static float mod(float a, float b) { int n = (int)(a/b); a -= n*b; if (a < 0) return a + b; return a; } /** * Return a mod b. This differs from the % operator with respect to negative numbers. * @param a the dividend * @param b the divisor * @return a mod b */ public static int mod(int a, int b) { int n = a/b; a -= n*b; if (a < 0) return a + b; return a; } /** * The triangle function. Returns a repeating triangle shape in the range 0..1 with wavelength 1.0 * @param x the input parameter * @return the output value */ public static float triangle(float x) { float r = mod(x, 1.0f); return 2.0f*(r < 0.5 ? r : 1-r); } /** * Linear interpolation. * @param t the interpolation parameter * @param a the lower interpolation range * @param b the upper interpolation range * @return the interpolated value */ public static float lerp(float t, float a, float b) { return a + t * (b - a); } /** * Linear interpolation. * @param t the interpolation parameter * @param a the lower interpolation range * @param b the upper interpolation range * @return the interpolated value */ public static int lerp(float t, int a, int b) { return (int)(a + t * (b - a)); } /** * Linear interpolation of ARGB values. * @param t the interpolation parameter * @param rgb1 the lower interpolation range * @param rgb2 the upper interpolation range * @return the interpolated value */ public static int mixColors(float t, int rgb1, int rgb2) { int a1 = (rgb1 >> 24) & 0xff; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; int a2 = (rgb2 >> 24) & 0xff; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; a1 = lerp(t, a1, a2); r1 = lerp(t, r1, r2); g1 = lerp(t, g1, g2); b1 = lerp(t, b1, b2); return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; } /** * Bilinear interpolation of ARGB values. * @param x the X interpolation parameter 0..1 * @param y the y interpolation parameter 0..1 * @param rgb array of four ARGB values in the order NW, NE, SW, SE * @return the interpolated value */ public static int bilinearInterpolate(float x, float y, int nw, int ne, int sw, int se) { float m0, m1; int a0 = (nw >> 24) & 0xff; int r0 = (nw >> 16) & 0xff; int g0 = (nw >> 8) & 0xff; int b0 = nw & 0xff; int a1 = (ne >> 24) & 0xff; int r1 = (ne >> 16) & 0xff; int g1 = (ne >> 8) & 0xff; int b1 = ne & 0xff; int a2 = (sw >> 24) & 0xff; int r2 = (sw >> 16) & 0xff; int g2 = (sw >> 8) & 0xff; int b2 = sw & 0xff; int a3 = (se >> 24) & 0xff; int r3 = (se >> 16) & 0xff; int g3 = (se >> 8) & 0xff; int b3 = se & 0xff; float cx = 1.0f-x; float cy = 1.0f-y; m0 = cx * a0 + x * a1; m1 = cx * a2 + x * a3; int a = (int)(cy * m0 + y * m1); m0 = cx * r0 + x * r1; m1 = cx * r2 + x * r3; int r = (int)(cy * m0 + y * m1); m0 = cx * g0 + x * g1; m1 = cx * g2 + x * g3; int g = (int)(cy * m0 + y * m1); m0 = cx * b0 + x * b1; m1 = cx * b2 + x * b3; int b = (int)(cy * m0 + y * m1); return (a << 24) | (r << 16) | (g << 8) | b; } /** * Return the NTSC gray level of an RGB value. * @param rgb1 the input pixel * @return the gray level (0-255) */ public static int brightnessNTSC(int rgb) { int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; return (int)(r*0.299f + g*0.587f + b*0.114f); } // Catmull-Rom splines private final static float m00 = -0.5f; private final static float m01 = 1.5f; private final static float m02 = -1.5f; private final static float m03 = 0.5f; private final static float m10 = 1.0f; private final static float m11 = -2.5f; private final static float m12 = 2.0f; private final static float m13 = -0.5f; private final static float m20 = -0.5f; private final static float m21 = 0.0f; private final static float m22 = 0.5f; private final static float m23 = 0.0f; private final static float m30 = 0.0f; private final static float m31 = 1.0f; private final static float m32 = 0.0f; private final static float m33 = 0.0f; /** * Compute a Catmull-Rom spline. * @param x the input parameter * @param numKnots the number of knots in the spline * @param knots the array of knots * @return the spline value */ public static float spline(float x, int numKnots, float[] knots) { int span; int numSpans = numKnots - 3; float k0, k1, k2, k3; float c0, c1, c2, c3; if (numSpans < 1) throw new IllegalArgumentException("Too few knots in spline"); x = clamp(x, 0, 1) * numSpans; span = (int)x; if (span > numKnots-4) span = numKnots-4; x -= span; k0 = knots[span]; k1 = knots[span+1]; k2 = knots[span+2]; k3 = knots[span+3]; c3 = m00*k0 + m01*k1 + m02*k2 + m03*k3; c2 = m10*k0 + m11*k1 + m12*k2 + m13*k3; c1 = m20*k0 + m21*k1 + m22*k2 + m23*k3; c0 = m30*k0 + m31*k1 + m32*k2 + m33*k3; return ((c3*x + c2)*x + c1)*x + c0; } /** * Compute a Catmull-Rom spline, but with variable knot spacing. * @param x the input parameter * @param numKnots the number of knots in the spline * @param xknots the array of knot x values * @param yknots the array of knot y values * @return the spline value */ public static float spline(float x, int numKnots, int[] xknots, int[] yknots) { int span; int numSpans = numKnots - 3; float k0, k1, k2, k3; float c0, c1, c2, c3; if (numSpans < 1) throw new IllegalArgumentException("Too few knots in spline"); for (span = 0; span < numSpans; span++) if (xknots[span+1] > x) break; if (span > numKnots-3) span = numKnots-3; float t = (float)(x-xknots[span]) / (xknots[span+1]-xknots[span]); span--; if (span < 0) { span = 0; t = 0; } k0 = yknots[span]; k1 = yknots[span+1]; k2 = yknots[span+2]; k3 = yknots[span+3]; c3 = m00*k0 + m01*k1 + m02*k2 + m03*k3; c2 = m10*k0 + m11*k1 + m12*k2 + m13*k3; c1 = m20*k0 + m21*k1 + m22*k2 + m23*k3; c0 = m30*k0 + m31*k1 + m32*k2 + m33*k3; return ((c3*t + c2)*t + c1)*t + c0; } /** * Compute a Catmull-Rom spline for RGB values. * @param x the input parameter * @param numKnots the number of knots in the spline * @param knots the array of knots * @return the spline value */ public static int colorSpline(float x, int numKnots, int[] knots) { int span; int numSpans = numKnots - 3; float k0, k1, k2, k3; float c0, c1, c2, c3; if (numSpans < 1) throw new IllegalArgumentException("Too few knots in spline"); x = clamp(x, 0, 1) * numSpans; span = (int)x; if (span > numKnots-4) span = numKnots-4; x -= span; int v = 0; for (int i = 0; i < 4; i++) { int shift = i * 8; k0 = (knots[span] >> shift) & 0xff; k1 = (knots[span+1] >> shift) & 0xff; k2 = (knots[span+2] >> shift) & 0xff; k3 = (knots[span+3] >> shift) & 0xff; c3 = m00*k0 + m01*k1 + m02*k2 + m03*k3; c2 = m10*k0 + m11*k1 + m12*k2 + m13*k3; c1 = m20*k0 + m21*k1 + m22*k2 + m23*k3; c0 = m30*k0 + m31*k1 + m32*k2 + m33*k3; int n = (int)(((c3*x + c2)*x + c1)*x + c0); if (n < 0) n = 0; else if (n > 255) n = 255; v |= n << shift; } return v; } /** * Compute a Catmull-Rom spline for RGB values, but with variable knot spacing. * @param x the input parameter * @param numKnots the number of knots in the spline * @param xknots the array of knot x values * @param yknots the array of knot y values * @return the spline value */ public static int colorSpline(int x, int numKnots, int[] xknots, int[] yknots) { int span; int numSpans = numKnots - 3; float k0, k1, k2, k3; float c0, c1, c2, c3; if (numSpans < 1) throw new IllegalArgumentException("Too few knots in spline"); for (span = 0; span < numSpans; span++) if (xknots[span+1] > x) break; if (span > numKnots-3) span = numKnots-3; float t = (float)(x-xknots[span]) / (xknots[span+1]-xknots[span]); span--; if (span < 0) { span = 0; t = 0; } int v = 0; for (int i = 0; i < 4; i++) { int shift = i * 8; k0 = (yknots[span] >> shift) & 0xff; k1 = (yknots[span+1] >> shift) & 0xff; k2 = (yknots[span+2] >> shift) & 0xff; k3 = (yknots[span+3] >> shift) & 0xff; c3 = m00*k0 + m01*k1 + m02*k2 + m03*k3; c2 = m10*k0 + m11*k1 + m12*k2 + m13*k3; c1 = m20*k0 + m21*k1 + m22*k2 + m23*k3; c0 = m30*k0 + m31*k1 + m32*k2 + m33*k3; int n = (int)(((c3*t + c2)*t + c1)*t + c0); if (n < 0) n = 0; else if (n > 255) n = 255; v |= n << shift; } return v; } /** * An implementation of Fant's resampling algorithm. * @param source the source pixels * @param dest the destination pixels * @param length the length of the scanline to resample * @param offset the start offset into the arrays * @param stride the offset between pixels in consecutive rows * @param out an array of output positions for each pixel */ public static void resample(int[] source, int[] dest, int length, int offset, int stride, float[] out) { int i, j; float intensity; float sizfac; float inSegment; float outSegment; int a, r, g, b, nextA, nextR, nextG, nextB; float aSum, rSum, gSum, bSum; float[] in; int srcIndex = offset; int destIndex = offset; int lastIndex = source.length; int rgb; in = new float[length+2]; i = 0; for (j = 0; j < length; j++) { while (out[i+1] < j) i++; in[j] = i + (float) (j - out[i]) / (out[i + 1] - out[i]); // in[j] = ImageMath.clamp( in[j], 0, length-1 ); } in[length] = length; in[length+1] = length; inSegment = 1.0f; outSegment = in[1]; sizfac = outSegment; aSum = rSum = gSum = bSum = 0.0f; rgb = source[srcIndex]; a = (rgb >> 24) & 0xff; r = (rgb >> 16) & 0xff; g = (rgb >> 8) & 0xff; b = rgb & 0xff; srcIndex += stride; rgb = source[srcIndex]; nextA = (rgb >> 24) & 0xff; nextR = (rgb >> 16) & 0xff; nextG = (rgb >> 8) & 0xff; nextB = rgb & 0xff; srcIndex += stride; i = 1; while (i <= length) { float aIntensity = inSegment * a + (1.0f - inSegment) * nextA; float rIntensity = inSegment * r + (1.0f - inSegment) * nextR; float gIntensity = inSegment * g + (1.0f - inSegment) * nextG; float bIntensity = inSegment * b + (1.0f - inSegment) * nextB; if (inSegment < outSegment) { aSum += (aIntensity * inSegment); rSum += (rIntensity * inSegment); gSum += (gIntensity * inSegment); bSum += (bIntensity * inSegment); outSegment -= inSegment; inSegment = 1.0f; a = nextA; r = nextR; g = nextG; b = nextB; if (srcIndex < lastIndex) rgb = source[srcIndex]; nextA = (rgb >> 24) & 0xff; nextR = (rgb >> 16) & 0xff; nextG = (rgb >> 8) & 0xff; nextB = rgb & 0xff; srcIndex += stride; } else { aSum += (aIntensity * outSegment); rSum += (rIntensity * outSegment); gSum += (gIntensity * outSegment); bSum += (bIntensity * outSegment); dest[destIndex] = ((int)Math.min(aSum/sizfac, 255) << 24) | ((int)Math.min(rSum/sizfac, 255) << 16) | ((int)Math.min(gSum/sizfac, 255) << 8) | (int)Math.min(bSum/sizfac, 255); destIndex += stride; aSum = rSum = gSum = bSum = 0.0f; inSegment -= outSegment; outSegment = in[i+1] - in[i]; sizfac = outSegment; i++; } } } } jhlabs-filters-2.0.235/com/jhlabs/image/ShatterFilter.java0000644000175000017500000001365110521402274022375 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.util.*; public class ShatterFilter extends AbstractBufferedImageOp { private float centreX = 0.5f, centreY = 0.5f; private float distance; private float transition; private float rotation; private float zoom; private float startAlpha = 1; private float endAlpha = 1; private int iterations = 5; private int tile; public ShatterFilter() { } public void setTransition( float transition ) { this.transition = transition; } public float getTransition() { return transition; } public void setDistance( float distance ) { this.distance = distance; } public float getDistance() { return distance; } public void setRotation( float rotation ) { this.rotation = rotation; } public float getRotation() { return rotation; } public void setZoom( float zoom ) { this.zoom = zoom; } public float getZoom() { return zoom; } public void setStartAlpha( float startAlpha ) { this.startAlpha = startAlpha; } public float getStartAlpha() { return startAlpha; } public void setEndAlpha( float endAlpha ) { this.endAlpha = endAlpha; } public float getEndAlpha() { return endAlpha; } public void setCentreX( float centreX ) { this.centreX = centreX; } public float getCentreX() { return centreX; } public void setCentreY( float centreY ) { this.centreY = centreY; } public float getCentreY() { return centreY; } public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } public void setIterations( int iterations ) { this.iterations = iterations; } public int getIterations() { return iterations; } public void setTile( int tile ) { this.tile = tile; } public int getTile() { return tile; } static class Tile { float x, y, vx, vy, w, h; float rotation; Shape shape; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { if ( dst == null ) dst = createCompatibleDestImage( src, null ); float width = (float)src.getWidth(); float height = (float)src.getHeight(); float cx = (float)src.getWidth() * centreX; float cy = (float)src.getHeight() * centreY; float imageRadius = (float)Math.sqrt( cx*cx + cy*cy ); // BufferedImage[] tiles = new BufferedImage[iterations]; int numTiles = iterations*iterations; Tile[] shapes = new Tile[numTiles]; float[] rx = new float[numTiles]; float[] ry = new float[numTiles]; float[] rz = new float[numTiles]; Graphics2D g = dst.createGraphics(); // g.drawImage( src, null, null ); Random random = new Random( 0 ); float lastx = 0, lasty = 0; /* for ( int i = 0; i <= numTiles; i++ ) { double angle = (double)i * 2*Math.PI / numTiles; float x = cx + width*(float)Math.cos(angle); float y = cy + height*(float)Math.sin(angle); g.setColor( Color.black ); g.setColor( Color.getHSBColor( (float)angle, 1, 1 ) ); if ( i != 0 ) { rz[i-1] = tile*(2*random.nextFloat()-1); ry[i-1] = tile*random.nextFloat(); rz[i-1] = tile*random.nextFloat(); GeneralPath p = new GeneralPath(); p.moveTo( cx, cy ); p.lineTo( lastx, lasty ); p.lineTo( x, y ); p.closePath(); shapes[i-1] = p; // Rectangle r = p.getBounds(); // r.intersect( r, new Rectangle( (int)width, (int)height ), r ); } lastx = x; lasty = y; } */ for ( int y = 0; y < iterations; y++ ) { int y1 = (int)height*y/iterations; int y2 = (int)height*(y+1)/iterations; for ( int x = 0; x < iterations; x++ ) { int i = y*iterations+x; int x1 = (int)width*x/iterations; int x2 = (int)width*(x+1)/iterations; rx[i] = tile*random.nextFloat(); ry[i] = tile*random.nextFloat(); rx[i] = 0; ry[i] = 0; rz[i] = tile*(2*random.nextFloat()-1); Shape p = new Rectangle( x1, y1, x2-x1, y2-y1 ); shapes[i] = new Tile(); shapes[i].shape = p; shapes[i].x = (x1+x2)*0.5f; shapes[i].y = (y1+y2)*0.5f; shapes[i].vx = width-(cx-x); shapes[i].vy = height-(cy-y); shapes[i].w = x2-x1; shapes[i].h = y2-y1; } } for ( int i = 0; i < numTiles; i++ ) { float h = (float)i / numTiles; double angle = h * 2*Math.PI; float x = transition * width*(float)Math.cos(angle); float y = transition * height*(float)Math.sin(angle); Tile tile = shapes[i]; Rectangle r = tile.shape.getBounds(); AffineTransform t = g.getTransform(); x = tile.x + transition * tile.vx; y = tile.y + transition * tile.vy; g.translate( x, y ); // g.translate( tile.w*0.5f, tile.h*0.5f ); g.rotate( transition * rz[i] ); // g.scale( (float)Math.cos( transition * rx[i] ), (float)Math.cos( transition * ry[i] ) ); // g.translate( -tile.w*0.5f, -tile.h*0.5f ); g.setColor( Color.getHSBColor( h, 1, 1 ) ); Shape clip = g.getClip(); g.clip( tile.shape ); g.drawImage( src, 0, 0, null ); g.setClip( clip ); g.setTransform( t ); } g.dispose(); return dst; } public String toString() { return "Transition/Shatter..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/MedianFilter.java0000644000175000017500000000476410521402274022165 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter which performs a 3x3 median operation. Useful for removing dust and noise. */ public class MedianFilter extends WholeImageFilter { public MedianFilter() { } private int median(int[] array) { int max, maxIndex; for (int i = 0; i < 4; i++) { max = 0; maxIndex = 0; for (int j = 0; j < 9; j++) { if (array[j] > max) { max = array[j]; maxIndex = j; } } array[maxIndex] = 0; } max = 0; for (int i = 0; i < 9; i++) { if (array[i] > max) max = array[i]; } return max; } private int rgbMedian(int[] r, int[] g, int[] b) { int sum, index = 0, min = Integer.MAX_VALUE; for (int i = 0; i < 9; i++) { sum = 0; for (int j = 0; j < 9; j++) { sum += Math.abs(r[i]-r[j]); sum += Math.abs(g[i]-g[j]); sum += Math.abs(b[i]-b[j]); } if (sum < min) { min = sum; index = i; } } return index; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] argb = new int[9]; int[] r = new int[9]; int[] g = new int[9]; int[] b = new int[9]; int[] outPixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int k = 0; for (int dy = -1; dy <= 1; dy++) { int iy = y+dy; if (0 <= iy && iy < height) { int ioffset = iy*width; for (int dx = -1; dx <= 1; dx++) { int ix = x+dx; if (0 <= ix && ix < width) { int rgb = inPixels[ioffset+ix]; argb[k] = rgb; r[k] = (rgb >> 16) & 0xff; g[k] = (rgb >> 8) & 0xff; b[k] = rgb & 0xff; k++; } } } } while (k < 9) { argb[k] = 0xff000000; r[k] = g[k] = b[k] = 0; k++; } outPixels[index++] = argb[rgbMedian(r, g, b)]; } } return outPixels; } public String toString() { return "Blur/Median"; } } jhlabs-filters-2.0.235/com/jhlabs/image/MaximumFilter.java0000644000175000017500000000266710521402274022405 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class MaximumFilter extends WholeImageFilter { public MaximumFilter() { } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] outPixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixel = 0xff000000; for (int dy = -1; dy <= 1; dy++) { int iy = y+dy; int ioffset; if (0 <= iy && iy < height) { ioffset = iy*width; for (int dx = -1; dx <= 1; dx++) { int ix = x+dx; if (0 <= ix && ix < width) { pixel = PixelUtils.combinePixels(pixel, inPixels[ioffset+ix], PixelUtils.MAX); } } } } outPixels[index++] = pixel; } } return outPixels; } public String toString() { return "Blur/Maximum"; } } jhlabs-filters-2.0.235/com/jhlabs/image/MaskFilter.java0000644000175000017500000000230110521402274021644 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.io.*; /** * Applies a bit mask to each ARGB pixel of an image. You can use this for, say, masking out the red channel. */ public class MaskFilter extends PointFilter implements Serializable { private int mask; public MaskFilter() { this(0xff00ffff); } public MaskFilter(int mask) { canFilterIndexColorModel = true; setMask(mask); } public void setMask(int mask) { this.mask = mask; } public int getMask() { return mask; } public int filterRGB(int x, int y, int rgb) { return rgb & mask; } public String toString() { return "Mask"; } } jhlabs-filters-2.0.235/com/jhlabs/image/FadeFilter.java0000644000175000017500000000543010521402272021614 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.io.*; public class FadeFilter extends PointFilter { private int width, height; private float angle = 0.0f; private float fadeStart = 1.0f; private float fadeWidth = 10.0f; private int sides; private boolean invert; private float m00 = 1.0f; private float m01 = 0.0f; private float m10 = 0.0f; private float m11 = 1.0f; public void setAngle(float angle) { this.angle = angle; float cos = (float)Math.cos(angle); float sin = (float)Math.sin(angle); m00 = cos; m01 = sin; m10 = -sin; m11 = cos; } public float getAngle() { return angle; } public void setSides(int sides) { this.sides = sides; } public int getSides() { return sides; } public void setFadeStart(float fadeStart) { this.fadeStart = fadeStart; } public float getFadeStart() { return fadeStart; } public void setFadeWidth(float fadeWidth) { this.fadeWidth = fadeWidth; } public float getFadeWidth() { return fadeWidth; } public void setInvert(boolean invert) { this.invert = invert; } public boolean getInvert() { return invert; } public void setDimensions(int width, int height) { this.width = width; this.height = height; super.setDimensions(width, height); } public int filterRGB(int x, int y, int rgb) { float nx = m00*x + m01*y; float ny = m10*x + m11*y; if (sides == 2) nx = (float)Math.sqrt(nx*nx + ny*ny); else if (sides == 3) nx = ImageMath.mod(nx, 16); else if (sides == 4) nx = symmetry(nx, 16); int alpha = (int)(ImageMath.smoothStep(fadeStart, fadeStart+fadeWidth, nx) * 255); if (invert) alpha = 255-alpha; return (alpha << 24) | (rgb & 0x00ffffff); } public float symmetry(float x, float b) { /* int d = (int)(x / b); x = ImageMath.mod(x, b); if ((d & 1) == 1) return b-x; return x; */ x = ImageMath.mod(x, 2*b); if (x > b) return 2*b-x; return x; } /* public float star(float x, float y, int sides, float rMin, float rMax) { float sideAngle = 2*Math.PI / sides; float angle = Math.atan2(y, x); float r = Math.sqrt(x*x + y*y); float t = ImageMath.mod(angle, sideAngle) / sideAngle; if (t > 0.5) t = 1.0-t; } */ public String toString() { return "Fade..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/SpectrumColormap.java0000644000175000017500000000201510521402274023104 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; /** * A colormap with the colors of the spectrum. */ public class SpectrumColormap implements Colormap, java.io.Serializable { /** * Construct a spcetrum color map */ public SpectrumColormap() { } /** * Convert a value in the range 0..1 to an RGB color. * @param v a value in the range 0..1 * @return an RGB color */ public int getColor(float v) { return Spectrum.wavelengthToRGB(380+400*ImageMath.clamp(v, 0, 1.0f)); } } jhlabs-filters-2.0.235/com/jhlabs/image/ContourFilter.java0000644000175000017500000000565410521402272022416 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class ContourFilter extends WholeImageFilter { private float levels = 5; private float scale = 1; private float offset = 0; private int contourColor = 0xff000000; public ContourFilter() { } public void setLevels( float levels ) { this.levels = levels; } public float getLevels() { return levels; } public void setScale( float scale ) { this.scale = scale; } public float getScale() { return scale; } public void setOffset( float offset ) { this.offset = offset; } public float getOffset() { return offset; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; short[][] r = new short[3][width]; int[] outPixels = new int[width * height]; short[] table = new short[256]; int offsetl = (int)(offset * 256 / levels); for ( int i = 0; i < 256; i++ ) table[i] = (short)PixelUtils.clamp( (int)(255 * Math.floor(levels*(i+offsetl) / 256) / (levels-1) - offsetl) ); for (int x = 0; x < width; x++) { int rgb = inPixels[x]; r[1][x] = (short)PixelUtils.brightness( rgb ); } for (int y = 0; y < height; y++) { boolean yIn = y > 0 && y < height-1; int nextRowIndex = index+width; if ( y < height-1) { for (int x = 0; x < width; x++) { int rgb = inPixels[nextRowIndex++]; r[2][x] = (short)PixelUtils.brightness( rgb ); } } for (int x = 0; x < width; x++) { boolean xIn = x > 0 && x < width-1; int w = x-1; int e = x+1; int v = 0; if ( yIn && xIn ) { short nwb = r[0][w]; short neb = r[0][x]; short swb = r[1][w]; short seb = r[1][x]; short nw = table[nwb]; short ne = table[neb]; short sw = table[swb]; short se = table[seb]; if (nw != ne || nw != sw || ne != se || sw != se) { v = (int)(scale * (Math.abs(nwb - neb) + Math.abs(nwb - swb) + Math.abs(neb - seb) + Math.abs(swb - seb))); // v /= 255; if (v > 255) v = 255; } } if ( v != 0 ) outPixels[index] = PixelUtils.combinePixels( inPixels[index], contourColor, PixelUtils.NORMAL, v ); else outPixels[index] = inPixels[index]; index++; } short[] t; t = r[0]; r[0] = r[1]; r[1] = r[2]; r[2] = t; } return outPixels; } public String toString() { return "Stylize/Contour..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ExposureFilter.java0000644000175000017500000000201210521402272022560 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class ExposureFilter extends TransferFilter { private float exposure = 1.0f; protected float transferFunction( float f ) { return 1 - (float)Math.exp(-f * exposure); } public void setExposure(float exposure) { this.exposure = exposure; initialized = false; } public float getExposure() { return exposure; } public String toString() { return "Colors/Exposure..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/OctTreeQuantizer.java0000644000175000017500000001476110521402274023070 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.util.*; import java.io.*; import java.awt.*; import java.awt.image.*; /** * An image Quantizer based on the Octree algorithm. This is a very basic implementation * at present and could be much improved by picking the nodes to reduce more carefully * (i.e. not completely at random) when I get the time. */ public class OctTreeQuantizer implements Quantizer { /** * The greatest depth the tree is allowed to reach */ final static int MAX_LEVEL = 5; /** * An Octtree node. */ class OctTreeNode { int children; int level; OctTreeNode parent; OctTreeNode leaf[] = new OctTreeNode[8]; boolean isLeaf; int count; int totalRed; int totalGreen; int totalBlue; int index; /** * A debugging method which prints the tree out. */ public void list(PrintStream s, int level) { for (int i = 0; i < level; i++) System.out.print(' '); if (count == 0) System.out.println(index+": count="+count); else System.out.println(index+": count="+count+" red="+(totalRed/count)+" green="+(totalGreen/count)+" blue="+(totalBlue/count)); for (int i = 0; i < 8; i++) if (leaf[i] != null) leaf[i].list(s, level+2); } } private int nodes = 0; private OctTreeNode root; private int reduceColors; private int maximumColors; private int colors = 0; private Vector[] colorList; public OctTreeQuantizer() { setup(256); colorList = new Vector[MAX_LEVEL+1]; for (int i = 0; i < MAX_LEVEL+1; i++) colorList[i] = new Vector(); root = new OctTreeNode(); } /** * Initialize the quantizer. This should be called before adding any pixels. * @param numColors the number of colors we're quantizing to. */ public void setup(int numColors) { maximumColors = numColors; reduceColors = Math.max(512, numColors * 2); } /** * Add pixels to the quantizer. * @param pixels the array of ARGB pixels * @param offset the offset into the array * @param count the count of pixels */ public void addPixels(int[] pixels, int offset, int count) { for (int i = 0; i < count; i++) { insertColor(pixels[i+offset]); if (colors > reduceColors) reduceTree(reduceColors); } } public int getIndexForColor(int rgb) { int red = (rgb >> 16) & 0xff; int green = (rgb >> 8) & 0xff; int blue = rgb & 0xff; OctTreeNode node = root; for (int level = 0; level <= MAX_LEVEL; level++) { OctTreeNode child; int bit = 0x80 >> level; int index = 0; if ((red & bit) != 0) index += 4; if ((green & bit) != 0) index += 2; if ((blue & bit) != 0) index += 1; child = node.leaf[index]; if (child == null) return node.index; else if (child.isLeaf) return child.index; else node = child; } System.out.println("getIndexForColor failed"); return 0; } private void insertColor(int rgb) { int red = (rgb >> 16) & 0xff; int green = (rgb >> 8) & 0xff; int blue = rgb & 0xff; OctTreeNode node = root; // System.out.println("insertColor="+Integer.toHexString(rgb)); for (int level = 0; level <= MAX_LEVEL; level++) { OctTreeNode child; int bit = 0x80 >> level; int index = 0; if ((red & bit) != 0) index += 4; if ((green & bit) != 0) index += 2; if ((blue & bit) != 0) index += 1; child = node.leaf[index]; if (child == null) { node.children++; child = new OctTreeNode(); child.parent = node; node.leaf[index] = child; node.isLeaf = false; nodes++; colorList[level].addElement(child); if (level == MAX_LEVEL) { child.isLeaf = true; child.count = 1; child.totalRed = red; child.totalGreen = green; child.totalBlue = blue; child.level = level; colors++; return; } node = child; } else if (child.isLeaf) { child.count++; child.totalRed += red; child.totalGreen += green; child.totalBlue += blue; return; } else node = child; } System.out.println("insertColor failed"); } private void reduceTree(int numColors) { for (int level = MAX_LEVEL-1; level >= 0; level--) { Vector v = colorList[level]; if (v != null && v.size() > 0) { for (int j = 0; j < v.size(); j++) { OctTreeNode node = (OctTreeNode)v.elementAt(j); if (node.children > 0) { for (int i = 0; i < 8; i++) { OctTreeNode child = node.leaf[i]; if (child != null) { if (!child.isLeaf) System.out.println("not a leaf!"); node.count += child.count; node.totalRed += child.totalRed; node.totalGreen += child.totalGreen; node.totalBlue += child.totalBlue; node.leaf[i] = null; node.children--; colors--; nodes--; colorList[level+1].removeElement(child); } } node.isLeaf = true; colors++; if (colors <= numColors) return; } } } } System.out.println("Unable to reduce the OctTree"); } public int[] buildColorTable() { int[] table = new int[colors]; buildColorTable(root, table, 0); return table; } /** * A quick way to use the quantizer. Just create a table the right size and pass in the pixels. */ public void buildColorTable(int[] inPixels, int[] table) { int count = inPixels.length; maximumColors = table.length; for (int i = 0; i < count; i++) { insertColor(inPixels[i]); if (colors > reduceColors) reduceTree(reduceColors); } if (colors > maximumColors) reduceTree(maximumColors); buildColorTable(root, table, 0); } private int buildColorTable(OctTreeNode node, int[] table, int index) { if (colors > maximumColors) reduceTree(maximumColors); if (node.isLeaf) { int count = node.count; table[index] = 0xff000000 | ((node.totalRed/count) << 16) | ((node.totalGreen/count) << 8) | node.totalBlue/count; node.index = index++; } else { for (int i = 0; i < 8; i++) { if (node.leaf[i] != null) { node.index = index; index = buildColorTable(node.leaf[i], table, index); } } } return index; } } jhlabs-filters-2.0.235/com/jhlabs/image/OutlineFilter.java0000644000175000017500000000345410521402274022402 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * Given a binary image, this filter converts it to its outline, replacing all interior pixels with the 'new' color. */ public class OutlineFilter extends BinaryFilter { public OutlineFilter() { newColor = 0xffffffff; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] outPixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixel = inPixels[y*width+x]; if (blackFunction.isBlack(pixel)) { int neighbours = 0; for (int dy = -1; dy <= 1; dy++) { int iy = y+dy; int ioffset; if (0 <= iy && iy < height) { ioffset = iy*width; for (int dx = -1; dx <= 1; dx++) { int ix = x+dx; if (!(dy == 0 && dx == 0) && 0 <= ix && ix < width) { int rgb = inPixels[ioffset+ix]; if (blackFunction.isBlack(rgb)) neighbours++; } else neighbours++; } } } if (neighbours == 9) pixel = newColor; } outPixels[index++] = pixel; } } return outPixels; } public String toString() { return "Binary/Outline..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/OffsetFilter.java0000644000175000017500000000367510521402274022216 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class OffsetFilter extends TransformFilter implements java.io.Serializable { private int width, height; private int xOffset, yOffset; private boolean wrap; public OffsetFilter() { this(0, 0, true); } public OffsetFilter(int xOffset, int yOffset, boolean wrap) { this.xOffset = xOffset; this.yOffset = yOffset; this.wrap = wrap; setEdgeAction( ZERO ); } public void setXOffset(int xOffset) { this.xOffset = xOffset; } public int getXOffset() { return xOffset; } public void setYOffset(int yOffset) { this.yOffset = yOffset; } public int getYOffset() { return yOffset; } public void setWrap(boolean wrap) { this.wrap = wrap; } public boolean getWrap() { return wrap; } protected void transformInverse(int x, int y, float[] out) { if ( wrap ) { out[0] = (x+width-xOffset) % width; out[1] = (y+height-yOffset) % height; } else { out[0] = x-xOffset; out[1] = y-yOffset; } } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { this.width = src.getWidth(); this.height = src.getHeight(); if ( wrap ) { while (xOffset < 0) xOffset += width; while (yOffset < 0) yOffset += height; xOffset %= width; yOffset %= height; } return super.filter( src, dst ); } public String toString() { return "Distort/Offset..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ErodeFilter.java0000644000175000017500000000470610521402272022020 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * Given a binary image, this filter performs binary erosion, setting all removed pixels to the given 'new' color. */ public class ErodeFilter extends BinaryFilter { protected int threshold = 2; public ErodeFilter() { newColor = 0xffffffff; } /** * Set the threshold - the number of neighbouring pixels for dilation to occur. * @param threshold the new threshold */ public void setThreshold(int threshold) { this.threshold = threshold; } /** * Return the threshold - the number of neighbouring pixels for dilation to occur. * @return the current threshold */ public int getThreshold() { return threshold; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int[] outPixels = new int[width * height]; for (int i = 0; i < iterations; i++) { int index = 0; if (i > 0) { int[] t = inPixels; inPixels = outPixels; outPixels = t; } for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixel = inPixels[y*width+x]; if (blackFunction.isBlack(pixel)) { int neighbours = 0; for (int dy = -1; dy <= 1; dy++) { int iy = y+dy; int ioffset; if (0 <= iy && iy < height) { ioffset = iy*width; for (int dx = -1; dx <= 1; dx++) { int ix = x+dx; if (!(dy == 0 && dx == 0) && 0 <= ix && ix < width) { int rgb = inPixels[ioffset+ix]; if (!blackFunction.isBlack(rgb)) neighbours++; } } } } if (neighbours >= threshold) { if (colormap != null) pixel = colormap.getColor((float)i/iterations); else pixel = newColor; } } outPixels[index++] = pixel; } } } return outPixels; } public String toString() { return "Binary/Erode..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/TextureFilter.java0000644000175000017500000000602510521402274022420 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import com.jhlabs.math.*; public class TextureFilter extends PointFilter implements java.io.Serializable { static final long serialVersionUID = -7538331862272404352L; private float scale = 32; private float stretch = 1.0f; private float angle = 0.0f; public float amount = 1.0f; public float turbulence = 1.0f; public float gain = 0.5f; public float bias = 0.5f; public int operation; private float m00 = 1.0f; private float m01 = 0.0f; private float m10 = 0.0f; private float m11 = 1.0f; private Colormap colormap = new Gradient(); private Function2D function = new Noise(); public TextureFilter() { } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public void setFunction(Function2D function) { this.function = function; } public Function2D getFunction() { return function; } public void setOperation(int operation) { this.operation = operation; } public int getOperation() { return operation; } public void setScale(float scale) { this.scale = scale; } public float getScale() { return scale; } public void setStretch(float stretch) { this.stretch = stretch; } public float getStretch() { return stretch; } public void setAngle(float angle) { this.angle = angle; float cos = (float)Math.cos(angle); float sin = (float)Math.sin(angle); m00 = cos; m01 = sin; m10 = -sin; m11 = cos; } public float getAngle() { return angle; } public void setTurbulence(float turbulence) { this.turbulence = turbulence; } public float getTurbulence() { return turbulence; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public int filterRGB(int x, int y, int rgb) { float nx = m00*x + m01*y; float ny = m10*x + m11*y; nx /= scale; ny /= scale * stretch; float f = turbulence == 1.0 ? Noise.noise2(nx, ny) : Noise.turbulence2(nx, ny, turbulence); f = (f * 0.5f) + 0.5f; f = ImageMath.gain(f, gain); f = ImageMath.bias(f, bias); f *= amount; int a = rgb & 0xff000000; int v; if (colormap != null) v = colormap.getColor(f); else { v = PixelUtils.clamp((int)(f*255)); int r = v << 16; int g = v << 8; int b = v; v = a|r|g|b; } if (operation != PixelUtils.REPLACE) v = PixelUtils.combinePixels(rgb, v, operation); return v; } public String toString() { return "Texture/Noise..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/LifeFilter.java0000644000175000017500000000335010521402274021635 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class LifeFilter extends BinaryFilter { public LifeFilter() { } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] outPixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int r = 0, g = 0, b = 0; int pixel = inPixels[y*width+x]; int a = pixel & 0xff000000; int neighbours = 0; for (int row = -1; row <= 1; row++) { int iy = y+row; int ioffset; if (0 <= iy && iy < height) { ioffset = iy*width; for (int col = -1; col <= 1; col++) { int ix = x+col; if (!(row == 0 && col == 0) && 0 <= ix && ix < width) { int rgb = inPixels[ioffset+ix]; if (blackFunction.isBlack(rgb)) neighbours++; } } } } if (blackFunction.isBlack(pixel)) outPixels[index++] = (neighbours == 2 || neighbours == 3) ? pixel : 0xffffffff; else outPixels[index++] = neighbours == 3 ? 0xff000000 : pixel; } } return outPixels; } public String toString() { return "Binary/Life"; } } jhlabs-filters-2.0.235/com/jhlabs/image/ShapeFilter.java0000644000175000017500000001760710521402274022030 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; // original code Copyright (C) Jerry Huxtable 1998 // // customizations (C) Michele Puccini 19/12/2001 // - conversion from float to int math // - complete rewrite of applyMap() // - implemented merge to dest function public class ShapeFilter extends WholeImageFilter { public final static int LINEAR = 0; public final static int CIRCLE_UP = 1; public final static int CIRCLE_DOWN = 2; public final static int SMOOTH = 3; private float factor = 1.0f; protected Colormap colormap; private boolean useAlpha = true; private boolean invert = false; private boolean merge = false; private int type; private final static int one = 41; private final static int sqrt2 = (int)(41*Math.sqrt(2)); private final static int sqrt5 = (int)(41*Math.sqrt(5)); public ShapeFilter() { colormap = new LinearColormap(); } public void setFactor(float factor) { this.factor = factor; } public float getFactor() { return factor; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public void setUseAlpha(boolean useAlpha) { this.useAlpha = useAlpha; } public boolean getUseAlpha() { return useAlpha; } public void setType(int type) { this.type = type; } public int getType() { return type; } public void setInvert(boolean invert) { this.invert = invert; } public boolean getInvert() { return invert; } public void setMerge(boolean merge) { this.merge = merge; } public boolean getMerge() { return merge; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int[] map = new int[width * height]; makeMap(inPixels, map, width, height); int max = distanceMap(map, width, height); applyMap(map, inPixels, width, height, max); return inPixels; } public int distanceMap(int[] map, int width, int height) { int xmax = width - 3; int ymax = height - 3; int max = 0; int v; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int offset = x + y * width; if (map[offset] > 0) { if (x < 2 || x > xmax || y < 2 || y > ymax) v = setEdgeValue(x, y, map, width, offset, xmax, ymax); else v = setValue(map, width, offset); if (v > max) max = v; } } } for (int y = height-1; y >= 0; y--) { for (int x = width-1; x >= 0; x--) { int offset = x + y * width; if (map[offset] > 0) { if (x < 2 || x > xmax || y < 2 || y > ymax) v = setEdgeValue(x, y, map, width, offset, xmax, ymax); else v = setValue(map, width, offset); if (v > max) max = v; } } } return max; } private void makeMap(int[] pixels, int[] map, int width, int height) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int offset = x + y * width; int b = useAlpha ? (pixels[offset] >> 24) & 0xff : PixelUtils.brightness(pixels[offset]); // map[offset] = b * one; map[offset] = b * one / 10; } } } private void applyMap(int[] map, int[] pixels, int width, int height, int max) { if (max == 0) max = 1; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int offset = x + y * width; int m = map[offset]; float v = 0; int sa = 0, sr = 0, sg = 0, sb = 0; if (m == 0) { // default color sa = sr = sg = sb = 0; sa = (pixels[offset] >> 24) & 0xff; } else { // get V from map v = ImageMath.clamp(factor * m / max, 0, 1); switch (type) { case CIRCLE_UP : v = (ImageMath.circleUp(v)); break; case CIRCLE_DOWN : v = (ImageMath.circleDown(v)); break; case SMOOTH : v = (ImageMath.smoothStep(0, 1, v)); break; } if (colormap == null) { sr = sg = sb = (int)(v*255); } else { int c = (colormap.getColor(v)); sr = (c >> 16) & 0xFF; sg = (c >> 8) & 0xFF; sb = (c) & 0xFF; } sa = useAlpha ? (pixels[offset] >> 24) & 0xff : PixelUtils.brightness(pixels[offset]); // invert v if necessary if (invert) { sr = 255-sr; sg = 255-sg; sb = 255-sb; } } // write results if (merge) { // merge with source int transp = 255; int col = pixels[offset]; int a = (col & 0xFF000000) >> 24; int r = (col & 0xFF0000) >> 16; int g = (col & 0xFF00) >> 8; int b = (col & 0xFF); r = (int)((sr*r/transp)); g = (int)((sg*g/transp)); b = (int)((sb*b/transp)); // clip colors if (r < 0) r = 0; if (r > 255) r = 255; if (g < 0) g = 0; if (g > 255) g = 255; if (b < 0) b = 0; if (b > 255) b = 255; pixels[offset] = (a << 24) | (r << 16) | (g << 8) | b; } else { // write gray shades pixels[offset] = (sa << 24) | (sr << 16) | (sg << 8) | sb; } } } } private int setEdgeValue(int x, int y, int[] map, int width, int offset, int xmax, int ymax) { int min, v; int r1, r2, r3, r4, r5; r1 = offset - width - width - 2; r2 = r1 + width; r3 = r2 + width; r4 = r3 + width; r5 = r4 + width; if (y == 0 || x == 0 || y == ymax+2 || x == xmax+2) return map[offset] = one; v = map[r2 + 2] + one; min = v; v = map[r3 + 1] + one; if (v < min) min = v; v = map[r3 + 3] + one; if (v < min) min = v; v = map[r4 + 2] + one; if (v < min) min = v; v = map[r2 + 1] + sqrt2; if (v < min) min = v; v = map[r2 + 3] + sqrt2; if (v < min) min = v; v = map[r4 + 1] + sqrt2; if (v < min) min = v; v = map[r4 + 3] + sqrt2; if (v < min) min = v; if (y == 1 || x == 1 || y == ymax+1 || x == xmax+1) return map[offset] = min; v = map[r1 + 1] + sqrt5; if (v < min) min = v; v = map[r1 + 3] + sqrt5; if (v < min) min = v; v = map[r2 + 4] + sqrt5; if (v < min) min = v; v = map[r4 + 4] + sqrt5; if (v < min) min = v; v = map[r5 + 3] + sqrt5; if (v < min) min = v; v = map[r5 + 1] + sqrt5; if (v < min) min = v; v = map[r4] + sqrt5; if (v < min) min = v; v = map[r2] + sqrt5; if (v < min) min = v; return map[offset] = min; } private int setValue(int[] map, int width, int offset) { int min, v; int r1, r2, r3, r4, r5; r1 = offset - width - width - 2; r2 = r1 + width; r3 = r2 + width; r4 = r3 + width; r5 = r4 + width; v = map[r2 + 2] + one; min = v; v = map[r3 + 1] + one; if (v < min) min = v; v = map[r3 + 3] + one; if (v < min) min = v; v = map[r4 + 2] + one; if (v < min) min = v; v = map[r2 + 1] + sqrt2; if (v < min) min = v; v = map[r2 + 3] + sqrt2; if (v < min) min = v; v = map[r4 + 1] + sqrt2; if (v < min) min = v; v = map[r4 + 3] + sqrt2; if (v < min) min = v; v = map[r1 + 1] + sqrt5; if (v < min) min = v; v = map[r1 + 3] + sqrt5; if (v < min) min = v; v = map[r2 + 4] + sqrt5; if (v < min) min = v; v = map[r4 + 4] + sqrt5; if (v < min) min = v; v = map[r5 + 3] + sqrt5; if (v < min) min = v; v = map[r5 + 1] + sqrt5; if (v < min) min = v; v = map[r4] + sqrt5; if (v < min) min = v; v = map[r2] + sqrt5; if (v < min) min = v; return map[offset] = min; } public String toString() { return "Stylize/Shapeburst..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/FourColorFilter.java0000644000175000017500000000521210521402272022665 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.util.*; /** * A filter which draws a gradient interpolated between four colors defined at the corners of the image. */ public class FourColorFilter extends PointFilter { private int width; private int height; private int colorNW; private int colorNE; private int colorSW; private int colorSE; private int rNW, gNW, bNW; private int rNE, gNE, bNE; private int rSW, gSW, bSW; private int rSE, gSE, bSE; public FourColorFilter() { setColorNW( 0xffff0000 ); setColorNE( 0xffff00ff ); setColorSW( 0xff0000ff ); setColorSE( 0xff00ffff ); } public void setColorNW( int color ) { this.colorNW = color; rNW = (color >> 16) & 0xff; gNW = (color >> 8) & 0xff; bNW = color & 0xff; } public int getColorNW() { return colorNW; } public void setColorNE( int color ) { this.colorNE = color; rNE = (color >> 16) & 0xff; gNE = (color >> 8) & 0xff; bNE = color & 0xff; } public int getColorNE() { return colorNE; } public void setColorSW( int color ) { this.colorSW = color; rSW = (color >> 16) & 0xff; gSW = (color >> 8) & 0xff; bSW = color & 0xff; } public int getColorSW() { return colorSW; } public void setColorSE( int color ) { this.colorSE = color; rSE = (color >> 16) & 0xff; gSE = (color >> 8) & 0xff; bSE = color & 0xff; } public int getColorSE() { return colorSE; } public void setDimensions(int width, int height) { this.width = width; this.height = height; super.setDimensions(width, height); } public int filterRGB(int x, int y, int rgb) { float fx = (float)x / width; float fy = (float)y / height; float p, q; p = rNW + (rNE - rNW) * fx; q = rSW + (rSE - rSW) * fx; int r = (int)( p + (q - p) * fy + 0.5f ); p = gNW + (gNE - gNW) * fx; q = gSW + (gSE - gSW) * fx; int g = (int)( p + (q - p) * fy + 0.5f ); p = bNW + (bNE - bNW) * fx; q = bSW + (bSE - bSW) * fx; int b = (int)( p + (q - p) * fy + 0.5f ); return 0xff000000 | (r << 16) | (g << 8) | b; } public String toString() { return "Texture/Four Color Fill..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/AverageFilter.java0000644000175000017500000000172110521402272022326 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A filter which averages the 3x3 neighbourhood of each pixel, providing a simple blur. */ public class AverageFilter extends ConvolveFilter { protected static float[] theMatrix = { 0.1f, 0.1f, 0.1f, 0.1f, 0.2f, 0.1f, 0.1f, 0.1f, 0.1f }; public AverageFilter() { super( theMatrix ); } public String toString() { return "Blur/Average Blur"; } } jhlabs-filters-2.0.235/com/jhlabs/image/MapFilter.java0000644000175000017500000000265110521402274021476 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import com.jhlabs.math.*; public class MapFilter extends TransformFilter { private Function2D xMapFunction; private Function2D yMapFunction; public MapFilter() { } public void setXMapFunction(Function2D xMapFunction) { this.xMapFunction = xMapFunction; } public Function2D getXMapFunction() { return xMapFunction; } public void setYMapFunction(Function2D yMapFunction) { this.yMapFunction = yMapFunction; } public Function2D getYMapFunction() { return yMapFunction; } protected void transformInverse(int x, int y, float[] out) { float xMap, yMap; xMap = xMapFunction.evaluate(x, y); yMap = yMapFunction.evaluate(x, y); out[0] = xMap * transformedSpace.width; out[1] = yMap * transformedSpace.height; } public String toString() { return "Distort/Map Coordinates..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/RescaleFilter.java0000644000175000017500000000206310521402274022334 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class RescaleFilter extends TransferFilter { static final long serialVersionUID = -2724874183243154495L; private float scale = 1.0f; protected float transferFunction( float v ) { return PixelUtils.clamp((int)(v * scale)); } public void setScale(float scale) { this.scale = scale; initialized = false; } public float getScale() { return scale; } public String toString() { return "Colors/Rescale..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/GlowFilter.java0000644000175000017500000000463410521402274021674 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A filter which adds Gaussian blur to an image, producing a glowing effect. * @author Jerry Huxtable */ public class GlowFilter extends GaussianFilter { static final long serialVersionUID = 5377089073023183684L; private float amount = 0.5f; public GlowFilter() { radius = 2; } public void setAmount( float amount ) { this.amount = amount; } public float getAmount() { return amount; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; src.getRGB( 0, 0, width, height, inPixels, 0, width ); if ( radius > 0 ) { convolveAndTranspose(kernel, inPixels, outPixels, width, height, alpha, CLAMP_EDGES); convolveAndTranspose(kernel, outPixels, inPixels, height, width, alpha, CLAMP_EDGES); } src.getRGB( 0, 0, width, height, outPixels, 0, width ); float a = 4*amount; int index = 0; for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++ ) { int rgb1 = outPixels[index]; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; int rgb2 = inPixels[index]; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; r1 = PixelUtils.clamp( (int)(r1 + a * r2) ); g1 = PixelUtils.clamp( (int)(g1 + a * g2) ); b1 = PixelUtils.clamp( (int)(b1 + a * b2) ); inPixels[index] = (rgb1 & 0xff000000) | (r1 << 16) | (g1 << 8) | b1; index++; } } dst.setRGB( 0, 0, width, height, inPixels, 0, width ); return dst; } public String toString() { return "Blur/Glow..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/FillFilter.java0000644000175000017500000000227210521402272021644 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter which fills an image with a given color. Normally you would just call Graphics.fillRect but it can sometimes be useful * to go via a filter to fit in with an existing API. */ public class FillFilter extends PointFilter { private int fillColor; public FillFilter() { this(0xff000000); } public FillFilter(int color) { this.fillColor = color; } public void setFillColor(int fillColor) { this.fillColor = fillColor; } public int getFillColor() { return fillColor; } public int filterRGB(int x, int y, int rgb) { return fillColor; } } jhlabs-filters-2.0.235/com/jhlabs/image/CompoundFilter.java0000644000175000017500000000205010521402272022534 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; public class CompoundFilter extends AbstractBufferedImageOp { private BufferedImageOp filter1; private BufferedImageOp filter2; public CompoundFilter( BufferedImageOp filter1, BufferedImageOp filter2 ) { this.filter1 = filter1; this.filter2 = filter2; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { BufferedImage image = filter1.filter( src, dst ); image = filter2.filter( image, dst ); return image; } } jhlabs-filters-2.0.235/com/jhlabs/image/SphereFilter.java0000644000175000017500000000603110521402274022203 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; public class SphereFilter extends TransformFilter { static final long serialVersionUID = -8148404526162968279L; private float a = 0; private float b = 0; private float a2 = 0; private float b2 = 0; private float centreX = 0.5f; private float centreY = 0.5f; private float refractionIndex = 1.5f; private float icentreX; private float icentreY; public SphereFilter() { setEdgeAction( CLAMP ); setRadius( 100.0f ); } public void setRefractionIndex(float refractionIndex) { this.refractionIndex = refractionIndex; } public float getRefractionIndex() { return refractionIndex; } public void setRadius(float r) { this.a = r; this.b = r; } public float getRadius() { return a; } public void setCentreX( float centreX ) { this.centreX = centreX; } public float getCentreX() { return centreX; } public void setCentreY( float centreY ) { this.centreY = centreY; } public float getCentreY() { return centreY; } public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); icentreX = width * centreX; icentreY = height * centreY; if (a == 0) a = width/2; if (b == 0) b = height/2; a2 = a*a; b2 = b*b; return super.filter( src, dst ); } protected void transformInverse(int x, int y, float[] out) { float dx = x-icentreX; float dy = y-icentreY; float x2 = dx*dx; float y2 = dy*dy; if (y2 >= (b2 - (b2*x2)/a2)) { out[0] = x; out[1] = y; } else { float rRefraction = 1.0f / refractionIndex; float z = (float)Math.sqrt((1.0f - x2/a2 - y2/b2) * (a*b)); float z2 = z*z; float xAngle = (float)Math.acos(dx / Math.sqrt(x2+z2)); float angle1 = ImageMath.HALF_PI - xAngle; float angle2 = (float)Math.asin(Math.sin(angle1)*rRefraction); angle2 = ImageMath.HALF_PI - xAngle - angle2; out[0] = x - (float)Math.tan(angle2)*z; float yAngle = (float)Math.acos(dy / Math.sqrt(y2+z2)); angle1 = ImageMath.HALF_PI - yAngle; angle2 = (float)Math.asin(Math.sin(angle1)*rRefraction); angle2 = ImageMath.HALF_PI - yAngle - angle2; out[1] = y - (float)Math.tan(angle2)*z; } } public String toString() { return "Distort/Sphere..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/HSBAdjustFilter.java0000644000175000017500000000361010521402274022544 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class HSBAdjustFilter extends PointFilter { public float hFactor, sFactor, bFactor; private float[] hsb = new float[3]; public HSBAdjustFilter() { this(0, 0, 0); } public HSBAdjustFilter(float r, float g, float b) { hFactor = r; sFactor = g; bFactor = b; canFilterIndexColorModel = true; } public void setHFactor( float hFactor ) { this.hFactor = hFactor; } public float getHFactor() { return hFactor; } public void setSFactor( float sFactor ) { this.sFactor = sFactor; } public float getSFactor() { return sFactor; } public void setBFactor( float bFactor ) { this.bFactor = bFactor; } public float getBFactor() { return bFactor; } public int filterRGB(int x, int y, int rgb) { int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; Color.RGBtoHSB(r, g, b, hsb); hsb[0] += hFactor; while (hsb[0] < 0) hsb[0] += Math.PI*2; hsb[1] += sFactor; if (hsb[1] < 0) hsb[1] = 0; else if (hsb[1] > 1.0) hsb[1] = 1.0f; hsb[2] += bFactor; if (hsb[2] < 0) hsb[2] = 0; else if (hsb[2] > 1.0) hsb[2] = 1.0f; rgb = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]); return a | (rgb & 0xffffff); } public String toString() { return "Colors/Adjust HSB..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/SmartBlurFilter.java0000644000175000017500000001070610521402274022674 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.awt.geom.*; public class SmartBlurFilter extends AbstractBufferedImageOp { private int hRadius = 5; private int vRadius = 5; private int threshold = 10; public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; getRGB( src, 0, 0, width, height, inPixels ); Kernel kernel = GaussianFilter.makeKernel(hRadius); thresholdBlur( kernel, inPixels, outPixels, width, height, true ); thresholdBlur( kernel, outPixels, inPixels, height, width, true ); setRGB( dst, 0, 0, width, height, inPixels ); return dst; } /** * Convolve with a kernel consisting of one row */ public void thresholdBlur(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, boolean alpha) { int index = 0; float[] matrix = kernel.getKernelData( null ); int cols = kernel.getWidth(); int cols2 = cols/2; for (int y = 0; y < height; y++) { int ioffset = y*width; int outIndex = y; for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; int moffset = cols2; int rgb1 = inPixels[ioffset+x]; int a1 = (rgb1 >> 24) & 0xff; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; float af = 0, rf = 0, gf = 0, bf = 0; for (int col = -cols2; col <= cols2; col++) { float f = matrix[moffset+col]; if (f != 0) { int ix = x+col; if (!(0 <= ix && ix < width)) ix = x; int rgb2 = inPixels[ioffset+ix]; int a2 = (rgb2 >> 24) & 0xff; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; int d; d = a1-a2; if ( d >= -threshold && d <= threshold ) { a += f * a2; af += f; } d = r1-r2; if ( d >= -threshold && d <= threshold ) { r += f * r2; rf += f; } d = g1-g2; if ( d >= -threshold && d <= threshold ) { g += f * g2; gf += f; } d = b1-b2; if ( d >= -threshold && d <= threshold ) { b += f * b2; bf += f; } } } a = af == 0 ? a1 : a/af; r = rf == 0 ? r1 : r/rf; g = gf == 0 ? g1 : g/gf; b = bf == 0 ? b1 : b/bf; int ia = alpha ? PixelUtils.clamp((int)(a+0.5)) : 0xff; int ir = PixelUtils.clamp((int)(r+0.5)); int ig = PixelUtils.clamp((int)(g+0.5)); int ib = PixelUtils.clamp((int)(b+0.5)); outPixels[outIndex] = (ia << 24) | (ir << 16) | (ig << 8) | ib; outIndex += height; } } } public void setHRadius(int hRadius) { this.hRadius = hRadius; } public int getHRadius() { return hRadius; } public void setVRadius(int vRadius) { this.vRadius = vRadius; } public int getVRadius() { return vRadius; } public void setRadius(int radius) { this.hRadius = this.vRadius = radius; } public int getRadius() { return hRadius; } public void setThreshold(int threshold) { this.threshold = threshold; } public int getThreshold() { return threshold; } public String toString() { return "Blur/Smart Blur..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/OilFilter.java0000644000175000017500000000540410521402274021503 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class OilFilter extends WholeImageFilter { static final long serialVersionUID = 1722613531684653826L; private int range = 3; private int levels = 256; public OilFilter() { } public void setRange( int range ) { this.range = range; } public int getRange() { return range; } public void setLevels( int levels ) { this.levels = levels; } public int getLevels() { return levels; } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] rHistogram = new int[levels]; int[] gHistogram = new int[levels]; int[] bHistogram = new int[levels]; int[] rTotal = new int[levels]; int[] gTotal = new int[levels]; int[] bTotal = new int[levels]; int[] outPixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { for (int i = 0; i < levels; i++) rHistogram[i] = gHistogram[i] = bHistogram[i] = rTotal[i] = gTotal[i] = bTotal[i] = 0; for (int row = -range; row <= range; row++) { int iy = y+row; int ioffset; if (0 <= iy && iy < height) { ioffset = iy*width; for (int col = -range; col <= range; col++) { int ix = x+col; if (0 <= ix && ix < width) { int rgb = inPixels[ioffset+ix]; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; int ri = r*levels/256; int gi = g*levels/256; int bi = b*levels/256; rTotal[ri] += r; gTotal[gi] += g; bTotal[bi] += b; rHistogram[ri]++; gHistogram[gi]++; bHistogram[bi]++; } } } } int r = 0, g = 0, b = 0; for (int i = 1; i < levels; i++) { if (rHistogram[i] > rHistogram[r]) r = i; if (gHistogram[i] > gHistogram[g]) g = i; if (bHistogram[i] > bHistogram[b]) b = i; } r = rTotal[r] / rHistogram[r]; g = gTotal[g] / gHistogram[g]; b = bTotal[b] / bHistogram[b]; outPixels[index++] = 0xff000000 | ( r << 16 ) | ( g << 8 ) | b; } } return outPixels; } public String toString() { return "Stylize/Oil..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/QuantizeFilter.java0000644000175000017500000001145510521402274022563 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.util.*; import java.awt.*; import java.awt.image.*; /** * A filter which quantizes an image to a set number of colors - useful for producing * images which are to be encoded using an index color model. The filter can perform * Floyd-Steinberg error-diffusion dithering if required. At present, the quantization * is done using an octtree algorithm but I eventually hope to add more quantization * methods such as median cut. Note: at present, the filter produces an image which * uses the RGB color model (because the application it was written for required it). * I hope to extend it to produce an IndexColorModel by request. */ public class QuantizeFilter extends WholeImageFilter implements java.io.Serializable { /** * Floyd-Steinberg dithering matrix. */ protected final static int[] matrix = { 0, 0, 0, 0, 0, 7, 3, 5, 1, }; private int sum = 3+5+7+1; private boolean dither; private int numColors = 256; private boolean serpentine = true; /** * Set the number of colors to quantize to. * @param numColors the number of colors. The default is 256. */ public void setNumColors(int numColors) { this.numColors = Math.min(Math.max(numColors, 8), 256); } /** * Get the number of colors to quantize to. * @return the number of colors. */ public int getNumColors() { return numColors; } /** * Set whether to use dithering or not. If not, the image is posterized. * @param dither true to use dithering */ public void setDither(boolean dither) { this.dither = dither; } /** * Return the dithering setting * @return the current setting */ public boolean getDither() { return dither; } /** * Set whether to use a serpentine pattern for return or not. This can reduce 'avalanche' artifacts in the output. * @param serpentine true to use serpentine pattern */ public void setSerpentine(boolean serpentine) { this.serpentine = serpentine; } /** * Return the serpentine setting * @return the current setting */ public boolean getSerpentine() { return serpentine; } public void quantize(int[] inPixels, int[] outPixels, int width, int height, int numColors, boolean dither, boolean serpentine) { int count = width*height; Quantizer quantizer = new OctTreeQuantizer(); quantizer.setup(numColors); quantizer.addPixels(inPixels, 0, count); int[] table = quantizer.buildColorTable(); if (!dither) { for (int i = 0; i < count; i++) outPixels[i] = table[quantizer.getIndexForColor(inPixels[i])]; } else { int index = 0; for (int y = 0; y < height; y++) { boolean reverse = serpentine && (y & 1) == 1; int direction; if (reverse) { index = y*width+width-1; direction = -1; } else { index = y*width; direction = 1; } for (int x = 0; x < width; x++) { int rgb1 = inPixels[index]; int rgb2 = table[quantizer.getIndexForColor(rgb1)]; outPixels[index] = rgb2; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; int er = r1-r2; int eg = g1-g2; int eb = b1-b2; for (int i = -1; i <= 1; i++) { int iy = i+y; if (0 <= iy && iy < height) { for (int j = -1; j <= 1; j++) { int jx = j+x; if (0 <= jx && jx < width) { int w; if (reverse) w = matrix[(i+1)*3-j+1]; else w = matrix[(i+1)*3+j+1]; if (w != 0) { int k = reverse ? index - j : index + j; rgb1 = inPixels[k]; r1 = (rgb1 >> 16) & 0xff; g1 = (rgb1 >> 8) & 0xff; b1 = rgb1 & 0xff; r1 += er * w/sum; g1 += eg * w/sum; b1 += eb * w/sum; inPixels[k] = (PixelUtils.clamp(r1) << 16) | (PixelUtils.clamp(g1) << 8) | PixelUtils.clamp(b1); } } } } } index += direction; } } } } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int[] outPixels = new int[width*height]; quantize(inPixels, outPixels, width, height, numColors, dither, serpentine); return outPixels; } public String toString() { return "Colors/Quantize..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/FBMFilter.java0000644000175000017500000001115510521402272021362 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import java.util.*; import com.jhlabs.math.*; /** * A filter which produces textures from fractal Brownian motion. */ public class FBMFilter extends PointFilter implements Cloneable { public final static int NOISE = 0; public final static int RIDGED = 1; public final static int VLNOISE = 2; public final static int SCNOISE = 3; public final static int CELLULAR = 4; private float scale = 32; private float stretch = 1.0f; private float angle = 0.0f; private float amount = 1.0f; private float H = 1.0f; private float octaves = 4.0f; private float lacunarity = 2.0f; private float gain = 0.5f; private float bias = 0.5f; private int operation; private float m00 = 1.0f; private float m01 = 0.0f; private float m10 = 0.0f; private float m11 = 1.0f; private float min; private float max; private Colormap colormap = new Gradient(); private boolean ridged; private FBM fBm; protected Random random = new Random(); private int basisType = NOISE; private Function2D basis; public FBMFilter() { setBasisType(NOISE); } public void setAmount(float amount) { this.amount = amount; } public float getAmount() { return amount; } public void setOperation(int operation) { this.operation = operation; } public int getOperation() { return operation; } public void setScale(float scale) { this.scale = scale; } public float getScale() { return scale; } public void setStretch(float stretch) { this.stretch = stretch; } public float getStretch() { return stretch; } public void setAngle(float angle) { this.angle = angle; float cos = (float)Math.cos(this.angle); float sin = (float)Math.sin(this.angle); m00 = cos; m01 = sin; m10 = -sin; m11 = cos; } public float getAngle() { return angle; } public void setOctaves(float octaves) { this.octaves = octaves; } public float getOctaves() { return octaves; } public void setH(float H) { this.H = H; } public float getH() { return H; } public void setLacunarity(float lacunarity) { this.lacunarity = lacunarity; } public float getLacunarity() { return lacunarity; } public void setGain(float gain) { this.gain = gain; } public float getGain() { return gain; } public void setBias(float bias) { this.bias = bias; } public float getBias() { return bias; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public void setBasisType(int basisType) { this.basisType = basisType; switch (basisType) { default: case NOISE: basis = new Noise(); break; case RIDGED: basis = new RidgedFBM(); break; case VLNOISE: basis = new VLNoise(); break; case SCNOISE: basis = new SCNoise(); break; case CELLULAR: basis = new CellularFunction2D(); break; } } public int getBasisType() { return basisType; } public void setBasis(Function2D basis) { this.basis = basis; } public Function2D getBasis() { return basis; } protected FBM makeFBM(float H, float lacunarity, float octaves) { FBM fbm = new FBM(H, lacunarity, octaves, basis); float[] minmax = Noise.findRange(fbm, null); min = minmax[0]; max = minmax[1]; return fbm; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { fBm = makeFBM(H, lacunarity, octaves); return super.filter( src, dst ); } public int filterRGB(int x, int y, int rgb) { float nx = m00*x + m01*y; float ny = m10*x + m11*y; nx /= scale; ny /= scale * stretch; float f = fBm.evaluate(nx, ny); // Normalize to 0..1 f = (f-min)/(max-min); f = ImageMath.gain(f, gain); f = ImageMath.bias(f, bias); f *= amount; int a = rgb & 0xff000000; int v; if (colormap != null) v = colormap.getColor(f); else { v = PixelUtils.clamp((int)(f*255)); int r = v << 16; int g = v << 8; int b = v; v = a|r|g|b; } if (operation != PixelUtils.REPLACE) v = PixelUtils.combinePixels(rgb, v, operation); return v; } public String toString() { return "Texture/Fractal Brownian Motion..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/SharpenFilter.java0000644000175000017500000000167710521402274022370 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; public class SharpenFilter extends ConvolveFilter { static final long serialVersionUID = -4883137561307845895L; protected static float[] sharpenMatrix = { 0.0f, -0.2f, 0.0f, -0.2f, 1.8f, -0.2f, 0.0f, -0.2f, 0.0f }; public SharpenFilter() { super(sharpenMatrix); } public String toString() { return "Blur/Sharpen"; } } jhlabs-filters-2.0.235/com/jhlabs/image/CropFilter.java0000644000175000017500000000370210521402272021660 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; /** * A filter which crops an image to a given rectangle. */ public class CropFilter extends AbstractBufferedImageOp { private int x; private int y; private int width; private int height; public CropFilter() { this(0, 0, 32, 32); } public CropFilter(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; } public void setX(int x) { this.x = x; } public int getX() { return x; } public void setY(int y) { this.y = y; } public int getY() { return y; } public void setWidth(int width) { this.width = width; } public int getWidth() { return width; } public void setHeight(int height) { this.height = height; } public int getHeight() { return height; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int w = src.getWidth(); int h = src.getHeight(); if ( dst == null ) { ColorModel dstCM = src.getColorModel(); dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(width, height), dstCM.isAlphaPremultiplied(), null); } Graphics2D g = dst.createGraphics(); g.drawRenderedImage( src, AffineTransform.getTranslateInstance(-x, -y) ); g.dispose(); return dst; } public String toString() { return "Distort/Crop"; } } jhlabs-filters-2.0.235/com/jhlabs/image/RGBAdjustFilter.java0000644000175000017500000000360010521402274022541 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class RGBAdjustFilter extends PointFilter implements java.io.Serializable { public float rFactor, gFactor, bFactor; public RGBAdjustFilter() { this(0, 0, 0); } public RGBAdjustFilter(float r, float g, float b) { rFactor = 1+r; gFactor = 1+g; bFactor = 1+b; canFilterIndexColorModel = true; } public void setRFactor( float rFactor ) { this.rFactor = 1+rFactor; } public float getRFactor() { return rFactor-1; } public void setGFactor( float gFactor ) { this.gFactor = 1+gFactor; } public float getGFactor() { return gFactor-1; } public void setBFactor( float bFactor ) { this.bFactor = 1+bFactor; } public float getBFactor() { return bFactor-1; } public int[] getLUT() { int[] lut = new int[256]; for ( int i = 0; i < 256; i++ ) { lut[i] = filterRGB( 0, 0, (i << 24) | (i << 16) | (i << 8) | i ); } return lut; } public int filterRGB(int x, int y, int rgb) { int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; r = PixelUtils.clamp((int)(r * rFactor)); g = PixelUtils.clamp((int)(g * gFactor)); b = PixelUtils.clamp((int)(b * bFactor)); return a | (r << 16) | (g << 8) | b; } public String toString() { return "Colors/Adjust RGB..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/CompositeFilter.java0000644000175000017500000000352510521402272022722 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; /** * A filter which composites two images together with an optional transform. */ public class CompositeFilter extends AbstractBufferedImageOp { private Composite composite; private AffineTransform transform; public CompositeFilter() { } public CompositeFilter( Composite composite ) { this.composite = composite; } public CompositeFilter( Composite composite, AffineTransform transform ) { this.composite = composite; this.transform = transform; } public void setComposite( Composite composite ) { this.composite = composite; } public Composite getComposite() { return composite; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { if ( dst == null ) dst = createCompatibleDestImage( src, null ); Graphics2D g = dst.createGraphics(); g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR ); g.setComposite( composite ); g.drawRenderedImage( src, transform ); g.dispose(); return dst; } public String toString() { return "Composite"; } } jhlabs-filters-2.0.235/com/jhlabs/image/GradientFilter.java0000644000175000017500000001747510521402274022530 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import java.util.*; /** * A filter which draws a coloured gradient. This is largely superceded by GradientPaint in Java1.2, but does provide a few * more gradient options. */ public class GradientFilter extends AbstractBufferedImageOp { public final static int LINEAR = 0; public final static int BILINEAR = 1; public final static int RADIAL = 2; public final static int CONICAL = 3; public final static int BICONICAL = 4; public final static int SQUARE = 5; public final static int INT_LINEAR = 0; public final static int INT_CIRCLE_UP = 1; public final static int INT_CIRCLE_DOWN = 2; public final static int INT_SMOOTH = 3; private float angle = 0; private int color1 = 0xff000000; private int color2 = 0xffffffff; private Point p1 = new Point(0, 0), p2 = new Point(64, 64); private boolean repeat = false; private float x1; private float y1; private float dx; private float dy; private Colormap colormap = null; private int type; private int interpolation = INT_LINEAR; private int paintMode = PixelUtils.NORMAL; public GradientFilter() { } public GradientFilter(Point p1, Point p2, int color1, int color2, boolean repeat, int type, int interpolation) { this.p1 = p1; this.p2 = p2; this.color1 = color1; this.color2 = color2; this.repeat = repeat; this.type = type; this.interpolation = interpolation; colormap = new LinearColormap(color1, color2); } public void setPoint1(Point point1) { this.p1 = point1; } public Point getPoint1() { return p1; } public void setPoint2(Point point2) { this.p2 = point2; } public Point getPoint2() { return p2; } public void setType(int type) { this.type = type; } public int getType() { return type; } public void setInterpolation(int interpolation) { this.interpolation = interpolation; } public int getInterpolation() { return interpolation; } public void setAngle(float angle) { this.angle = angle; p2 = new Point((int)(64*Math.cos(angle)), (int)(64*Math.sin(angle))); } public float getAngle() { return angle; } public void setColormap(Colormap colormap) { this.colormap = colormap; } public Colormap getColormap() { return colormap; } public void setPaintMode(int paintMode) { this.paintMode = paintMode; } public int getPaintMode() { return paintMode; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int rgb1, rgb2; float x1, y1, x2, y2; x1 = p1.x; x2 = p2.x; if (x1 > x2 && type != RADIAL) { y1 = x1; x1 = x2; x2 = y1; y1 = p2.y; y2 = p1.y; rgb1 = color2; rgb2 = color1; } else { y1 = p1.y; y2 = p2.y; rgb1 = color1; rgb2 = color2; } float dx = x2 - x1; float dy = y2 - y1; float lenSq = dx * dx + dy * dy; this.x1 = x1; this.y1 = y1; if (lenSq >= Float.MIN_VALUE) { dx = dx / lenSq; dy = dy / lenSq; if (repeat) { dx = dx % 1.0f; dy = dy % 1.0f; } } this.dx = dx; this.dy = dy; int[] pixels = new int[width]; for (int y = 0; y < height; y++ ) { getRGB( src, 0, y, width, 1, pixels ); switch (type) { case LINEAR: case BILINEAR: linearGradient(pixels, y, width, 1); break; case RADIAL: radialGradient(pixels, y, width, 1); break; case CONICAL: case BICONICAL: conicalGradient(pixels, y, width, 1); break; case SQUARE: squareGradient(pixels, y, width, 1); break; } setRGB( dst, 0, y, width, 1, pixels ); } return dst; } private void repeatGradient(int[] pixels, int w, int h, float rowrel, float dx, float dy) { int off = 0; for (int y = 0; y < h; y++) { float colrel = rowrel; int j = w; int rgb; while (--j >= 0) { if (type == BILINEAR) rgb = colormap.getColor(map(ImageMath.triangle(colrel))); else rgb = colormap.getColor(map(ImageMath.mod(colrel, 1.0f))); pixels[off] = PixelUtils.combinePixels(rgb, pixels[off], paintMode); off++; colrel += dx; } rowrel += dy; } } private void singleGradient(int[] pixels, int w, int h, float rowrel, float dx, float dy) { int off = 0; for (int y = 0; y < h; y++) { float colrel = rowrel; int j = w; int rgb; if (colrel <= 0.0) { rgb = colormap.getColor(0); do { pixels[off] = PixelUtils.combinePixels(rgb, pixels[off], paintMode); off++; colrel += dx; } while (--j > 0 && colrel <= 0.0); } while (colrel < 1.0 && --j >= 0) { if (type == BILINEAR) rgb = colormap.getColor(map(ImageMath.triangle(colrel))); else rgb = colormap.getColor(map(colrel)); pixels[off] = PixelUtils.combinePixels(rgb, pixels[off], paintMode); off++; colrel += dx; } if (j > 0) { if (type == BILINEAR) rgb = colormap.getColor(0.0f); else rgb = colormap.getColor(1.0f); do { pixels[off] = PixelUtils.combinePixels(rgb, pixels[off], paintMode); off++; } while (--j > 0); } rowrel += dy; } } private void linearGradient(int[] pixels, int y, int w, int h) { int x = 0; float rowrel = (x - x1) * dx + (y - y1) * dy; if (repeat) repeatGradient(pixels, w, h, rowrel, dx, dy); else singleGradient(pixels, w, h, rowrel, dx, dy); } private void radialGradient(int[] pixels, int y, int w, int h) { int off = 0; float radius = distance(p2.x-p1.x, p2.y-p1.y); for (int x = 0; x < w; x++) { float distance = distance(x-p1.x, y-p1.y); float ratio = distance / radius; if (repeat) ratio = ratio % 2; else if (ratio > 1.0) ratio = 1.0f; int rgb = colormap.getColor(map(ratio)); pixels[off] = PixelUtils.combinePixels(rgb, pixels[off], paintMode); off++; } } private void squareGradient(int[] pixels, int y, int w, int h) { int off = 0; float radius = Math.max(Math.abs(p2.x-p1.x), Math.abs(p2.y-p1.y)); for (int x = 0; x < w; x++) { float distance = Math.max(Math.abs(x-p1.x), Math.abs(y-p1.y)); float ratio = distance / radius; if (repeat) ratio = ratio % 2; else if (ratio > 1.0) ratio = 1.0f; int rgb = colormap.getColor(map(ratio)); pixels[off] = PixelUtils.combinePixels(rgb, pixels[off], paintMode); off++; } } private void conicalGradient(int[] pixels, int y, int w, int h) { int off = 0; float angle0 = (float)Math.atan2(p2.x-p1.x, p2.y-p1.y); for (int x = 0; x < w; x++) { float angle = (float)(Math.atan2(x-p1.x, y-p1.y) - angle0) / (ImageMath.TWO_PI); angle += 1.0f; angle %= 1.0f; if (type == BICONICAL) angle = ImageMath.triangle(angle); int rgb = colormap.getColor(map(angle)); pixels[off] = PixelUtils.combinePixels(rgb, pixels[off], paintMode); off++; } } private float map(float v) { if (repeat) v = v > 1.0 ? 2.0f-v : v; switch (interpolation) { case INT_CIRCLE_UP: v = ImageMath.circleUp(ImageMath.clamp(v, 0.0f, 1.0f)); break; case INT_CIRCLE_DOWN: v = ImageMath.circleDown(ImageMath.clamp(v, 0.0f, 1.0f)); break; case INT_SMOOTH: v = ImageMath.smoothStep(0, 1, v); break; } return v; } private float distance(float a, float b) { return (float)Math.sqrt(a*a+b*b); } public String toString() { return "Other/Gradient Fill..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/InvertFilter.java0000644000175000017500000000170410521402274022226 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; /** * A filter which inverts the RGB channels of an image. */ public class InvertFilter extends PointFilter { public InvertFilter() { canFilterIndexColorModel = true; } public int filterRGB(int x, int y, int rgb) { int a = rgb & 0xff000000; return a | (~rgb & 0x00ffffff); } public String toString() { return "Colors/Invert"; } } jhlabs-filters-2.0.235/com/jhlabs/image/TwirlFilter.java0000644000175000017500000000575610521402274022073 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; /** * A Filter which distorts an image by twisting it from the centre out. * The twisting is centred at the centre of the image and extends out to the smallest of * the width and height. Pixels outside this radius are unaffected. */ public class TwirlFilter extends TransformFilter { static final long serialVersionUID = 1550445062822803342L; private float angle = 0; private float centreX = 0.5f; private float centreY = 0.5f; private float radius = 100; private float radius2 = 0; private float icentreX; private float icentreY; /** * Construct a TwirlFilter with no distortion. */ public TwirlFilter() { setEdgeAction( CLAMP ); } /** * Set the angle of twirl in radians. 0 means no distortion. * @param angle the angle of twirl. This is the angle by which pixels at the nearest edge of the image will move. */ public void setAngle(float angle) { this.angle = angle; } /** * Get the angle of twist. * @return the angle in radians. */ public float getAngle() { return angle; } public void setCentreX( float centreX ) { this.centreX = centreX; } public float getCentreX() { return centreX; } public void setCentreY( float centreY ) { this.centreY = centreY; } public float getCentreY() { return centreY; } public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } public void setRadius(float radius) { this.radius = radius; } public float getRadius() { return radius; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { icentreX = src.getWidth() * centreX; icentreY = src.getHeight() * centreY; if ( radius == 0 ) radius = Math.min(icentreX, icentreY); radius2 = radius*radius; return super.filter( src, dst ); } protected void transformInverse(int x, int y, float[] out) { float dx = x-icentreX; float dy = y-icentreY; float distance = dx*dx + dy*dy; if (distance > radius2) { out[0] = x; out[1] = y; } else { distance = (float)Math.sqrt(distance); float a = (float)Math.atan2(dy, dx) + angle * (radius-distance) / radius; out[0] = icentreX + distance*(float)Math.cos(a); out[1] = icentreY + distance*(float)Math.sin(a); } } public String toString() { return "Distort/Twirl..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/SparkleFilter.java0000644000175000017500000000526410521402274022365 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import java.util.*; public class SparkleFilter extends PointFilter implements java.io.Serializable { static final long serialVersionUID = 1692413049411710802L; private int rays = 50; private int radius = 25; private int amount = 50; private int color = 0xffffffff; private int randomness = 25; private int width, height; private int centreX, centreY; private long seed = 371; private float[] rayLengths; private Random randomNumbers = new Random(); public SparkleFilter() { } public void setColor(int color) { this.color = color; } public int getColor() { return color; } public void setRandomness(int randomness) { this.randomness = randomness; } public int getRandomness() { return randomness; } public void setAmount(int amount) { this.amount = amount; } public int getAmount() { return amount; } public void setRays(int rays) { this.rays = rays; } public int getRays() { return rays; } public void setRadius(int radius) { this.radius = radius; } public int getRadius() { return radius; } public void setDimensions(int width, int height) { this.width = width; this.height = height; centreX = width/2; centreY = height/2; super.setDimensions(width, height); randomNumbers.setSeed(seed); rayLengths = new float[rays]; for (int i = 0; i < rays; i++) rayLengths[i] = radius + randomness / 100.0f * radius * (float)randomNumbers.nextGaussian(); } public int filterRGB(int x, int y, int rgb) { float dx = x-centreX; float dy = y-centreY; float distance = dx*dx+dy*dy; float angle = (float)Math.atan2(dy, dx); float d = (angle+ImageMath.PI) / (ImageMath.TWO_PI) * rays; int i = (int)d; float f = d - i; if (radius != 0) { float length = ImageMath.lerp(f, rayLengths[i % rays], rayLengths[(i+1) % rays]); float g = length*length / (distance+0.0001f); g = (float)Math.pow(g, (100-amount) / 50.0); f -= 0.5f; // f *= amount/50.0f; f = 1 - f*f; f *= g; } f = ImageMath.clamp(f, 0, 1); return ImageMath.mixColors(f, rgb, color); } public String toString() { return "Stylize/Sparkle..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/ShearFilter.java0000644000175000017500000000624110521402274022022 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; public class ShearFilter extends TransformFilter { private float xangle = 0.0f; private float yangle = 0.0f; private float shx = 0.0f; private float shy = 0.0f; private float xoffset = 0.0f; private float yoffset = 0.0f; private boolean resize = true; public ShearFilter() { } public void setResize(boolean resize) { this.resize = resize; } public boolean isResize() { return resize; } public void setXAngle(float xangle) { this.xangle = xangle; initialize(); } public float getXAngle() { return xangle; } public void setYAngle(float yangle) { this.yangle = yangle; initialize(); } public float getYAngle() { return yangle; } private void initialize() { shx = (float)Math.sin(xangle); shy = (float)Math.sin(yangle); } protected void transformSpace(Rectangle r) { float tangent = (float)Math.tan(xangle); xoffset = -r.height * tangent; if (tangent < 0.0) tangent = -tangent; r.width = (int)(r.height * tangent + r.width + 0.999999f); tangent = (float)Math.tan(yangle); yoffset = -r.width * tangent; if (tangent < 0.0) tangent = -tangent; r.height = (int)(r.width * tangent + r.height + 0.999999f); } /* public void imageComplete(int status) { try { if (status == IMAGEERROR || status == IMAGEABORTED) { consumer.imageComplete(status); return; } int width = originalSpace.width; int height = originalSpace.height; float tangent = Math.tan(angle); if (tangent < 0.0) tangent = -tangent; int newWidth = (int)(height * tangent + width + 0.999999); int[] outPixels = new int[height*newWidth]; int inIndex = 0; int yOffset = 0; for (int y = 0; y < height; y++) { float newCol; if (angle >= 0.0) newCol = y * tangent; else newCol = (height-y) * tangent; int iNewCol = (int)newCol; float f = newCol - iNewCol; f = 1.0 - f; int outIndex = yOffset+iNewCol; int lastRGB = inPixels[inIndex]; for (int x = 0; x < width; x++) { int rgb = inPixels[inIndex]; outPixels[outIndex] = ImageMath.mixColors(f, lastRGB, rgb); lastRGB = rgb; inIndex++; outIndex++; } outPixels[outIndex] = ImageMath.mixColors(f, lastRGB, 0); yOffset += newWidth; } consumer.setPixels(0, 0, newWidth, height, defaultRGBModel, outPixels, 0, newWidth); consumer.imageComplete(status); inPixels = null; } catch (Exception e) { e.printStackTrace(); } } */ protected void transformInverse(int x, int y, float[] out) { out[0] = x + xoffset + (y * shx); out[1] = y + yoffset + (x * shy); } public String toString() { return "Distort/Shear..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/LinearColormap.java0000644000175000017500000000412010521402274022513 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; /** * A colormap which interpolates linearly between two colors. */ public class LinearColormap implements Colormap, java.io.Serializable { static final long serialVersionUID = 4256182891287368612L; private int color1; private int color2; /** * Construct a color map with a grayscale ramp from black to white */ public LinearColormap() { this(0xff000000, 0xffffffff); } /** * Construct a linear color map * @param color1 the color corresponding to value 0 in the colormap * @param color2 the color corresponding to value 1 in the colormap */ public LinearColormap(int color1, int color2) { this.color1 = color1; this.color2 = color2; } /** * Set the first color * @param color1 the color corresponding to value 0 in the colormap */ public void setColor1(int color1) { this.color1 = color1; } /** * Get the first color * @return the color corresponding to value 0 in the colormap */ public int getColor1() { return color1; } /** * Set the second color * @param color2 the color corresponding to value 1 in the colormap */ public void setColor2(int color2) { this.color2 = color2; } /** * Get the second color * @return the color corresponding to value 1 in the colormap */ public int getColor2() { return color2; } /** * Convert a value in the range 0..1 to an RGB color. * @param v a value in the range 0..1 * @return an RGB color */ public int getColor(float v) { return ImageMath.mixColors(ImageMath.clamp(v, 0, 1.0f), color1, color2); } } jhlabs-filters-2.0.235/com/jhlabs/image/Flush3DFilter.java0000644000175000017500000000300010521402272022214 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * This filter tries to apply the Swing "flush 3D" effect to the black lines in an image. */ public class Flush3DFilter extends WholeImageFilter { public Flush3DFilter() { } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] outPixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixel = inPixels[y*width+x]; if (pixel != 0xff000000 && y > 0 && x > 0) { int count = 0; if (inPixels[y*width+x-1] == 0xff000000) count++; if (inPixels[(y-1)*width+x] == 0xff000000) count++; if (inPixels[(y-1)*width+x-1] == 0xff000000) count++; if (count >= 2) pixel = 0xffffffff; } outPixels[index++] = pixel; } } return outPixels; } public String toString() { return "Stylize/Flush 3D..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/DissolveFilter.java0000644000175000017500000000360510521402272022547 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import java.util.*; /** * A filter which "dissolves" an image by thresholding the alpha channel with random numbers. */ public class DissolveFilter extends PointFilter { private float density = 1; private float softness = 0; private float minDensity, maxDensity; private Random randomNumbers; public DissolveFilter() { } /** * Set the density of the image in the range 0..1. * *arg density The density */ public void setDensity( float density ) { this.density = density; } public float getDensity() { return density; } /** * Set the density of the dissolve in the range 0..1. * *arg softness The softness */ public void setSoftness( float softness ) { this.softness = softness; } public float getSoftness() { return softness; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { float d = (1-density) * (1+softness); minDensity = d-softness; maxDensity = d; randomNumbers = new Random( 0 ); return super.filter( src, dst ); } public int filterRGB(int x, int y, int rgb) { int a = (rgb >> 24) & 0xff; float v = randomNumbers.nextFloat(); float f = ImageMath.smoothStep( minDensity, maxDensity, v ); return ((int)(a * f) << 24) | rgb & 0x00ffffff; } public String toString() { return "Stylize/Dissolve..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/EqualizeFilter.java0000644000175000017500000000366610521402272022545 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter to perform auto-equalization on an image. */ public class EqualizeFilter extends WholeImageFilter implements java.io.Serializable { protected int[][] lut; public EqualizeFilter() { } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { Histogram histogram = new Histogram(inPixels, width, height, 0, width); int i, j; if (histogram.getNumSamples() > 0) { float scale = 255.0f / histogram.getNumSamples(); lut = new int[3][256]; for (i = 0; i < 3; i++) { lut[i][0] = histogram.getFrequency(i, 0); for (j = 1; j < 256; j++) lut[i][j] = lut[i][j-1] + histogram.getFrequency(i, j); for (j = 0; j < 256; j++) lut[i][j] = (int)Math.round(lut[i][j]*scale); } } else lut = null; i = 0; for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { inPixels[i] = filterRGB(x, y, inPixels[i]); i++; } lut = null; return inPixels; } public int filterRGB(int x, int y, int rgb) { if (lut != null) { int a = rgb & 0xff000000; int r = lut[Histogram.RED][(rgb >> 16) & 0xff]; int g = lut[Histogram.GREEN][(rgb >> 8) & 0xff]; int b = lut[Histogram.BLUE][rgb & 0xff]; return a | (r << 16) | (g << 8) | b; } return rgb; } public String toString() { return "Colors/Equalize"; } } jhlabs-filters-2.0.235/com/jhlabs/image/LightFilter.java0000644000175000017500000004225610521402274022035 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.image.*; import com.jhlabs.math.*; import com.jhlabs.vecmath.*; import java.awt.*; import java.io.*; import java.util.*; public class LightFilter extends WholeImageFilter implements Serializable { public final static int COLORS_FROM_IMAGE = 0; public final static int COLORS_CONSTANT = 1; public final static int BUMPS_FROM_IMAGE = 0; public final static int BUMPS_FROM_IMAGE_ALPHA = 1; public final static int BUMPS_FROM_MAP = 2; public final static int BUMPS_FROM_BEVEL = 3; private float bumpHeight; private float bumpSoftness; private int bumpShape; private float viewDistance = 10000.0f; Material material; private Vector lights; private int colorSource = COLORS_FROM_IMAGE; private int bumpSource = BUMPS_FROM_IMAGE; private Function2D bumpFunction; private Image environmentMap; private int[] envPixels; private int envWidth = 1, envHeight = 1; // Temporary variables used to avoid per-pixel memory allocation while filtering private Vector3f l; private Vector3f v; private Vector3f n; private Color4f shadedColor; private Color4f diffuse_color; private Color4f specular_color; private Vector3f tmpv, tmpv2; public LightFilter() { lights = new Vector(); addLight(new DistantLight()); bumpHeight = 1.0f; bumpSoftness = 5.0f; bumpShape = 0; material = new Material(); l = new Vector3f(); v = new Vector3f(); n = new Vector3f(); shadedColor = new Color4f(); diffuse_color = new Color4f(); specular_color = new Color4f(); tmpv = new Vector3f(); tmpv2 = new Vector3f(); } public void setBumpFunction(Function2D bumpFunction) { this.bumpFunction = bumpFunction; } public Function2D getBumpFunction() { return bumpFunction; } public void setBumpHeight(float bumpHeight) { this.bumpHeight = bumpHeight; } public float getBumpHeight() { return bumpHeight; } public void setBumpSoftness(float bumpSoftness) { this.bumpSoftness = bumpSoftness; } public float getBumpSoftness() { return bumpSoftness; } public void setBumpShape(int bumpShape) { this.bumpShape = bumpShape; } public int getBumpShape() { return bumpShape; } public void setViewDistance(float viewDistance) { this.viewDistance = viewDistance; } public float getViewDistance() { return viewDistance; } public void setEnvironmentMap(BufferedImage environmentMap) { this.environmentMap = environmentMap; if (environmentMap != null) { envWidth = environmentMap.getWidth(); envHeight = environmentMap.getHeight(); envPixels = getRGB( environmentMap, 0, 0, envWidth, envHeight, null ); } else { envWidth = envHeight = 1; envPixels = null; } } public Image getEnvironmentMap() { return environmentMap; } public void setColorSource(int colorSource) { this.colorSource = colorSource; } public int getColorSource() { return colorSource; } public void setBumpSource(int bumpSource) { this.bumpSource = bumpSource; } public int getBumpSource() { return bumpSource; } public void setDiffuseColor(int diffuseColor) { material.diffuseColor = diffuseColor; } public int getDiffuseColor() { return material.diffuseColor; } public void addLight(Light light) { lights.addElement(light); } public void removeLight(Light light) { lights.removeElement(light); } public Vector getLights() { return lights; } protected final static float r255 = 1.0f/255.0f; protected void setFromRGB( Color4f c, int argb ) { c.set( ((argb >> 16) & 0xff) * r255, ((argb >> 8) & 0xff) * r255, (argb & 0xff) * r255, ((argb >> 24) & 0xff) * r255 ); } protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { int index = 0; int[] outPixels = new int[width * height]; float width45 = Math.abs(6.0f * bumpHeight); boolean invertBumps = bumpHeight < 0; Vector3f position = new Vector3f(0.0f, 0.0f, 0.0f); Vector3f viewpoint = new Vector3f((float)width / 2.0f, (float)height / 2.0f, viewDistance); Vector3f normal = new Vector3f(); Color4f envColor = new Color4f(); Color4f diffuseColor = new Color4f( new Color(material.diffuseColor) ); Color4f specularColor = new Color4f( new Color(material.specularColor) ); Function2D bump = bumpFunction; // Apply the bump softness if (bumpSource == BUMPS_FROM_IMAGE || bumpSource == BUMPS_FROM_IMAGE_ALPHA || bumpSource == BUMPS_FROM_MAP || bump == null) { if ( bumpSoftness != 0 ) { int bumpWidth = width; int bumpHeight = height; int[] bumpPixels = inPixels; if ( bumpSource == BUMPS_FROM_MAP && bumpFunction instanceof ImageFunction2D ) { ImageFunction2D if2d = (ImageFunction2D)bumpFunction; bumpWidth = if2d.getWidth(); bumpHeight = if2d.getHeight(); bumpPixels = if2d.getPixels(); } int [] tmpPixels = new int[bumpWidth * bumpHeight]; int [] softPixels = new int[bumpWidth * bumpHeight]; /* for (int i = 0; i < 3; i++ ) { BoxBlurFilter.blur( bumpPixels, tmpPixels, bumpWidth, bumpHeight, (int)bumpSoftness ); BoxBlurFilter.blur( tmpPixels, softPixels, bumpHeight, bumpWidth, (int)bumpSoftness ); } */ Kernel kernel = GaussianFilter.makeKernel( bumpSoftness ); GaussianFilter.convolveAndTranspose( kernel, bumpPixels, tmpPixels, bumpWidth, bumpHeight, true, GaussianFilter.WRAP_EDGES ); GaussianFilter.convolveAndTranspose( kernel, tmpPixels, softPixels, bumpHeight, bumpWidth, true, GaussianFilter.WRAP_EDGES ); bump = new ImageFunction2D(softPixels, bumpWidth, bumpHeight, ImageFunction2D.CLAMP, bumpSource == BUMPS_FROM_IMAGE_ALPHA); final Function2D bbump = bump; if ( bumpShape != 0 ) { bump = new Function2D() { private Function2D original = bbump; public float evaluate(float x, float y) { float v = original.evaluate( x, y ); switch ( bumpShape ) { case 1: v = v > 0.5f ? 0.5f : v; break; case 2: v = v < 0.5f ? 0.5f : v; break; case 3: v = ImageMath.triangle( v ); break; case 4: v = ImageMath.circleDown( v ); break; case 5: // v = ImageMath.circleDown( v ); v = ImageMath.gain( v, 0.75f ); break; } return v; } }; } } else if ( bumpSource != BUMPS_FROM_MAP ) bump = new ImageFunction2D(inPixels, width, height, ImageFunction2D.CLAMP, bumpSource == BUMPS_FROM_IMAGE_ALPHA); } float reflectivity = material.reflectivity; float areflectivity = (1-reflectivity); Vector3f v1 = new Vector3f(); Vector3f v2 = new Vector3f(); Vector3f n = new Vector3f(); Light[] lightsArray = new Light[lights.size()]; lights.copyInto(lightsArray); for (int i = 0; i < lightsArray.length; i++) lightsArray[i].prepare(width, height); float[][] heightWindow = new float[3][width]; for (int x = 0; x < width; x++) heightWindow[1][x] = width45*bump.evaluate(x, 0); // Loop through each source pixel for (int y = 0; y < height; y++) { boolean y0 = y > 0; boolean y1 = y < height-1; position.y = y; for (int x = 0; x < width; x++) heightWindow[2][x] = width45*bump.evaluate(x, y+1); for (int x = 0; x < width; x++) { boolean x0 = x > 0; boolean x1 = x < width-1; // Calculate the normal at this point if (bumpSource != BUMPS_FROM_BEVEL) { // Complicated and slower method // Calculate four normals using the gradients in +/- X/Y directions int count = 0; normal.x = normal.y = normal.z = 0; float m0 = heightWindow[1][x]; float m1 = x0 ? heightWindow[1][x-1]-m0 : 0; float m2 = y0 ? heightWindow[0][x]-m0 : 0; float m3 = x1 ? heightWindow[1][x+1]-m0 : 0; float m4 = y1 ? heightWindow[2][x]-m0 : 0; if (x0 && y1) { v1.x = -1.0f; v1.y = 0.0f; v1.z = m1; v2.x = 0.0f; v2.y = 1.0f; v2.z = m4; n.cross(v1, v2); n.normalize(); if (n.z < 0.0) n.z = -n.z; normal.add(n); count++; } if (x0 && y0) { v1.x = -1.0f; v1.y = 0.0f; v1.z = m1; v2.x = 0.0f; v2.y = -1.0f; v2.z = m2; n.cross(v1, v2); n.normalize(); if (n.z < 0.0) n.z = -n.z; normal.add(n); count++; } if (y0 && x1) { v1.x = 0.0f; v1.y = -1.0f; v1.z = m2; v2.x = 1.0f; v2.y = 0.0f; v2.z = m3; n.cross(v1, v2); n.normalize(); if (n.z < 0.0) n.z = -n.z; normal.add(n); count++; } if (x1 && y1) { v1.x = 1.0f; v1.y = 0.0f; v1.z = m3; v2.x = 0.0f; v2.y = 1.0f; v2.z = m4; n.cross(v1, v2); n.normalize(); if (n.z < 0.0) n.z = -n.z; normal.add(n); count++; } // Average the four normals normal.x /= count; normal.y /= count; normal.z /= count; } if (invertBumps) { normal.x = -normal.x; normal.y = -normal.y; } position.x = x; if (normal.z >= 0) { // Get the material colour at this point if (colorSource == COLORS_FROM_IMAGE) setFromRGB(diffuseColor, inPixels[index]); else setFromRGB(diffuseColor, material.diffuseColor); if (reflectivity != 0 && environmentMap != null) { //FIXME-too much normalizing going on here tmpv2.set(viewpoint); tmpv2.sub(position); tmpv2.normalize(); tmpv.set(normal); tmpv.normalize(); // Reflect tmpv.scale( 2.0f*tmpv.dot(tmpv2) ); tmpv.sub(v); tmpv.normalize(); setFromRGB(envColor, getEnvironmentMap(tmpv, inPixels, width, height));//FIXME-interpolate() diffuseColor.x = reflectivity*envColor.x + areflectivity*diffuseColor.x; diffuseColor.y = reflectivity*envColor.y + areflectivity*diffuseColor.y; diffuseColor.z = reflectivity*envColor.z + areflectivity*diffuseColor.z; } // Shade the pixel Color4f c = phongShade(position, viewpoint, normal, diffuseColor, specularColor, material, lightsArray); int alpha = inPixels[index] & 0xff000000; int rgb = ((int)(c.x * 255) << 16) | ((int)(c.y * 255) << 8) | (int)(c.z * 255); outPixels[index++] = alpha | rgb; } else outPixels[index++] = 0; } float[] t = heightWindow[0]; heightWindow[0] = heightWindow[1]; heightWindow[1] = heightWindow[2]; heightWindow[2] = t; } return outPixels; } public Color4f phongShade(Vector3f position, Vector3f viewpoint, Vector3f normal, Color4f diffuseColor, Color4f specularColor, Material material, Light[] lightsArray) { shadedColor.set(diffuseColor); shadedColor.scale(material.ambientIntensity); for (int i = 0; i < lightsArray.length; i++) { Light light = lightsArray[i]; n.set(normal); l.set(light.position); if (light.type != DISTANT) l.sub(position); l.normalize(); float nDotL = n.dot(l); if (nDotL >= 0.0) { float dDotL = 0; v.set(viewpoint); v.sub(position); v.normalize(); // Spotlight if (light.type == SPOT) { dDotL = light.direction.dot(l); if (dDotL < light.cosConeAngle) continue; } n.scale(2.0f * nDotL); n.sub(l); float rDotV = n.dot(v); float rv; if (rDotV < 0.0) rv = 0.0f; else // rv = (float)Math.pow(rDotV, material.highlight); rv = rDotV / (material.highlight - material.highlight*rDotV + rDotV); // Fast approximation to pow // Spotlight if (light.type == SPOT) { dDotL = light.cosConeAngle/dDotL; float e = dDotL; e *= e; e *= e; e *= e; e = (float)Math.pow(dDotL, light.focus*10)*(1 - e); rv *= e; nDotL *= e; } diffuse_color.set(diffuseColor); diffuse_color.scale(material.diffuseReflectivity); diffuse_color.x *= light.realColor.x * nDotL; diffuse_color.y *= light.realColor.y * nDotL; diffuse_color.z *= light.realColor.z * nDotL; specular_color.set(specularColor); specular_color.scale(material.specularReflectivity); specular_color.x *= light.realColor.x * rv; specular_color.y *= light.realColor.y * rv; specular_color.z *= light.realColor.z * rv; diffuse_color.add(specular_color); diffuse_color.clamp( 0, 1 ); shadedColor.add(diffuse_color); } } shadedColor.clamp( 0, 1 ); return shadedColor; } private int getEnvironmentMap(Vector3f normal, int[] inPixels, int width, int height) { if (environmentMap != null) { float angle = (float)Math.acos(-normal.y); float x, y; y = angle/ImageMath.PI; if (y == 0.0f || y == 1.0f) x = 0.0f; else { float f = normal.x/(float)Math.sin(angle); if (f > 1.0f) f = 1.0f; else if (f < -1.0f) f = -1.0f; x = (float)Math.acos(f)/ImageMath.PI; } // A bit of empirical scaling.... x = ImageMath.clamp(x * envWidth, 0, envWidth-1); y = ImageMath.clamp(y * envHeight, 0, envHeight-1); int ix = (int)x; int iy = (int)y; float xWeight = x-ix; float yWeight = y-iy; int i = envWidth*iy + ix; int dx = ix == envWidth-1 ? 0 : 1; int dy = iy == envHeight-1 ? 0 : envWidth; return ImageMath.bilinearInterpolate( xWeight, yWeight, envPixels[i], envPixels[i+dx], envPixels[i+dy], envPixels[i+dx+dy] ); } return 0; } public String toString() { return "Stylize/Light Effects..."; } public static class Material { int diffuseColor; int specularColor; float ambientIntensity; float diffuseReflectivity; float specularReflectivity; float highlight; float reflectivity; public Material() { ambientIntensity = 0.5f; diffuseReflectivity = 1.0f; specularReflectivity = 1.0f; highlight = 3.0f; reflectivity = 0.0f; diffuseColor = 0xff888888; specularColor = 0xffffffff; } public void setDiffuseColor(int diffuseColor) { this.diffuseColor = diffuseColor; } public int getDiffuseColor() { return diffuseColor; } } public final static int AMBIENT = 0; public final static int DISTANT = 1; public final static int POINT = 2; public final static int SPOT = 3; public static class Light implements Cloneable { int type = AMBIENT; Vector3f position; Vector3f direction; Color4f realColor = new Color4f(); int color = 0xffffffff; float intensity; float azimuth; float elevation; float focus = 0.5f; float centreX = 0.5f, centreY = 0.5f; float coneAngle = ImageMath.PI/6; float cosConeAngle; float distance = 100.0f; public Light() { this(270*ImageMath.PI/180.0f, 0.5235987755982988f, 1.0f); } public Light(float azimuth, float elevation, float intensity) { this.azimuth = azimuth; this.elevation = elevation; this.intensity = intensity; } public void setAzimuth(float azimuth) { this.azimuth = azimuth; } public float getAzimuth() { return azimuth; } public void setElevation(float elevation) { this.elevation = elevation; } public float getElevation() { return elevation; } public void setDistance(float distance) { this.distance = distance; } public float getDistance() { return distance; } public void setIntensity(float intensity) { this.intensity = intensity; } public float getIntensity() { return intensity; } public void setConeAngle(float coneAngle) { this.coneAngle = coneAngle; } public float getConeAngle() { return coneAngle; } public void setFocus(float focus) { this.focus = focus; } public float getFocus() { return focus; } public void setColor(int color) { this.color = color; } public int getColor() { return color; } public void setCentreX(float x) { centreX = x; } public float getCentreX() { return centreX; } public void setCentreY(float y) { centreY = y; } public float getCentreY() { return centreY; } public void prepare(int width, int height) { float lx = (float)(Math.cos(azimuth) * Math.cos(elevation)); float ly = (float)(Math.sin(azimuth) * Math.cos(elevation)); float lz = (float)Math.sin(elevation); direction = new Vector3f(lx, ly, lz); direction.normalize(); if (type != DISTANT) { lx *= distance; ly *= distance; lz *= distance; lx += width * centreX; ly += height * centreY; } position = new Vector3f(lx, ly, lz); realColor.set( new Color(color) ); realColor.scale(intensity); cosConeAngle = (float)Math.cos(coneAngle); } public Object clone() { try { Light copy = (Light)super.clone(); return copy; } catch (CloneNotSupportedException e) { return null; } } public String toString() { return "Light"; } } public class AmbientLight extends Light { public String toString() { return "Ambient Light"; } } public class PointLight extends Light { public PointLight() { type = POINT; } public String toString() { return "Point Light"; } } public class DistantLight extends Light { public DistantLight() { type = DISTANT; } public String toString() { return "Distant Light"; } } public class SpotLight extends Light { public SpotLight() { type = SPOT; } public String toString() { return "Spotlight"; } } } jhlabs-filters-2.0.235/com/jhlabs/image/DiffuseFilter.java0000644000175000017500000000321110521402272022335 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; import com.jhlabs.math.*; /** * This filter diffuses an image by moving its pixels in random directions. */ public class DiffuseFilter extends TransformFilter { public float[] sinTable, cosTable; public float scale = 4; public DiffuseFilter() { setEdgeAction(CLAMP); } public void setScale(float scale) { this.scale = scale; } public float getScale() { return scale; } protected void transformInverse(int x, int y, float[] out) { int angle = (int)(Math.random() * 255); float distance = (float)Math.random(); out[0] = x + distance * sinTable[angle]; out[1] = y + distance * cosTable[angle]; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { sinTable = new float[256]; cosTable = new float[256]; for (int i = 0; i < 256; i++) { float angle = ImageMath.TWO_PI*i/256f; sinTable[i] = (float)(scale*Math.sin(angle)); cosTable[i] = (float)(scale*Math.cos(angle)); } return super.filter( src, dst ); } public String toString() { return "Distort/Diffuse..."; } } jhlabs-filters-2.0.235/com/jhlabs/image/GrayFilter.java0000644000175000017500000000216310521402274021661 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.image; import java.awt.*; import java.awt.image.*; /** * A filter which 'grays out' an image by averaging each pixel with white. */ public class GrayFilter extends PointFilter { public GrayFilter() { canFilterIndexColorModel = true; } public int filterRGB(int x, int y, int rgb) { int a = rgb & 0xff000000; int r = (rgb >> 16) & 0xff; int g = (rgb >> 8) & 0xff; int b = rgb & 0xff; r = (r+255)/2; g = (g+255)/2; b = (b+255)/2; return a | (r << 16) | (g << 8) | b; } public String toString() { return "Colors/Gray Out"; } } jhlabs-filters-2.0.235/com/jhlabs/math/0000755000175000017500000000000010527103462016616 5ustar varunvarunjhlabs-filters-2.0.235/com/jhlabs/math/FBM.java0000644000175000017500000000340410521402274020063 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public class FBM implements Function2D { protected float[] exponents; protected float H; protected float lacunarity; protected float octaves; protected Function2D basis; public FBM(float H, float lacunarity, float octaves) { this(H, lacunarity, octaves, new Noise()); } public FBM(float H, float lacunarity, float octaves, Function2D basis) { this.H = H; this.lacunarity = lacunarity; this.octaves = octaves; this.basis = basis; exponents = new float[(int)octaves+1]; float frequency = 1.0f; for (int i = 0; i <= (int)octaves; i++) { exponents[i] = (float)Math.pow(frequency, -H); frequency *= lacunarity; } } public void setBasis(Function2D basis) { this.basis = basis; } public Function2D getBasisType() { return basis; } public float evaluate(float x, float y) { float value = 0.0f; float remainder; int i; // to prevent "cascading" effects x += 371; y += 529; for (i = 0; i < (int)octaves; i++) { value += basis.evaluate(x, y) * exponents[i]; x *= lacunarity; y *= lacunarity; } remainder = octaves - (int)octaves; if (remainder != 0) value += remainder * basis.evaluate(x, y) * exponents[i]; return value; } } jhlabs-filters-2.0.235/com/jhlabs/math/CompoundFunction2D.java0000644000175000017500000000156110521402274023141 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public abstract class CompoundFunction2D implements Function2D { protected Function2D basis; public CompoundFunction2D(Function2D basis) { this.basis = basis; } public void setBasis(Function2D basis) { this.basis = basis; } public Function2D getBasis() { return basis; } } jhlabs-filters-2.0.235/com/jhlabs/math/Noise.java0000644000175000017500000001636410521402274020545 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; import java.util.*; /** * Perlin Noise functions */ public class Noise implements Function1D, Function2D, Function3D { private static Random randomGenerator = new Random(); public float evaluate(float x) { return noise1(x); } public float evaluate(float x, float y) { return noise2(x, y); } public float evaluate(float x, float y, float z) { return noise3(x, y, z); } /** * Compute turbulence using Perlin noise. * @param x the x value * @param y the y value * @param octaves number of octaves of turbulence * @return turbulence value at (x,y) */ public static float turbulence2(float x, float y, float octaves) { float t = 0.0f; for (float f = 1.0f; f <= octaves; f *= 2) t += Math.abs(noise2(f * x, f * y)) / f; return t; } /** * Compute turbulence using Perlin noise. * @param x the x value * @param y the y value * @param octaves number of octaves of turbulence * @return turbulence value at (x,y) */ public static float turbulence3(float x, float y, float z, float octaves) { float t = 0.0f; for (float f = 1.0f; f <= octaves; f *= 2) t += Math.abs(noise3(f * x, f * y, f * z)) / f; return t; } private final static int B = 0x100; private final static int BM = 0xff; private final static int N = 0x1000; static int[] p = new int[B + B + 2]; static float[][] g3 = new float[B + B + 2][3]; static float[][] g2 = new float[B + B + 2][2]; static float[] g1 = new float[B + B + 2]; static boolean start = true; private static float sCurve(float t) { return t * t * (3.0f - 2.0f * t); } /** * Compute 1-dimensional Perlin noise. * @param x the x value * @return noise value at x in the range -1..1 */ public static float noise1(float x) { int bx0, bx1; float rx0, rx1, sx, t, u, v; if (start) { start = false; init(); } t = x + N; bx0 = ((int)t) & BM; bx1 = (bx0+1) & BM; rx0 = t - (int)t; rx1 = rx0 - 1.0f; sx = sCurve(rx0); u = rx0 * g1[p[bx0]]; v = rx1 * g1[p[bx1]]; return 2.3f*lerp(sx, u, v); } /** * Compute 2-dimensional Perlin noise. * @param x the x coordinate * @param y the y coordinate * @return noise value at (x,y) */ public static float noise2(float x, float y) { int bx0, bx1, by0, by1, b00, b10, b01, b11; float rx0, rx1, ry0, ry1, q[], sx, sy, a, b, t, u, v; int i, j; if (start) { start = false; init(); } t = x + N; bx0 = ((int)t) & BM; bx1 = (bx0+1) & BM; rx0 = t - (int)t; rx1 = rx0 - 1.0f; t = y + N; by0 = ((int)t) & BM; by1 = (by0+1) & BM; ry0 = t - (int)t; ry1 = ry0 - 1.0f; i = p[bx0]; j = p[bx1]; b00 = p[i + by0]; b10 = p[j + by0]; b01 = p[i + by1]; b11 = p[j + by1]; sx = sCurve(rx0); sy = sCurve(ry0); q = g2[b00]; u = rx0 * q[0] + ry0 * q[1]; q = g2[b10]; v = rx1 * q[0] + ry0 * q[1]; a = lerp(sx, u, v); q = g2[b01]; u = rx0 * q[0] + ry1 * q[1]; q = g2[b11]; v = rx1 * q[0] + ry1 * q[1]; b = lerp(sx, u, v); return 1.5f*lerp(sy, a, b); } /** * Compute 3-dimensional Perlin noise. * @param x the x coordinate * @param y the y coordinate * @param y the y coordinate * @return noise value at (x,y,z) */ public static float noise3(float x, float y, float z) { int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; float rx0, rx1, ry0, ry1, rz0, rz1, q[], sy, sz, a, b, c, d, t, u, v; int i, j; if (start) { start = false; init(); } t = x + N; bx0 = ((int)t) & BM; bx1 = (bx0+1) & BM; rx0 = t - (int)t; rx1 = rx0 - 1.0f; t = y + N; by0 = ((int)t) & BM; by1 = (by0+1) & BM; ry0 = t - (int)t; ry1 = ry0 - 1.0f; t = z + N; bz0 = ((int)t) & BM; bz1 = (bz0+1) & BM; rz0 = t - (int)t; rz1 = rz0 - 1.0f; i = p[bx0]; j = p[bx1]; b00 = p[i + by0]; b10 = p[j + by0]; b01 = p[i + by1]; b11 = p[j + by1]; t = sCurve(rx0); sy = sCurve(ry0); sz = sCurve(rz0); q = g3[b00 + bz0]; u = rx0 * q[0] + ry0 * q[1] + rz0 * q[2]; q = g3[b10 + bz0]; v = rx1 * q[0] + ry0 * q[1] + rz0 * q[2]; a = lerp(t, u, v); q = g3[b01 + bz0]; u = rx0 * q[0] + ry1 * q[1] + rz0 * q[2]; q = g3[b11 + bz0]; v = rx1 * q[0] + ry1 * q[1] + rz0 * q[2]; b = lerp(t, u, v); c = lerp(sy, a, b); q = g3[b00 + bz1]; u = rx0 * q[0] + ry0 * q[1] + rz1 * q[2]; q = g3[b10 + bz1]; v = rx1 * q[0] + ry0 * q[1] + rz1 * q[2]; a = lerp(t, u, v); q = g3[b01 + bz1]; u = rx0 * q[0] + ry1 * q[1] + rz1 * q[2]; q = g3[b11 + bz1]; v = rx1 * q[0] + ry1 * q[1] + rz1 * q[2]; b = lerp(t, u, v); d = lerp(sy, a, b); return 1.5f*lerp(sz, c, d); } public static float lerp(float t, float a, float b) { return a + t * (b - a); } private static void normalize2(float v[]) { float s = (float)Math.sqrt(v[0] * v[0] + v[1] * v[1]); v[0] = v[0] / s; v[1] = v[1] / s; } static void normalize3(float v[]) { float s = (float)Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); v[0] = v[0] / s; v[1] = v[1] / s; v[2] = v[2] / s; } private static int random() { return randomGenerator.nextInt() & 0x7fffffff; } private static void init() { int i, j, k; for (i = 0; i < B; i++) { p[i] = i; g1[i] = (float)((random() % (B + B)) - B) / B; for (j = 0; j < 2; j++) g2[i][j] = (float)((random() % (B + B)) - B) / B; normalize2(g2[i]); for (j = 0; j < 3; j++) g3[i][j] = (float)((random() % (B + B)) - B) / B; normalize3(g3[i]); } for (i = B-1; i >= 0; i--) { k = p[i]; p[i] = p[j = random() % B]; p[j] = k; } for (i = 0; i < B + 2; i++) { p[B + i] = p[i]; g1[B + i] = g1[i]; for (j = 0; j < 2; j++) g2[B + i][j] = g2[i][j]; for (j = 0; j < 3; j++) g3[B + i][j] = g3[i][j]; } } /** * Returns the minimum and maximum of a number of random values * of the given function. This is useful for making some stab at * normalising the function. */ public static float[] findRange(Function1D f, float[] minmax) { if (minmax == null) minmax = new float[2]; float min = 0, max = 0; // Some random numbers here... for (float x = -100; x < 100; x += 1.27139) { float n = f.evaluate(x); min = Math.min(min, n); max = Math.max(max, n); } minmax[0] = min; minmax[1] = max; return minmax; } /** * Returns the minimum and maximum of a number of random values * of the given function. This is useful for making some stab at * normalising the function. */ public static float[] findRange(Function2D f, float[] minmax) { if (minmax == null) minmax = new float[2]; float min = 0, max = 0; // Some random numbers here... for (float y = -100; y < 100; y += 10.35173) { for (float x = -100; x < 100; x += 10.77139) { float n = f.evaluate(x, y); min = Math.min(min, n); max = Math.max(max, n); } } minmax[0] = min; minmax[1] = max; return minmax; } } jhlabs-filters-2.0.235/com/jhlabs/math/BinaryFunction.java0000644000175000017500000000122210521402274022405 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public interface BinaryFunction { public boolean isBlack(int rgb); } jhlabs-filters-2.0.235/com/jhlabs/math/Function3D.java0000644000175000017500000000123710521402274021435 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public interface Function3D { public float evaluate(float x, float y, float z); } jhlabs-filters-2.0.235/com/jhlabs/math/CompositeFunction1D.java0000644000175000017500000000152210521402274023313 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public class CompositeFunction1D implements Function1D { private Function1D f1, f2; public CompositeFunction1D(Function1D f1, Function1D f2) { this.f1 = f1; this.f2 = f2; } public float evaluate(float v) { return f1.evaluate(f2.evaluate(v)); } } jhlabs-filters-2.0.235/com/jhlabs/math/VLNoise.java0000644000175000017500000000174310521402274021002 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public class VLNoise implements Function2D { private float distortion = 10.0f; public void setDistortion(float distortion) { this.distortion = distortion; } public float getDistortion() { return distortion; } public float evaluate(float x, float y) { float ox = Noise.noise2(x+0.5f, y) * distortion; float oy = Noise.noise2(x, y+0.5f) * distortion; return Noise.noise2(x+ox, y+oy); } } jhlabs-filters-2.0.235/com/jhlabs/math/BlackFunction.java0000644000175000017500000000130710521402274022201 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public class BlackFunction implements BinaryFunction { public boolean isBlack(int rgb) { return rgb == 0xff000000; } } jhlabs-filters-2.0.235/com/jhlabs/math/MathFunction1D.java0000644000175000017500000000262610521402274022250 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public class MathFunction1D implements Function1D { public final static int SIN = 1; public final static int COS = 2; public final static int TAN = 3; public final static int SQRT = 4; public final static int ASIN = -1; public final static int ACOS = -2; public final static int ATAN = -3; public final static int SQR = -4; private int operation; public MathFunction1D(int operation) { this.operation = operation; } public float evaluate(float v) { switch (operation) { case SIN: return (float)Math.sin(v); case COS: return (float)Math.cos(v); case TAN: return (float)Math.tan(v); case SQRT: return (float)Math.sqrt(v); case ASIN: return (float)Math.asin(v); case ACOS: return (float)Math.acos(v); case ATAN: return (float)Math.atan(v); case SQR: return v*v; } return v; } } jhlabs-filters-2.0.235/com/jhlabs/math/FractalSumFunction.java0000644000175000017500000000162610521402274023232 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public class FractalSumFunction extends CompoundFunction2D { private float octaves = 1.0f; public FractalSumFunction(Function2D basis) { super(basis); } public float evaluate(float x, float y) { float t = 0.0f; for (float f = 1.0f; f <= octaves; f *= 2) t += basis.evaluate(f * x, f * y) / f; return t; } } jhlabs-filters-2.0.235/com/jhlabs/math/ImageFunction2D.java0000644000175000017500000000706110521402274022400 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; import java.awt.*; import java.awt.image.*; import com.jhlabs.image.*; public class ImageFunction2D implements Function2D { public final static int ZERO = 0; public final static int CLAMP = 1; public final static int WRAP = 2; protected int[] pixels; protected int width; protected int height; protected int edgeAction = ZERO; protected boolean alpha = false; public ImageFunction2D(BufferedImage image) { this(image, false); } public ImageFunction2D(BufferedImage image, boolean alpha) { this(image, ZERO, alpha); } public ImageFunction2D(BufferedImage image, int edgeAction, boolean alpha) { init( getRGB( image, 0, 0, image.getWidth(), image.getHeight(), null), image.getWidth(), image.getHeight(), edgeAction, alpha); } public ImageFunction2D(int[] pixels, int width, int height, int edgeAction, boolean alpha) { init(pixels, width, height, edgeAction, alpha); } public ImageFunction2D(Image image) { this( image, ZERO, false ); } public ImageFunction2D(Image image, int edgeAction, boolean alpha) { PixelGrabber pg = new PixelGrabber(image, 0, 0, -1, -1, null, 0, -1); try { pg.grabPixels(); } catch (InterruptedException e) { throw new RuntimeException("interrupted waiting for pixels!"); } if ((pg.status() & ImageObserver.ABORT) != 0) { throw new RuntimeException("image fetch aborted"); } init((int[])pg.getPixels(), pg.getWidth(), pg.getHeight(), edgeAction, alpha); } /** * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance * penalty of BufferedImage.getRGB unmanaging the image. */ public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) { int type = image.getType(); if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB ) return (int [])image.getRaster().getDataElements( x, y, width, height, pixels ); return image.getRGB( x, y, width, height, pixels, 0, width ); } public void init(int[] pixels, int width, int height, int edgeAction, boolean alpha) { this.pixels = pixels; this.width = width; this.height = height; this.edgeAction = edgeAction; this.alpha = alpha; } public float evaluate(float x, float y) { int ix = (int)x; int iy = (int)y; if (edgeAction == WRAP) { ix = ImageMath.mod(ix, width); iy = ImageMath.mod(iy, height); } else if (ix < 0 || iy < 0 || ix >= width || iy >= height) { if (edgeAction == ZERO) return 0; if (ix < 0) ix = 0; else if (ix >= width) ix = width-1; if (iy < 0) iy = 0; else if (iy >= height) iy = height-1; } return alpha ? ((pixels[iy*width+ix] >> 24) & 0xff) / 255.0f : PixelUtils.brightness(pixels[iy*width+ix]) / 255.0f; } public void setEdgeAction(int edgeAction) { this.edgeAction = edgeAction; } public int getEdgeAction() { return edgeAction; } public int getWidth() { return width; } public int getHeight() { return height; } public int[] getPixels() { return pixels; } } jhlabs-filters-2.0.235/com/jhlabs/math/SCNoise.java0000644000175000017500000001171110521402274020762 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; import java.util.*; /** * Sparse Convolution Noise. This is computationally very expensive, but worth it. */ public class SCNoise implements Function1D, Function2D, Function3D { private static Random randomGenerator = new Random(); public float evaluate(float x) { return evaluate(x, .1f); } public float evaluate(float x, float y) { int i, j, k, h, n; int ix, iy; float sum = 0; float fx, fy, dx, dy, distsq; if (impulseTab == null) impulseTab = impulseTabInit(665); ix = floor(x); fx = x - ix; iy = floor(y); fy = y - iy; /* Perform the sparse convolution. */ int m = 2; for (i = -m; i <= m; i++) { for (j = -m; j <= m; j++) { /* Compute voxel hash code. */ h = perm[(ix+i + perm[(iy+j)&TABMASK])&TABMASK]; for (n = NIMPULSES; n > 0; n--, h = (h+1) & TABMASK) { /* Convolve filter and impulse. */ int h4 = h*4; dx = fx - (i + impulseTab[h4++]); dy = fy - (j + impulseTab[h4++]); distsq = dx*dx + dy*dy; sum += catrom2(distsq) * impulseTab[h4]; } } } return sum / NIMPULSES; } public float evaluate(float x, float y, float z) { int i, j, k, h, n; int ix, iy, iz; float sum = 0; float fx, fy, fz, dx, dy, dz, distsq; if (impulseTab == null) impulseTab = impulseTabInit(665); ix = floor(x); fx = x - ix; iy = floor(y); fy = y - iy; iz = floor(z); fz = z - iz; /* Perform the sparse convolution. */ int m = 2; for (i = -m; i <= m; i++) { for (j = -m; j <= m; j++) { for (k = -m; k <= m; k++) { /* Compute voxel hash code. */ h = perm[(ix+i + perm[(iy+j + perm[(iz+k)&TABMASK])&TABMASK])&TABMASK]; for (n = NIMPULSES; n > 0; n--, h = (h+1) & TABMASK) { /* Convolve filter and impulse. */ int h4 = h*4; dx = fx - (i + impulseTab[h4++]); dy = fy - (j + impulseTab[h4++]); dz = fz - (k + impulseTab[h4++]); distsq = dx*dx + dy*dy + dz*dz; sum += catrom2(distsq) * impulseTab[h4]; } } } } return sum / NIMPULSES; } public short[] perm = { 225,155,210,108,175,199,221,144,203,116, 70,213, 69,158, 33,252, 5, 82,173,133,222,139,174, 27, 9, 71, 90,246, 75,130, 91,191, 169,138, 2,151,194,235, 81, 7, 25,113,228,159,205,253,134,142, 248, 65,224,217, 22,121,229, 63, 89,103, 96,104,156, 17,201,129, 36, 8,165,110,237,117,231, 56,132,211,152, 20,181,111,239,218, 170,163, 51,172,157, 47, 80,212,176,250, 87, 49, 99,242,136,189, 162,115, 44, 43,124, 94,150, 16,141,247, 32, 10,198,223,255, 72, 53,131, 84, 57,220,197, 58, 50,208, 11,241, 28, 3,192, 62,202, 18,215,153, 24, 76, 41, 15,179, 39, 46, 55, 6,128,167, 23,188, 106, 34,187,140,164, 73,112,182,244,195,227, 13, 35, 77,196,185, 26,200,226,119, 31,123,168,125,249, 68,183,230,177,135,160,180, 12, 1,243,148,102,166, 38,238,251, 37,240,126, 64, 74,161, 40, 184,149,171,178,101, 66, 29, 59,146, 61,254,107, 42, 86,154, 4, 236,232,120, 21,233,209, 45, 98,193,114, 78, 19,206, 14,118,127, 48, 79,147, 85, 30,207,219, 54, 88,234,190,122, 95, 67,143,109, 137,214,145, 93, 92,100,245, 0,216,186, 60, 83,105, 97,204, 52 }; private final static int TABSIZE = 256; private final static int TABMASK = (TABSIZE-1); private final static int NIMPULSES = 3; private static float[] impulseTab; public static int floor(float x) { int ix = (int)x; if (x < 0 && x != ix) return ix-1; return ix; } private final static int SAMPRATE = 100; /* table entries per unit distance */ private final static int NENTRIES = (4*SAMPRATE+1); private static float[] table; public float catrom2(float d) { float x; int i; if (d >= 4) return 0; if (table == null) { table = new float[NENTRIES]; for (i = 0; i < NENTRIES; i++) { x = i/(float)SAMPRATE; x = (float)Math.sqrt(x); if (x < 1) table[i] = 0.5f * (2+x*x*(-5+x*3)); else table[i] = 0.5f * (4+x*(-8+x*(5-x))); } } d = d*SAMPRATE + 0.5f; i = floor(d); if (i >= NENTRIES) return 0; return table[i]; } static float[] impulseTabInit(int seed) { float[] impulseTab = new float[TABSIZE*4]; randomGenerator = new Random(seed); /* Set random number generator seed. */ for (int i = 0; i < TABSIZE; i++) { impulseTab[i++] = randomGenerator.nextFloat(); impulseTab[i++] = randomGenerator.nextFloat(); impulseTab[i++] = randomGenerator.nextFloat(); impulseTab[i++] = 1.0f - 2.0f*randomGenerator.nextFloat(); } return impulseTab; } } jhlabs-filters-2.0.235/com/jhlabs/math/MarbleFunction.java0000644000175000017500000000163110521402274022367 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public class MarbleFunction extends CompoundFunction2D { public MarbleFunction() { super(new TurbulenceFunction(new Noise(), 6)); } public MarbleFunction(Function2D basis) { super(basis); } public float evaluate(float x, float y) { return (float)Math.pow(0.5 * (Math.sin(8. * basis.evaluate(x, y)) + 1), 0.77); } } jhlabs-filters-2.0.235/com/jhlabs/math/TurbulenceFunction.java0000644000175000017500000000207210521402274023275 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public class TurbulenceFunction extends CompoundFunction2D { private float octaves; public TurbulenceFunction(Function2D basis, float octaves) { super(basis); this.octaves = octaves; } public void setOctaves(float octaves) { this.octaves = octaves; } public float getOctaves() { return octaves; } public float evaluate(float x, float y) { float t = 0.0f; for (float f = 1.0f; f <= octaves; f *= 2) t += Math.abs(basis.evaluate(f * x, f * y)) / f; return t; } } jhlabs-filters-2.0.235/com/jhlabs/math/Function2D.java0000644000175000017500000000122610521402274021432 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public interface Function2D { public float evaluate(float x, float y); } jhlabs-filters-2.0.235/com/jhlabs/math/RidgedFBM.java0000644000175000017500000000132510521402274021202 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public class RidgedFBM implements Function2D { public float evaluate(float x, float y) { return 1-Math.abs(Noise.noise2(x, y)); } } jhlabs-filters-2.0.235/com/jhlabs/math/CellularFunction2D.java0000644000175000017500000000651710521402274023126 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; import java.awt.image.*; import java.util.*; public class CellularFunction2D implements Function2D { public float distancePower = 2; public boolean cells = false; public boolean angular = false; private float[] coefficients = { 1, 0, 0, 0 }; private Random random = new Random(); private Point[] results = null; public CellularFunction2D() { results = new Point[2]; for (int j = 0; j < results.length; j++) results[j] = new Point(); } public void setCoefficient(int c, float v) { coefficients[c] = v; } public float getCoefficient(int c) { return coefficients[c]; } class Point { int index; float x, y; float distance; } private float checkCube(float x, float y, int cubeX, int cubeY, Point[] results) { random.setSeed(571*cubeX + 23*cubeY); int numPoints = 3 + random.nextInt() % 4; numPoints = 4; for (int i = 0; i < numPoints; i++) { float px = random.nextFloat(); float py = random.nextFloat(); float dx = Math.abs(x-px); float dy = Math.abs(y-py); float d; if (distancePower == 1.0f) d = dx + dy; else if (distancePower == 2.0f) d = (float)Math.sqrt(dx*dx + dy*dy); else d = (float)Math.pow(Math.pow(dx, distancePower) + Math.pow(dy, distancePower), 1/distancePower); // Insertion sort for (int j = 0; j < results.length; j++) { if (results[j].distance == Double.POSITIVE_INFINITY) { Point last = results[j]; last.distance = d; last.x = px; last.y = py; results[j] = last; break; } else if (d < results[j].distance) { Point last = results[results.length-1]; for (int k = results.length-1; k > j; k--) results[k] = results[k-1]; last.distance = d; last.x = px; last.y = py; results[j] = last; break; } } } return results[1].distance; } public float evaluate(float x, float y) { for (int j = 0; j < results.length; j++) results[j].distance = Float.POSITIVE_INFINITY; int ix = (int)x; int iy = (int)y; float fx = x-ix; float fy = y-iy; float d = checkCube(fx, fy, ix, iy, results); if (d > fy) d = checkCube(fx, fy+1, ix, iy-1, results); if (d > 1-fy) d = checkCube(fx, fy-1, ix, iy+1, results); if (d > fx) { checkCube(fx+1, fy, ix-1, iy, results); if (d > fy) d = checkCube(fx+1, fy+1, ix-1, iy-1, results); if (d > 1-fy) d = checkCube(fx+1, fy-1, ix-1, iy+1, results); } if (d > 1-fx) { d = checkCube(fx-1, fy, ix+1, iy, results); if (d > fy) d = checkCube(fx-1, fy+1, ix+1, iy-1, results); if (d > 1-fy) d = checkCube(fx-1, fy-1, ix+1, iy+1, results); } float t = 0; for (int i = 0; i < 2; i++) t += coefficients[i] * results[i].distance; if (angular) t += Math.atan2(fy-results[0].y, fx-results[0].x) / (2*Math.PI) + 0.5; return t; } } jhlabs-filters-2.0.235/com/jhlabs/math/Function1D.java0000644000175000017500000000121510521402274021427 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public interface Function1D { public float evaluate(float v); } jhlabs-filters-2.0.235/com/jhlabs/math/FFT.java0000644000175000017500000001111210521402274020071 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.math; public class FFT { // Weighting factors protected float[] w1; protected float[] w2; protected float[] w3; public FFT( int logN ) { // Prepare the weighting factors w1 = new float[logN]; w2 = new float[logN]; w3 = new float[logN]; int N = 1; for ( int k = 0; k < logN; k++ ) { N <<= 1; double angle = -2.0 * Math.PI / N; w1[k] = (float)Math.sin(0.5 * angle); w2[k] = -2.0f * w1[k] * w1[k]; w3[k] = (float)Math.sin(angle); } } private void scramble( int n, float[] real, float[] imag ) { int j = 0; for ( int i = 0; i < n; i++ ) { if ( i > j ) { float t; t = real[j]; real[j] = real[i]; real[i] = t; t = imag[j]; imag[j] = imag[i]; imag[i] = t; } int m = n >> 1; while (j >= m && m >= 2) { j -= m; m >>= 1; } j += m; } } private void butterflies( int n, int logN, int direction, float[] real, float[] imag ) { int N = 1; for ( int k = 0; k < logN; k++ ) { float w_re, w_im, wp_re, wp_im, temp_re, temp_im, wt; int half_N = N; N <<= 1; wt = direction * w1[k]; wp_re = w2[k]; wp_im = direction * w3[k]; w_re = 1.0f; w_im = 0.0f; for ( int offset = 0; offset < half_N; offset++ ) { for( int i = offset; i < n; i += N ) { int j = i + half_N; float re = real[j]; float im = imag[j]; temp_re = (w_re * re) - (w_im * im); temp_im = (w_im * re) + (w_re * im); real[j] = real[i] - temp_re; real[i] += temp_re; imag[j] = imag[i] - temp_im; imag[i] += temp_im; } wt = w_re; w_re = wt * wp_re - w_im * wp_im + w_re; w_im = w_im * wp_re + wt * wp_im + w_im; } } if ( direction == -1 ) { float nr = 1.0f / n; for ( int i = 0; i < n; i++ ) { real[i] *= nr; imag[i] *= nr; } } } public void transform1D( float[] real, float[] imag, int logN, int n, boolean forward ) { scramble( n, real, imag ); butterflies( n, logN, forward ? 1 : -1, real, imag ); } public void transform2D( float[] real, float[] imag, int cols, int rows, boolean forward ) { int log2cols = log2(cols); int log2rows = log2(rows); int n = Math.max(rows, cols); float[] rtemp = new float[n]; float[] itemp = new float[n]; // FFT the rows for ( int y = 0; y < rows; y++ ) { int offset = y*cols; System.arraycopy( real, offset, rtemp, 0, cols ); System.arraycopy( imag, offset, itemp, 0, cols ); transform1D(rtemp, itemp, log2cols, cols, forward); System.arraycopy( rtemp, 0, real, offset, cols ); System.arraycopy( itemp, 0, imag, offset, cols ); } // FFT the columns for ( int x = 0; x < cols; x++ ) { int index = x; for ( int y = 0; y < rows; y++ ) { rtemp[y] = real[index]; itemp[y] = imag[index]; index += cols; } transform1D(rtemp, itemp, log2rows, rows, forward); index = x; for ( int y = 0; y < rows; y++ ) { real[index] = rtemp[y]; imag[index] = itemp[y]; index += cols; } } } private int log2( int n ) { int m = 1; int log2n = 0; while (m < n) { m *= 2; log2n++; } return m == n ? log2n : -1; } } jhlabs-filters-2.0.235/com/jhlabs/composite/0000755000175000017500000000000010527103462017667 5ustar varunvarunjhlabs-filters-2.0.235/com/jhlabs/composite/DarkenComposite.java0000644000175000017500000000403010521402272023611 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class DarkenComposite extends RGBComposite { public DarkenComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; dor = dir < sr ? dir : sr; dog = dig < sg ? dig : sg; dob = dib < sb ? dib : sb; float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/MiscCompositeContext.java0000644000175000017500000002117610521402272024657 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.awt.color.*; import java.net.*; import java.io.*; public class MiscCompositeContext implements CompositeContext { private int rule; private float alpha; private ColorModel srcColorModel; private ColorModel dstColorModel; private ColorSpace srcColorSpace; private ColorSpace dstColorSpace; private boolean srcNeedsConverting; private boolean dstNeedsConverting; public MiscCompositeContext(int rule, float alpha, ColorModel srcColorModel, ColorModel dstColorModel) { this.rule = rule; this.alpha = alpha; this.srcColorModel = srcColorModel; this.dstColorModel = dstColorModel; this.srcColorSpace = srcColorModel.getColorSpace(); this.dstColorSpace = dstColorModel.getColorSpace(); ColorModel srgbCM = ColorModel.getRGBdefault(); // srcNeedsConverting = !srcColorModel.equals(srgbCM); // dstNeedsConverting = !dstColorModel.equals(srgbCM); } public void dispose() { } // Multiply two numbers in the range 0..255 such that 255*255=255 static int multiply255( int a, int b ) { int t = a * b + 0x80; return ((t >> 8) + t) >> 8; } static int clamp( int a ) { return a < 0 ? 0 : a > 255 ? 255 : a; } public void compose(Raster src, Raster dstIn, WritableRaster dstOut) { float a=0, ac=0; float alpha = this.alpha; int t; float[] sHsv = null, diHsv = null, doHsv = null; switch ( rule ) { case MiscComposite.HUE: case MiscComposite.SATURATION: case MiscComposite.VALUE: case MiscComposite.COLOR: sHsv = new float[3]; diHsv = new float[3]; doHsv = new float[3]; break; } int[] srcPix = null; int[] dstPix = null; int x = dstOut.getMinX(); int w = dstOut.getWidth(); int y0 = dstOut.getMinY(); int y1 = y0 + dstOut.getHeight(); for ( int y = y0; y < y1; y++ ) { srcPix = src.getPixels(x, y, w, 1, srcPix); dstPix = dstIn.getPixels(x, y, w, 1, dstPix); int i = 0; int end = w*4; while ( i < end ) { int sr = srcPix[i]; int dir = dstPix[i]; int sg = srcPix[i+1]; int dig = dstPix[i+1]; int sb = srcPix[i+2]; int dib = dstPix[i+2]; int sa = srcPix[i+3]; int dia = dstPix[i+3]; int dor, dog, dob, doa; switch ( rule ) { case MiscComposite.ADD: default: dor = dir + sr; if ( dor > 255 ) dor = 255; dog = dig + sg; if ( dog > 255 ) dog = 255; dob = dib + sb; if ( dob > 255 ) dob = 255; break; case MiscComposite.SUBTRACT: dor = dir - sr; if ( dor < 0 ) dor = 0; dog = dig - sg; if ( dog < 0 ) dog = 0; dob = dib - sb; if ( dob < 0 ) dob = 0; break; case MiscComposite.DIFFERENCE: dor = dir - sr; if ( dor < 0 ) dor = -dor; dog = dig - sg; if ( dog < 0 ) dog = -dog; dob = dib - sb; if ( dob < 0 ) dob = -dob; break; case MiscComposite.MULTIPLY: t = dir * sr + 0x80; dor = ((t >> 8) + t) >> 8; t = dig * sg + 0x80; dog = ((t >> 8) + t) >> 8; t = dib * sb + 0x80; dob = ((t >> 8) + t) >> 8; break; case MiscComposite.SCREEN: t = (255-dir) * (255-sr) + 0x80; dor = 255 - ( ((t >> 8) + t) >> 8 ); t = (255-dig) * (255-sg) + 0x80; dog = 255 - ( ((t >> 8) + t) >> 8 ); t = (255-dib) * (255-sb) + 0x80; dob = 255 - ( ((t >> 8) + t) >> 8 ); break; case MiscComposite.OVERLAY: if ( dir < 128 ) { t = dir * sr + 0x80; dor = 2 * (((t >> 8) + t) >> 8); } else { t = (255-dir) * (255-sr) + 0x80; dor = 2 * (255 - ( ((t >> 8) + t) >> 8 )); } if ( dig < 128 ) { t = dig * sg + 0x80; dog = 2 * (((t >> 8) + t) >> 8); } else { t = (255-dig) * (255-sg) + 0x80; dog = 2 * (255 - ( ((t >> 8) + t) >> 8 )); } if ( dib < 128 ) { t = dib * sb + 0x80; dob = 2 * (((t >> 8) + t) >> 8); } else { t = (255-dib) * (255-sb) + 0x80; dob = 2 * (255 - ( ((t >> 8) + t) >> 8 )); } break; case MiscComposite.DARKEN: dor = dir < sr ? dir : sr; dog = dig < sg ? dig : sg; dob = dib < sb ? dib : sb; break; case MiscComposite.LIGHTEN: dor = dir > sr ? dir : sr; dog = dig > sg ? dig : sg; dob = dib > sb ? dib : sb; break; case MiscComposite.AVERAGE: dor = (dir + sr) / 2; dog = (dig + sg) / 2; dob = (dib + sb) / 2; break; case MiscComposite.HUE: case MiscComposite.SATURATION: case MiscComposite.VALUE: case MiscComposite.COLOR: Color.RGBtoHSB(sr, sg, sb, sHsv); Color.RGBtoHSB(dir, dig, dib, diHsv); switch(rule) { case MiscComposite.HUE: doHsv[0] = sHsv[0]; doHsv[1] = diHsv[1]; doHsv[2] = diHsv[2]; break; case MiscComposite.SATURATION: doHsv[0] = diHsv[0]; doHsv[1] = sHsv[1]; doHsv[2] = diHsv[2]; break; case MiscComposite.VALUE: doHsv[0] = diHsv[0]; doHsv[1] = diHsv[1]; doHsv[2] = sHsv[2]; break; case MiscComposite.COLOR: doHsv[0] = sHsv[0]; doHsv[1] = sHsv[1]; doHsv[2] = diHsv[2]; break; } int doRGB = Color.HSBtoRGB(doHsv[0], doHsv[1], doHsv[2]); dor = (doRGB&0xff0000)>>16; dog = (doRGB&0xff00)>>8; dob = (doRGB&0xff); break; case MiscComposite.BURN: if (dir != 255) dor = clamp(255-(((int)(255-sr) << 8) / (dir+1))); else dor = sr; if (dig != 255) dog = clamp(255-(((int)(255-sg) << 8) / (dig+1))); else dog = sg; if (dib != 255) dob = clamp(255-(((int)(255-sb) << 8) / (dib+1))); else dob = sb; break; case MiscComposite.COLOR_BURN: if (sr != 0) dor = Math.max(255 - (((int)(255-dir) << 8) / sr), 0); else dor = sr; if (sg != 0) dog = Math.max(255 - (((int)(255-dig) << 8) / sg), 0); else dog = sg; if (sb != 0) dob = Math.max(255 - (((int)(255-dib) << 8) / sb), 0); else dob = sb; break; case MiscComposite.DODGE: dor = clamp((sr << 8) / (256-dir)); dog = clamp((sg << 8) / (256-dig)); dob = clamp((sb << 8) / (256-dib)); break; case MiscComposite.COLOR_DODGE: if (sr != 255) dor = Math.min((dir << 8) / (255-sr), 255); else dor = sr; if (sg != 255) dog = Math.min((dig << 8) / (255-sg), 255); else dog = sg; if (sb != 255) dob = Math.min((dib << 8) / (255-sb), 255); else dob = sb; break; case MiscComposite.SOFT_LIGHT: int d; d = multiply255(sr, dir); dor = d + multiply255(dir, 255 - multiply255(255-dir, 255-sr)-d); d = multiply255(sg, dig); dog = d + multiply255(dig, 255 - multiply255(255-dig, 255-sg)-d); d = multiply255(sb, dib); dob = d + multiply255(dib, 255 - multiply255(255-dib, 255-sb)-d); break; case MiscComposite.HARD_LIGHT: if (sr > 127) dor = 255 - 2*multiply255(255 - sr, 255 - dir); else dor = 2*multiply255(sr, dir); if (sg > 127) dog = 255 - 2*multiply255(255 - sg, 255 - dig); else dog = 2*multiply255(sg, dig); if (sb > 127) dob = 255 - 2*multiply255(255 - sb, 255 - dib); else dob = 2*multiply255(sb, dib); break; case MiscComposite.PIN_LIGHT: dor = sr > 127 ? Math.max(sr, dir) : Math.min(sr, dir); dog = sg > 127 ? Math.max(sg, dig) : Math.min(sg, dig); dob = sb > 127 ? Math.max(sb, dib) : Math.min(sb, dib); break; case MiscComposite.EXCLUSION: dor = dir+multiply255(sr, (255-dir-dir)); dog = dig+multiply255(sg, (255-dig-dig)); dob = dib+multiply255(sb, (255-dib-dib)); break; case MiscComposite.NEGATION: dor = 255 - Math.abs(255-sr-dir); dog = 255 - Math.abs(255-sg-dig); dob = 255 - Math.abs(255-sb-dib); break; } a = alpha*sa/255f; ac = 1-a; dstPix[i] = (int)(a*dor + ac*dir); dstPix[i+1] = (int)(a*dog + ac*dig); dstPix[i+2] = (int)(a*dob + ac*dib); dstPix[i+3] = (int)(sa*alpha + dia*ac); i += 4; } dstOut.setPixels(x, y, w, 1, dstPix); } } } jhlabs-filters-2.0.235/com/jhlabs/composite/DifferenceComposite.java0000644000175000017500000000427410521402272024451 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class DifferenceComposite extends RGBComposite { public DifferenceComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; dor = dir - sr; if ( dor < 0 ) dor = -dor; dog = dig - sg; if ( dog < 0 ) dog = -dog; dob = dib - sb; if ( dob < 0 ) dob = -dob; float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/MiscComposite.java0000644000175000017500000001213510521402272023305 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class MiscComposite implements Composite { public final static int BLEND = 0; public final static int ADD = 1; public final static int SUBTRACT = 2; public final static int DIFFERENCE = 3; public final static int MULTIPLY = 4; public final static int DARKEN = 5; public final static int BURN = 6; public final static int COLOR_BURN = 7; public final static int SCREEN = 8; public final static int LIGHTEN = 9; public final static int DODGE = 10; public final static int COLOR_DODGE = 11; public final static int HUE = 12; public final static int SATURATION = 13; public final static int VALUE = 14; public final static int COLOR = 15; public final static int OVERLAY = 16; public final static int SOFT_LIGHT = 17; public final static int HARD_LIGHT = 18; public final static int PIN_LIGHT = 19; public final static int EXCLUSION = 20; public final static int NEGATION = 21; public final static int AVERAGE = 22; public final static int STENCIL = 23; public final static int SILHOUETTE = 24; private static final int MIN_RULE = BLEND; private static final int MAX_RULE = SILHOUETTE; public static String[] RULE_NAMES = { "Normal", "Add", "Subtract", "Difference", "Multiply", "Darken", "Burn", "Color Burn", "Screen", "Lighten", "Dodge", "Color Dodge", "Hue", "Saturation", "Brightness", "Color", "Overlay", "Soft Light", "Hard Light", "Pin Light", "Exclusion", "Negation", "Average", "Stencil", "Silhouette", }; protected float extraAlpha; protected int rule; private MiscComposite(int rule) { this(rule, 1.0f); } private MiscComposite(int rule, float alpha) { if (alpha < 0.0f || alpha > 1.0f) throw new IllegalArgumentException("alpha value out of range"); if (rule < MIN_RULE || rule > MAX_RULE) throw new IllegalArgumentException("unknown composite rule"); this.rule = rule; this.extraAlpha = alpha; } public static Composite getInstance(int rule, float alpha) { switch ( rule ) { case MiscComposite.BLEND: return AlphaComposite.getInstance( AlphaComposite.SRC_OVER, alpha ); case MiscComposite.ADD: return new AddComposite( alpha ); case MiscComposite.SUBTRACT: return new SubtractComposite( alpha ); case MiscComposite.DIFFERENCE: return new DifferenceComposite( alpha ); case MiscComposite.MULTIPLY: return new MultiplyComposite( alpha ); case MiscComposite.DARKEN: return new DarkenComposite( alpha ); case MiscComposite.BURN: return new BurnComposite( alpha ); case MiscComposite.COLOR_BURN: return new ColorBurnComposite( alpha ); case MiscComposite.SCREEN: return new ScreenComposite( alpha ); case MiscComposite.LIGHTEN: return new LightenComposite( alpha ); case MiscComposite.DODGE: return new DodgeComposite( alpha ); case MiscComposite.COLOR_DODGE: return new ColorDodgeComposite( alpha ); case MiscComposite.HUE: return new HueComposite( alpha ); case MiscComposite.SATURATION: return new SaturationComposite( alpha ); case MiscComposite.VALUE: return new ValueComposite( alpha ); case MiscComposite.COLOR: return new ColorComposite( alpha ); case MiscComposite.OVERLAY: return new OverlayComposite( alpha ); case MiscComposite.SOFT_LIGHT: return new SoftLightComposite( alpha ); case MiscComposite.HARD_LIGHT: return new HardLightComposite( alpha ); case MiscComposite.PIN_LIGHT: return new PinLightComposite( alpha ); case MiscComposite.EXCLUSION: return new ExclusionComposite( alpha ); case MiscComposite.NEGATION: return new NegationComposite( alpha ); case MiscComposite.AVERAGE: return new AverageComposite( alpha ); case MiscComposite.STENCIL: return AlphaComposite.getInstance( AlphaComposite.DST_IN, alpha ); case MiscComposite.SILHOUETTE: return AlphaComposite.getInstance( AlphaComposite.DST_OUT, alpha ); } return new MiscComposite(rule, alpha); } public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) { return new MiscCompositeContext( rule, extraAlpha, srcColorModel, dstColorModel ); } public float getAlpha() { return extraAlpha; } public int getRule() { return rule; } public int hashCode() { return (Float.floatToIntBits(extraAlpha) * 31 + rule); } public boolean equals(Object o) { if (!(o instanceof MiscComposite)) return false; MiscComposite c = (MiscComposite)o; if (rule != c.rule) return false; if (extraAlpha != c.extraAlpha) return false; return true; } } jhlabs-filters-2.0.235/com/jhlabs/composite/RGBComposite.java0000644000175000017500000000542210521402272023025 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public abstract class RGBComposite implements Composite { protected float extraAlpha; public RGBComposite() { this( 1.0f ); } public RGBComposite( float alpha ) { if ( alpha < 0.0f || alpha > 1.0f ) throw new IllegalArgumentException("RGBComposite: alpha must be between 0 and 1"); this.extraAlpha = alpha; } public float getAlpha() { return extraAlpha; } public int hashCode() { return Float.floatToIntBits(extraAlpha); } public boolean equals(Object o) { if (!(o instanceof RGBComposite)) return false; RGBComposite c = (RGBComposite)o; if ( extraAlpha != c.extraAlpha ) return false; return true; } public abstract static class RGBCompositeContext implements CompositeContext { private float alpha; private ColorModel srcColorModel; private ColorModel dstColorModel; public RGBCompositeContext( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { this.alpha = alpha; this.srcColorModel = srcColorModel; this.dstColorModel = dstColorModel; } public void dispose() { } // Multiply two numbers in the range 0..255 such that 255*255=255 static int multiply255( int a, int b ) { int t = a * b + 0x80; return ((t >> 8) + t) >> 8; } static int clamp( int a ) { return a < 0 ? 0 : a > 255 ? 255 : a; } public abstract void composeRGB( int[] src, int[] dst, float alpha ); public void compose( Raster src, Raster dstIn, WritableRaster dstOut ) { float alpha = this.alpha; int[] srcPix = null; int[] dstPix = null; int x = dstOut.getMinX(); int w = dstOut.getWidth(); int y0 = dstOut.getMinY(); int y1 = y0 + dstOut.getHeight(); for ( int y = y0; y < y1; y++ ) { srcPix = src.getPixels( x, y, w, 1, srcPix ); dstPix = dstIn.getPixels( x, y, w, 1, dstPix ); composeRGB( srcPix, dstPix, alpha ); dstOut.setPixels( x, y, w, 1, dstPix ); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/SaturationComposite.java0000644000175000017500000000452010521402272024542 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class SaturationComposite extends RGBComposite { public SaturationComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { private float[] sHSB = new float[3]; private float[] dHSB = new float[3]; public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; Color.RGBtoHSB( sr, sg, sb, sHSB ); Color.RGBtoHSB( dir, dig, dib, dHSB ); dHSB[1] = sHSB[1]; int doRGB = Color.HSBtoRGB( dHSB[0], dHSB[1], dHSB[2] ); dor = (doRGB & 0xff0000) >> 16; dog = (doRGB & 0xff00) >> 8; dob = (doRGB & 0xff); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/HardLightComposite.java0000644000175000017500000000463010521402272024261 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class HardLightComposite extends RGBComposite { public HardLightComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; if (sr > 127) dor = 255 - 2*multiply255(255 - sr, 255 - dir); else dor = 2*multiply255(sr, dir); if (sg > 127) dog = 255 - 2*multiply255(255 - sg, 255 - dig); else dog = 2*multiply255(sg, dig); if (sb > 127) dob = 255 - 2*multiply255(255 - sb, 255 - dib); else dob = 2*multiply255(sb, dib); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/HueComposite.java0000644000175000017500000000450210521402272023132 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class HueComposite extends RGBComposite { public HueComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { private float[] sHSB = new float[3]; private float[] dHSB = new float[3]; public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; Color.RGBtoHSB( sr, sg, sb, sHSB ); Color.RGBtoHSB( dir, dig, dib, dHSB ); dHSB[0] = sHSB[0]; int doRGB = Color.HSBtoRGB( dHSB[0], dHSB[1], dHSB[2] ); dor = (doRGB & 0xff0000) >> 16; dog = (doRGB & 0xff00) >> 8; dob = (doRGB & 0xff); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/BurnComposite.java0000644000175000017500000000454110521402272023322 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class BurnComposite extends RGBComposite { public BurnComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; if (dir != 255) dor = clamp(255-(((int)(255-sr) << 8) / (dir+1))); else dor = sr; if (dig != 255) dog = clamp(255-(((int)(255-sg) << 8) / (dig+1))); else dog = sg; if (dib != 255) dob = clamp(255-(((int)(255-sb) << 8) / (dib+1))); else dob = sb; float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/SoftLightComposite.java0000644000175000017500000000445010521402272024316 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class SoftLightComposite extends RGBComposite { public SoftLightComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; int d; d = multiply255(sr, dir); dor = d + multiply255(dir, 255 - multiply255(255-dir, 255-sr)-d); d = multiply255(sg, dig); dog = d + multiply255(dig, 255 - multiply255(255-dig, 255-sg)-d); d = multiply255(sb, dib); dob = d + multiply255(dib, 255 - multiply255(255-dib, 255-sb)-d); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/ValueComposite.java0000644000175000017500000000450610521402272023471 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class ValueComposite extends RGBComposite { public ValueComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { private float[] sHSB = new float[3]; private float[] dHSB = new float[3]; public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; Color.RGBtoHSB( sr, sg, sb, sHSB ); Color.RGBtoHSB( dir, dig, dib, dHSB ); dHSB[2] = sHSB[2]; int doRGB = Color.HSBtoRGB( dHSB[0], dHSB[1], dHSB[2] ); dor = (doRGB & 0xff0000) >> 16; dog = (doRGB & 0xff00) >> 8; dob = (doRGB & 0xff); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/ScreenComposite.java0000644000175000017500000000431510521402272023632 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class ScreenComposite extends RGBComposite { public ScreenComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; int t = (255-dir) * (255-sr) + 0x80; dor = 255 - ( ((t >> 8) + t) >> 8 ); t = (255-dig) * (255-sg) + 0x80; dog = 255 - ( ((t >> 8) + t) >> 8 ); t = (255-dib) * (255-sb) + 0x80; dob = 255 - ( ((t >> 8) + t) >> 8 ); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/OverlayComposite.java0000644000175000017500000000542010521402272024032 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class OverlayComposite extends RGBComposite { public OverlayComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; int t; if ( dir < 128 ) { t = dir * sr + 0x80; dor = 2 * (((t >> 8) + t) >> 8); } else { t = (255-dir) * (255-sr) + 0x80; dor = 2 * (255 - ( ((t >> 8) + t) >> 8 )); } if ( dig < 128 ) { t = dig * sg + 0x80; dog = 2 * (((t >> 8) + t) >> 8); } else { t = (255-dig) * (255-sg) + 0x80; dog = 2 * (255 - ( ((t >> 8) + t) >> 8 )); } if ( dib < 128 ) { t = dib * sb + 0x80; dob = 2 * (((t >> 8) + t) >> 8); } else { t = (255-dib) * (255-sb) + 0x80; dob = 2 * (255 - ( ((t >> 8) + t) >> 8 )); } float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/ExclusionComposite.java0000644000175000017500000000411310521402272024360 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class ExclusionComposite extends RGBComposite { public ExclusionComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; dor = dir+multiply255(sr, (255-dir-dir)); dog = dig+multiply255(sg, (255-dig-dig)); dob = dib+multiply255(sb, (255-dib-dib)); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/ContourComposite.java0000644000175000017500000000566510521402272024055 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; import java.awt.color.*; /** * A special Composite used for drawing "marching ants". It draws the ants at the 127 contour of the alpha channel of the source. * This can only be used on TYPE_INT_RGBA images. */ public final class ContourComposite implements Composite { private int offset; public ContourComposite( int offset ) { this.offset = offset; } public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) { return new ContourCompositeContext( offset, srcColorModel, dstColorModel ); } public int hashCode() { return 0; } public boolean equals(Object o) { if (!(o instanceof ContourComposite)) return false; return true; } } class ContourCompositeContext implements CompositeContext { private int offset; public ContourCompositeContext( int offset, ColorModel srcColorModel, ColorModel dstColorModel ) { this.offset = offset; } public void dispose() { } public void compose(Raster src, Raster dstIn, WritableRaster dstOut) { int x = src.getMinX(); int y = src.getMinY(); int w = src.getWidth(); int h = src.getHeight(); int[] srcPix = null; int[] srcPix2 = null; int[] dstInPix = null; int[] dstOutPix = new int[w*4]; for ( int i = 0; i < h; i++ ) { srcPix = src.getPixels(x, y, w, 1, srcPix); dstInPix = dstIn.getPixels(x, y, w, 1, dstInPix); int lastAlpha = 0; int k = 0; for ( int j = 0; j < w; j++ ) { int alpha = srcPix[k+3]; int alphaAbove = i != 0 ? srcPix2[k+3] : alpha; if ( i != 0 && j != 0 && ((alpha ^ lastAlpha) & 0x80) != 0 || ((alpha ^ alphaAbove) & 0x80) != 0 ) { if ((offset+i+j)%10 > 4) { dstOutPix[k] = 0x00; dstOutPix[k+1] = 0x00; dstOutPix[k+2] = 0x00; } else { dstOutPix[k] = 0xff; dstOutPix[k+1] = 0xff; dstOutPix[k+2] = 0x7f; } dstOutPix[k+3] = 0xff; } else { dstOutPix[k] = dstInPix[k]; dstOutPix[k+1] = dstInPix[k+1]; dstOutPix[k+2] = dstInPix[k+2]; // if ( dstOut == dstIn ) dstOutPix[k] = 0xff; dstOutPix[k+1] = 0; dstOutPix[k+2] = 0; dstOutPix[k+3] = 0; // else // dstOutPix[k+3] = dstInPix[k+3]; } lastAlpha = alpha; k += 4; } dstOut.setPixels(x, y, w, 1, dstOutPix); int[] t = srcPix; srcPix = srcPix2; srcPix2 = t; y++; } } } jhlabs-filters-2.0.235/com/jhlabs/composite/ColorComposite.java0000644000175000017500000000455110521402272023473 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class ColorComposite extends RGBComposite { public ColorComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { private float[] sHSB = new float[3]; private float[] dHSB = new float[3]; public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; Color.RGBtoHSB( sr, sg, sb, sHSB ); Color.RGBtoHSB( dir, dig, dib, dHSB ); dHSB[0] = sHSB[0]; dHSB[1] = sHSB[1]; int doRGB = Color.HSBtoRGB( dHSB[0], dHSB[1], dHSB[2] ); dor = (doRGB & 0xff0000) >> 16; dog = (doRGB & 0xff00) >> 8; dob = (doRGB & 0xff); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/PinLightComposite.java0000644000175000017500000000416310521402272024132 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class PinLightComposite extends RGBComposite { public PinLightComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; dor = sr > 127 ? Math.max(sr, dir) : Math.min(sr, dir); dog = sg > 127 ? Math.max(sg, dig) : Math.min(sg, dig); dob = sb > 127 ? Math.max(sb, dib) : Math.min(sb, dib); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/AddComposite.java0000644000175000017500000000426110521402272023103 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class AddComposite extends RGBComposite { public AddComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; dor = dir + sr; if ( dor > 255 ) dor = 255; dog = dig + sg; if ( dog > 255 ) dog = 255; dob = dib + sb; if ( dob > 255 ) dob = 255; float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/ColorBurnComposite.java0000644000175000017500000000455610521402272024327 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class ColorBurnComposite extends RGBComposite { public ColorBurnComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; if (sr != 0) dor = Math.max(255 - (((int)(255-dir) << 8) / sr), 0); else dor = sr; if (sg != 0) dog = Math.max(255 - (((int)(255-dig) << 8) / sg), 0); else dog = sg; if (sb != 0) dob = Math.max(255 - (((int)(255-dib) << 8) / sb), 0); else dob = sb; float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/SubtractComposite.java0000644000175000017500000000425710521402272024207 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class SubtractComposite extends RGBComposite { public SubtractComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; dor = dir - sr; if ( dor < 0 ) dor = 0; dog = dig - sg; if ( dog < 0 ) dog = 0; dob = dib - sb; if ( dob < 0 ) dob = 0; float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/DodgeComposite.java0000644000175000017500000000406110521402272023433 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class DodgeComposite extends RGBComposite { public DodgeComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; dor = clamp((sr << 8) / (256-dir)); dog = clamp((sg << 8) / (256-dig)); dob = clamp((sb << 8) / (256-dib)); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/LightenComposite.java0000644000175000017500000000403210521402272024001 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class LightenComposite extends RGBComposite { public LightenComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; dor = dir > sr ? dir : sr; dog = dig > sg ? dig : sg; dob = dib > sb ? dib : sb; float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/MultiplyComposite.java0000644000175000017500000000421710521402272024233 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class MultiplyComposite extends RGBComposite { public MultiplyComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; int t = dir * sr + 0x80; dor = ((t >> 8) + t) >> 8; t = dig * sg + 0x80; dog = ((t >> 8) + t) >> 8; t = dib * sb + 0x80; dob = ((t >> 8) + t) >> 8; float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/AverageComposite.java0000644000175000017500000000401310521402272023760 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class AverageComposite extends RGBComposite { public AverageComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; dor = (dir + sr) / 2; dog = (dig + sg) / 2; dob = (dib + sb) / 2; float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/NegationComposite.java0000644000175000017500000000406110521402272024155 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class NegationComposite extends RGBComposite { public NegationComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; dor = 255 - Math.abs(255-sr-dir); dog = 255 - Math.abs(255-sg-dig); dob = 255 - Math.abs(255-sb-dib); float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } } jhlabs-filters-2.0.235/com/jhlabs/composite/ColorDodgeComposite.java0000644000175000017500000000452510521402272024437 0ustar varunvarun/* Copyright 2006 Jerry Huxtable Licensed 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 com.jhlabs.composite; import java.awt.*; import java.awt.image.*; public final class ColorDodgeComposite extends RGBComposite { public ColorDodgeComposite( float alpha ) { super( alpha ); } public CompositeContext createContext( ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints ) { return new Context( extraAlpha, srcColorModel, dstColorModel ); } static class Context extends RGBCompositeContext { public Context( float alpha, ColorModel srcColorModel, ColorModel dstColorModel ) { super( alpha, srcColorModel, dstColorModel ); } public void composeRGB( int[] src, int[] dst, float alpha ) { int w = src.length; for ( int i = 0; i < w; i += 4 ) { int sr = src[i]; int dir = dst[i]; int sg = src[i+1]; int dig = dst[i+1]; int sb = src[i+2]; int dib = dst[i+2]; int sa = src[i+3]; int dia = dst[i+3]; int dor, dog, dob; if (sr != 255) dor = Math.min((dir << 8) / (255-sr), 255); else dor = sr; if (sg != 255) dog = Math.min((dig << 8) / (255-sg), 255); else dog = sg; if (sb != 255) dob = Math.min((dib << 8) / (255-sb), 255); else dob = sb; float a = alpha*sa/255f; float ac = 1-a; dst[i] = (int)(a*dor + ac*dir); dst[i+1] = (int)(a*dog + ac*dig); dst[i+2] = (int)(a*dob + ac*dib); dst[i+3] = (int)(sa*alpha + dia*ac); } } } }