buffer stores 2 channels of double; colour using both channels; default supersample...
[maximus:sft.git] / SuperFractalThing / source / IndexBuffer2D.java
1 //      IndexBuffer2D
2 //      Stores the results of a Mandelbrot set calculation, and builds the final texture
3 //
4 //    Copyright 2013 Kevin Martin
5 //    Copyright 2013 Claude Heiland-Allen
6 //
7 //    This file is part of SuperFractalThing.
8 //
9 //    SuperFractalThing is free software: you can redistribute it and/or modify
10 //    it under the terms of the GNU General Public License as published by
11 //    the Free Software Foundation, either version 3 of the License, or
12 //    any later version.
13 //
14 //    SuperFractalThing is distributed in the hope that it will be useful,
15 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 //    GNU General Public License for more details.
18 //
19 //    You should have received a copy of the GNU General Public License
20 //    along with SuperFractalThing.  If not, see <http://www.gnu.org/licenses/>.
21 //
22 import java.awt.image.BufferedImage;
23
24
25 interface IPalette
26 {
27         public int GetColour(double aIndex, double aDistance);
28         public int GetAverageColour(double i0, double i1, double i2, double i3, double d0, double d1, double d2, double d3);
29         public int GetAverageColour(double i0, double i1, double i2, double i3,double i4, double i5, double i6, double i7, double i8, double d0, double d1, double d2, double d3,double d4, double d5, double d6, double d7, double d8);
30         public void SetPixelSpacing(double aPixelSpacing);
31 }
32
33 enum SuperSampleType
34 {
35         SUPER_SAMPLE_NONE,
36         SUPER_SAMPLE_2X,
37         SUPER_SAMPLE_4X,        
38         SUPER_SAMPLE_4X_9,              
39         SUPER_SAMPLE_9X         
40 }
41
42 public class IndexBuffer2D
43 {
44         public IndexBuffer2D( int aWidth, int aHeight)
45         {
46                 mBuffer=new double[aWidth * aHeight * 2];
47                 mWidth = aWidth;
48                 mHeight = aHeight;
49                 mStride = aWidth * 2;
50         }
51         
52         public IndexBuffer2D( double aBuffer[], int aWidth, int aHeight, int aStride, int aOffset)
53         {
54                 mBuffer=aBuffer;
55                 mWidth = aWidth;
56                 mHeight = aHeight;
57                 mStride = aStride;
58                 mOffset = aOffset;
59         }       
60         
61         public void Set(int x, int y, int c, double aValue)
62         {
63                 mBuffer[mOffset+c+2*x+y*mStride]=aValue;
64         }
65         public double GetValue(int x, int y, int c)
66         {
67                 return mBuffer[mOffset+c+2*x+y*mStride];
68         }
69         public int GetOffsetY()
70         {
71                 return mOffset/mStride;
72         }
73         public double GetValueSafe(int x, int y, int c)
74         {
75                 if (x<0)
76                         x=0;
77                 if (x>=mWidth)
78                         x = mWidth-1;
79                 
80                 if (y<0)
81                         y=0;
82                 if (y>=mHeight)
83                         y = mHeight-1;
84                 if (c<0)
85                         c=0;
86                 if (c>1)
87                         c=1;
88                 return mBuffer[mOffset+c+2*x+y*mStride];
89         }
90         
91         public void Clear(int c, double pValue)
92         {
93                 int x,y;
94                 for (y=0; y<mHeight; y++)
95                         for (x=0; x<mWidth; x++)
96                                 Set( x,y,c, pValue );
97         }
98         
99         public IndexBuffer2D SubBuffer( int x1, int y1, int x2, int y2 )
100         {
101                 return new IndexBuffer2D(mBuffer, x2-x1,y2-y1, mStride, y1*mStride+2*x1+mOffset);
102         }
103         
104         public int GetWidth()
105         {
106                 return mWidth;
107         }
108         public int GetHeight()
109         {
110                 return mHeight;
111         }
112         float GetAspectRatio()
113         {
114                 return (float)mWidth/mHeight;
115         }       
116         
117         BufferedImage MakeTexture( IPalette aPalette, SuperSampleType aSuper_sample, double aPixelSpacing)
118         {
119                 aPalette.SetPixelSpacing(aPixelSpacing);
120                 BufferedImage image=null;
121                 int x,y,w,h,y2;
122                 double i,j,k,l,m,n,o,p,q;
123                 double di,dj,dk,dl,dm,dn,doo,dp,dq;
124
125                 try
126                 {
127                         switch (aSuper_sample)
128                         {
129                         case SUPER_SAMPLE_NONE:
130                                 image = new BufferedImage(mWidth, mHeight, BufferedImage.TYPE_INT_ARGB);
131                                 for (y=0,y2=mHeight-1; y<mHeight; y++,y2--)
132                                         for (x=0; x<mWidth; x++)
133                                         {
134                                                 i=GetValue(x,y,0);
135                                                 di=GetValue(x,y,1);
136                                                 image.setRGB(x, y2,aPalette.GetColour(i, di));
137                                         }
138                                 break;
139                         case SUPER_SAMPLE_2X:
140                                 w = mWidth-1;
141                                 h = mHeight/2;
142                                 image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
143                                 
144                                 for (y=0,y2=h-1; y<h; y++,y2--)
145                                         for (x=0; x<w; x++)
146                                         {
147                                                 i=GetValue(x,y,0);
148                                                 j=GetValue(x,y+1,0);
149                                                 k=GetValue(x,y+h+1,0);
150                                                 l=GetValue(x+1,y+h+1,0);
151                                                 di=GetValue(x,y,1);
152                                                 dj=GetValue(x,y+1,1);
153                                                 dk=GetValue(x,y+h+1,1);
154                                                 dl=GetValue(x+1,y+h+1,1);
155                                                 image.setRGB(x, y2,aPalette.GetAverageColour(i,j,k,l, di,dj,dk,dl));
156                                         }
157                                 break;
158                         case SUPER_SAMPLE_4X:
159                                 w = mWidth/2;
160                                 h = mHeight/2;
161                                 image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
162                                 
163                                 for (y=0,y2=mHeight-2; y<mHeight; y+=2,y2-=2)
164                                         for (x=0; x<mWidth; x+=2)
165                                         {
166                                                 i=GetValue(x,y,0);
167                                                 j=GetValue(x,y+1,0);
168                                                 k=GetValue(x+1,y,0);
169                                                 l=GetValue(x+1,y+1,0);
170                                                 di=GetValue(x,y,1);
171                                                 dj=GetValue(x,y+1,1);
172                                                 dk=GetValue(x+1,y+1,1);
173                                                 dl=GetValue(x+1,y+1,1);
174                                                 image.setRGB(x/2, y2/2,aPalette.GetAverageColour(i,j,k,l, di,dj,dk,dl));
175                                         }
176                                 break;
177                         case SUPER_SAMPLE_4X_9:
178                                 w = mWidth/2;
179                                 h = mHeight/2;
180                                 image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
181                                 for (y=0,y2=mHeight-3; y<mHeight-1; y+=2,y2-=2)
182                                         for (x=0; x<mWidth-1; x+=2)
183                                         {
184                                                 i=GetValue(x,y,0);
185                                                 j=GetValue(x,y+1,0);
186                                                 k=GetValue(x+1,y+1,0);
187                                                 l=GetValue(x+1,y,0);
188                                                 m=GetValue(x+2,y,0);
189                                                 n=GetValue(x+2,y+1,0);
190                                                 o=GetValue(x+2,y+2,0);
191                                                 p=GetValue(x+1,y+2,0);
192                                                 q=GetValue(x,y+2,0);
193                                                 di=GetValue(x,y,1);
194                                                 dj=GetValue(x,y+1,1);
195                                                 dk=GetValue(x+1,y+1,1);
196                                                 dl=GetValue(x+1,y,1);
197                                                 dm=GetValue(x+2,y,1);
198                                                 dn=GetValue(x+2,y+1,1);
199                                                 doo=GetValue(x+2,y+2,1);
200                                                 dp=GetValue(x+1,y+2,1);
201                                                 dq=GetValue(x,y+2,1);
202                                                 image.setRGB(x/2, y2/2,aPalette.GetAverageColour(i,j,k,l,m,n,o,p,q,di,dj,dk,dl,dm,dn,doo,dp,dq));
203                                         }
204                                 break;
205                         case SUPER_SAMPLE_9X:
206                                 w = mWidth/3;
207                                 h = mHeight/3;
208                                 image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
209                                 
210                                 for (y=0,y2=mHeight-2; y<mHeight; y+=3,y2-=3)
211                                         for (x=0; x<mWidth; x+=3)
212                                         {
213                                                 i=GetValue(x,y,0);
214                                                 j=GetValue(x,y+1,0);
215                                                 k=GetValue(x+1,y+1,0);
216                                                 l=GetValue(x+1,y,0);
217                                                 m=GetValue(x+2,y,0);
218                                                 n=GetValue(x+2,y+1,0);
219                                                 o=GetValue(x+2,y+2,0);
220                                                 p=GetValue(x+1,y+2,0);
221                                                 q=GetValue(x,y+2,0);
222                                                 di=GetValue(x,y,1);
223                                                 dj=GetValue(x,y+1,1);
224                                                 dk=GetValue(x+1,y+1,1);
225                                                 dl=GetValue(x+1,y,1);
226                                                 dm=GetValue(x+2,y,1);
227                                                 dn=GetValue(x+2,y+1,1);
228                                                 doo=GetValue(x+2,y+2,1);
229                                                 dp=GetValue(x+1,y+2,1);
230                                                 dq=GetValue(x,y+2,1);
231                                                 image.setRGB(x/3, y2/3,aPalette.GetAverageColour(i,j,k,l,m,n,o,p,q,di,dj,dk,dl,dm,dn,doo,dp,dq));
232                                         }
233                                 break;
234                         }
235                 }
236                 catch (OutOfMemoryError e)
237                 {
238                         return null;
239                 }
240                 return image;
241         }
242         
243         int mWidth;
244         int mHeight;
245         int mStride;
246         int mOffset;
247         double mBuffer[];
248 }