001/*
002Copyright 2006 Jerry Huxtable
003
004Licensed under the Apache License, Version 2.0 (the "License");
005you may not use this file except in compliance with the License.
006You may obtain a copy of the License at
007
008   http://www.apache.org/licenses/LICENSE-2.0
009
010Unless required by applicable law or agreed to in writing, software
011distributed under the License is distributed on an "AS IS" BASIS,
012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013See the License for the specific language governing permissions and
014limitations under the License.
015*/
016
017package com.jhlabs.image;
018
019import java.awt.image.*;
020import java.util.*;
021import com.jhlabs.math.*;
022
023public class MarbleTexFilter extends PointFilter {
024
025        private float scale = 32;
026        private float stretch = 1.0f;
027        private float angle = 0.0f;
028        private float turbulence = 1;
029        private float turbulenceFactor = 0.5f;
030        private Colormap colormap;
031        private float m00 = 1.0f;
032        private float m01 = 0.0f;
033        private float m10 = 0.0f;
034        private float m11 = 1.0f;
035
036        public MarbleTexFilter() {
037        }
038
039        public void setScale(float scale) {
040                this.scale = scale;
041        }
042
043        public float getScale() {
044                return scale;
045        }
046
047        public void setStretch(float stretch) {
048                this.stretch = stretch;
049        }
050
051        public float getStretch() {
052                return stretch;
053        }
054
055        public void setAngle(float angle) {
056                this.angle = angle;
057                float cos = (float)Math.cos(angle);
058                float sin = (float)Math.sin(angle);
059                m00 = cos;
060                m01 = sin;
061                m10 = -sin;
062                m11 = cos;
063        }
064
065        public float getAngle() {
066                return angle;
067        }
068
069        public void setTurbulence(float turbulence) {
070                this.turbulence = turbulence;
071        }
072
073        public float getTurbulence() {
074                return turbulence;
075        }
076
077        public void setTurbulenceFactor(float turbulenceFactor) {
078                this.turbulenceFactor = turbulenceFactor;
079        }
080
081        public float getTurbulenceFactor() {
082                return turbulenceFactor;
083        }
084
085        public void setColormap(Colormap colormap) {
086                this.colormap = colormap;
087        }
088        
089        public Colormap getColormap() {
090                return colormap;
091        }
092        
093        public int filterRGB(int x, int y, int rgb) {
094                float nx = m00*x + m01*y;
095                float ny = m10*x + m11*y;
096                nx /= scale * stretch;
097                ny /= scale;
098
099                int a = rgb & 0xff000000;
100                if (colormap != null) {
101//                      float f = Noise.turbulence2(nx, ny, turbulence);
102//                      f = 3*turbulenceFactor*f+ny;
103//                      f = Math.sin(f*Math.PI);
104                        float chaos = turbulenceFactor*Noise.turbulence2(nx, ny, turbulence);
105//                      float f = Math.sin(Math.sin(8.*chaos + 7*nx +3.*ny));
106                        float f = 3*turbulenceFactor*chaos+ny;
107                        f = (float)Math.sin(f*Math.PI);
108                        float perturb = (float)Math.sin(40.*chaos);
109                        f += .2 * perturb;
110                        return colormap.getColor(f);
111                } else {
112                        float red, grn, blu;
113                        float chaos, brownLayer, greenLayer;
114                        float perturb, brownPerturb, greenPerturb, grnPerturb;
115                        float t;
116
117                        chaos = turbulenceFactor*Noise.turbulence2(nx, ny, turbulence);
118                        t = (float)Math.sin(Math.sin(8.*chaos + 7*nx +3.*ny));
119
120                        greenLayer = brownLayer = Math.abs(t);
121
122                        perturb = (float)Math.sin(40.*chaos);
123                        perturb = (float)Math.abs(perturb);
124
125                        brownPerturb = .6f*perturb + 0.3f;
126                        greenPerturb = .2f*perturb + 0.8f;
127                        grnPerturb = .15f*perturb + 0.85f;
128                        grn = 0.5f * (float)Math.pow(Math.abs(brownLayer), 0.3);
129                        brownLayer = (float)Math.pow(0.5 * (brownLayer+1.0), 0.6) * brownPerturb;
130                        greenLayer = (float)Math.pow(0.5 * (greenLayer+1.0), 0.6) * greenPerturb;
131
132                        red = (0.5f*brownLayer + 0.35f*greenLayer)*2.0f*grn;
133                        blu = (0.25f*brownLayer + 0.35f*greenLayer)*2.0f*grn;
134                        grn *= Math.max(brownLayer, greenLayer) * grnPerturb;
135                        int r = (rgb >> 16) & 0xff;
136                        int g = (rgb >> 8) & 0xff;
137                        int b = rgb & 0xff;
138                        r = PixelUtils.clamp((int)(r*red));
139                        g = PixelUtils.clamp((int)(g*grn));
140                        b = PixelUtils.clamp((int)(b*blu));
141                        return (rgb & 0xff000000) | (r<<16) | (g<<8) | b;
142                }
143        }
144
145        public String toString() {
146                return "Texture/Marble Texture...";
147        }
148        
149}