7 import "GradientDesigner"
9 define app = (GuiApplication)__thisModule;
10 define gradient = fractalsDesigner.gradientDesigner.gradient;
23 void Allocate(int w, int h)
27 pixels = renew pixels float[w * h];
28 z = renew z Complex[w * h];
29 FillBytes(pixels, 0, w * h * sizeof(float));
30 FillBytes(z, 0, w * h * sizeof(Complex)); // renew0 crashes
39 class ParallelFractalRenderThread : Thread
41 FractalRenderThread thread;
49 void Render(int ns, int ne, int start, int end)
52 int w = thread.buffer.width;
53 int h = thread.buffer.height;
56 float * buffer = thread.buffer.pixels;
57 Complex * bufferZ = thread.buffer.z;
59 int power = thread.exponent;
60 bool julia = thread.isJulia;
61 double logOf2 = log(2);
62 double log2logOf2 = log(2*logOf2);
63 double logPower = log(power);
69 d.b = thread.range * h / w;
74 d.a = thread.range * w / h;
77 C0.a = thread.center.a - d.a/2;
78 C0.b = thread.center.b - d.b/2;
82 C = thread.juliaPoint;
86 C.b += start * d.b / h;
91 for( y = start; y <=end && !terminate; y++)
96 buf = buffer + bufferPos;
97 for( x = 0; x < w/* && !terminate*/; x++)
100 for(n = ns; n<=ne; n++)
109 Z = Complex { x * delta + C0.a, y * delta + C0.b };
111 Z = bufferZ[bufferPos];
114 for(c = 1; c<power; c++)
116 Z = { Z.a*oldZ.a - Z.b*oldZ.b, Z.a*oldZ.b + Z.b*oldZ.a };
121 zm = sqrt(Z.a * Z.a + Z.b * Z.b);
125 *buf = (float)(n + 1 - log(log(zm)) / logOf2);
127 *buf = (float)(n + (log2logOf2 - log(log(zm)) / logPower));
128 bufferZ[bufferPos] = Z;
134 if(!julia) C.a += delta;
138 if(minY == MAXINT) minY = y;
156 Render(depth, depth, yStart, yEnd);
163 define numThreads = 16;
165 class FractalRenderThread : Thread
171 // Complex juliaPoint { -0.726895347709114071439, 0.188887129043845954792 };
172 Complex juliaPoint { 0.37799999117851257000, -0.30700001120567322000 };
200 ParallelFractalRenderThread * threads = new ParallelFractalRenderThread[numThreads];
202 for(t = 0; t < numThreads; t++)
205 if(t == numThreads - 1)
206 yEnd = buffer.height - 1;
208 yEnd = yStart + buffer.height / numThreads - 1;
209 threads[t] = ParallelFractalRenderThread { thread = this, yStart = yStart, yEnd = yEnd, minY = MAXINT, maxY = MAXINT };
213 for(c = maxDepth; c<iterations && !terminate; c++)
219 for(t = 0; t < numThreads; t++)
221 threads[t].depth = c;
222 threads[t].go.Release();
224 for(t = 0; t < numThreads; t++)
225 threads[t].done.Wait();
230 for(t = 0; t < numThreads; t++)
232 if(threads[t].minY != MAXINT)
234 threads[t].yStart = threads[t].minY;
235 threads[t].yEnd = threads[t].maxY;
239 threads[t].yStart = threads[t].yEnd + 1;
243 for(t = 0; t < numThreads; t++)
245 if(threads[t].minY != MAXINT) { yStart = threads[t].minY; break; }
247 for(t = numThreads-1; t >=0 numThreads; t--)
249 if(threads[t].maxY != MAXINT) { max = threads[t].maxY; break; }
251 for(t = 0; t < numThreads; t++)
254 if(t == numThreads - 1)
257 yEnd = yStart + (max + 1 - yStart) / numThreads - 1;
258 threads[t].yStart = yStart;
259 threads[t].yEnd = yEnd;
265 if(!(c%25) && c == maxDepth)
266 fractal.UpdateDepth((depth < c) ? depth : (c+1), c+1);
269 depth = (depth < c) ? depth : (c+1);
270 //fractal.params.depthScroll.range = maxDepth;
271 //fractal.params.depthLabel.SetText("%d / %d", depth, fractal.params.depthScroll.range-1);
277 for(t = 0; t < numThreads; t++)
279 threads[t].terminate = true;
280 threads[t].go.Release();
285 fractal.UpdateDepth(Min(depth, iterations), maxDepth);
291 static define numColors = 30000;
292 static ColorAlpha palette[numColors];
294 class Fractal : Window
296 borderStyle = sizable;
297 size = Size { 408, 428 };
298 hasHorzScroll = true;
299 hasVertScroll = true;
300 isActiveClient = true;
304 FractalParams params;
305 FractalRenderThread thread;
307 Point mouse0, mouse1;
309 void UpdateDepth(int d, int max)
311 params.depthScroll.range = max+1;
312 params.depthScroll.thumbPosition = d;
320 thread.center = Complex { 0, 0 };
325 if(thread.exponent == 2)
326 thread.center = { -0.75, 0 };
328 thread.center = { 0, 0 };
330 params.UpdateControls();
334 Size imageSize { 400, 400 };
335 scrollArea = imageSize;
340 bool OnLeftButtonDown(int x, int y, Modifiers mods)
342 if(x >= 0 && y >= 0 && x < clientSize.w && y < clientSize.h)
344 x -= Max((clientSize.w - imageSize.w) / 2, 0);
345 y -= Max((clientSize.h - imageSize.h) / 2, 0);
348 if(x >= 0 && y >= 0 && x < imageSize.w && y < imageSize.h)
350 mouse0 = mouse1 = Point { x, y };
359 bool OnLeftButtonUp(int x, int y, Modifiers mods)
363 Complex C0, d, point;
365 int h = image.height;
366 int dx = Abs(mouse1.x - mouse0.x);
367 int dy = Abs(mouse1.y - mouse0.y);
372 d.b = thread.range * h / w;
377 d.a = thread.range * w / h;
380 C0.a = thread.center.a - d.a/2;
381 C0.b = thread.center.b - d.b/2;
382 point = Complex { (mouse0.x + mouse1.x) / 2.0 * d.a / w + C0.a, (mouse0.y + mouse1.y) / 2.0 * d.b / h + C0.b };
384 if(Abs(x - mouse0.x) > 5 && Abs(y - mouse0.y) > 5)
386 thread.center = point;
389 thread.range = d.a * dx / w;
391 thread.range = d.b * dy / h;
394 params.UpdateControls();
396 else if(!thread.isJulia)
398 FractalsDesigner designer = (FractalsDesigner) master;
401 designer.julia.thread.juliaPoint = point;
402 designer.paramsJulia.UpdateControls();
403 designer.julia.Render(true);
412 bool OnRightButtonUp(int x, int y, Modifiers mods)
414 Complex C0, d, point;
416 int h = image.height;
418 x -= Max((clientSize.w - imageSize.w) / 2, 0);
419 y -= Max((clientSize.h - imageSize.h) / 2, 0);
426 d.b = thread.range * h / w;
431 d.a = thread.range * w / h;
434 C0.a = thread.center.a - d.a/2;
435 C0.b = thread.center.b - d.b/2;
437 point = Complex { x * d.a / w + C0.a, y * d.b / h + C0.b };
440 thread.center = point;
443 params.UpdateControls();
451 bool OnMouseMove(int x, int y, Modifiers mods)
455 x -= Max((clientSize.w - imageSize.w) / 2, 0);
456 y -= Max((clientSize.h - imageSize.h) / 2, 0);
460 mouse1 = Point { x, y };
466 params.depthScroll.thumbPosition =
467 (int)((double)x / (double)clientSize.w * (double)(params.depthScroll.range - 1));
469 params.loop.thumbPosition = (int)((double)y / (double)clientSize.h * 512);
476 if(this && image.picture)
478 int w = image.width, h = image.height;
483 ColorAlpha * picture = (ColorAlpha *)image.picture;
487 cbuffer = thread.buffer.pixels;
488 depth = thread.depth + 1;
495 int bufferPos = y * w;
498 double i = cbuffer[bufferPos+x];
501 *(picture++) = thread.useBlack ? black : palette[numColors - 1];
507 index = Min((int)(i * thread.numScales), ((int)(thread.maxLoops * numColors)) - 1) % numColors;
509 index = Min((int)(i * thread.numScales), numColors - 1);
510 if(index < 0) index = 0;
511 *(picture++) = palette[index];
515 thread.mutex.Release();
519 void OnRedraw(Surface surface)
521 JuliaFractal julia = ((FractalsDesigner)master).julia;
522 int x = Max((clientSize.w - imageSize.w) / 2, 0);
523 int y = Max((clientSize.h - imageSize.h) / 2, 0);
526 surface.Blit(image, x, y, scroll.x, scroll.y, image.width, image.height);
527 surface.SetForeground(lime);
529 surface.Rectangle(x+mouse0.x - scroll.x, y+mouse0.y - scroll.y, x+mouse1.x - scroll.x, y+mouse1.y - scroll.y);
530 if(!thread.isJulia && julia)
532 Complex juliaPoint = julia.thread.juliaPoint;
535 int h = image.height;
539 d.b = thread.range * h / w;
544 d.a = thread.range * w / h;
546 C0.a = thread.center.a - d.a/2;
547 C0.b = thread.center.b - d.b/2;
549 x += (int)((juliaPoint.a - C0.a) * w / d.a ) - scroll.x;
550 y += (int)((juliaPoint.b - C0.b) * h / d.b ) - scroll.y;
552 surface.DrawLine(x - 5, y, x + 5, y);
553 surface.DrawLine(x, y - 5, x, y + 5);
559 thread.terminate = true;
568 void Render(bool resetDepth)
570 thread.terminate = true;
577 int width = imageSize.w;
578 int height = imageSize.h;
579 thread.buffer.Allocate(width, height);
581 image.Allocate(null, width, height, 0, pixelFormat888, false);
585 thread.terminate = false;
592 params.UpdateControls();
598 thread.terminate = true;
604 void OnScroll(ScrollBarAction action, int position, Key key)
609 OnHScroll = OnScroll;
610 OnVScroll = OnScroll;
613 Menu fileMenu { parent = menu, "File", f };
617 fileMenu, "Export Image...", e, ctrlE;
619 bool NotifySelect(MenuItem selection, Modifiers mods)
622 FileDialog exportDialog = ((FractalsDesigner)master).exportDialog;
623 exportDialog.SetText("Export %s image", text);
624 if(exportDialog.Modal())
626 char * ext = exportDialog.types[exportDialog.fileType].typeExtension;
629 char extension[MAX_EXTENSION];
630 GetExtension(exportDialog.filePath, extension);
634 ChangeExtension(exportDialog.filePath, ext, exportDialog.filePath);
637 image.Save(exportDialog.filePath, ext, (void *) bool::true);
643 MenuItem exportItemFiltered
645 fileMenu, "Export Image (filtered half)...", f;
647 bool NotifySelect(MenuItem selection, Modifiers mods)
650 FileDialog exportDialog = ((FractalsDesigner)master).exportDialog;
651 exportDialog.SetText("Export %s image", text);
652 if(exportDialog.Modal())
654 char * ext = exportDialog.types[exportDialog.fileType].typeExtension;
658 char extension[MAX_EXTENSION];
659 GetExtension(exportDialog.filePath, extension);
663 ChangeExtension(exportDialog.filePath, ext, exportDialog.filePath);
666 if(filtered.Allocate(null, image.width/2, image.height/2, 0, pixelFormat888, false))
668 Surface surface = filtered.GetSurface(0,0,null);
669 surface.Filter(image, 0,0,0,0, filtered.width, filtered.height, image.width, image.height);
670 filtered.Save(exportDialog.filePath, ext, (void *) bool::true);
680 class MandelbrotFractal : Fractal
683 FractalRenderThread mandelbrotThread { fractal = this, center = { -0.75, 0 }, range = 3 /*, range = 0.049179316033124996, center = { -0.7623287774189061, -0.1281808432395703 }*/ };
685 thread = mandelbrotThread;
688 class JuliaFractal : Fractal
691 FractalRenderThread juliaThread { fractal = this, isJulia = true, range = 3 };
692 thread = juliaThread;
695 class FractalParams : Window
697 text = "Mandelbrot Parameters";
698 background = activeBorder;
702 size = Size { 206, 506 };
706 Label { labeledWindow = width, parent = this, position = Point { 16, 8 } };
707 Label { labeledWindow = height, parent = this, position = Point { 104, 8 } };
710 parent = this, text = "Width", position = Point { 16, 32 };
712 bool NotifyModified(EditBox editBox)
714 fractal.imageSize.w = atoi(editBox.contents);
715 fractal.scrollArea = fractal.imageSize;
716 fractal.clientSize = fractal.imageSize;
717 fractal.Render(true);
723 parent = this, text = "Height", position = Point { 104, 32 };
725 bool NotifyModified(EditBox editBox)
727 fractal.imageSize.h = atoi(editBox.contents);
728 fractal.scrollArea = fractal.imageSize;
729 fractal.clientSize = fractal.imageSize;
730 fractal.Render(true);
736 parent = this, text = "Exponent", position = Point { 16, 88 };
738 bool NotifyModified(EditBox editBox)
740 FractalsDesigner master = (FractalsDesigner)this.master;
742 master.mandelbrot.thread.exponent = master.julia.thread.exponent = atoi(editBox.contents);
744 master.paramsJulia.UpdateControls();
745 master.julia.Render(true);
747 master.paramsMandelbrot.UpdateControls();
748 master.mandelbrot.Render(true);
754 parent = this, text = "Iterations", position = Point { 104, 88 };
756 bool NotifyModified(EditBox editBox)
758 fractal.thread.mutex.Wait();
759 fractal.thread.iterations = atoi(editBox.contents);
760 fractal.thread.depth = fractal.thread.iterations;
761 fractal.thread.mutex.Release();
762 fractal.Render(false);
766 ScrollBar depthScroll
768 parent = this, text = "scrollBar1", size = Size { 172, 16 }, position = Point { 16, 120 };
770 void NotifyScrolling(ScrollBar scrollBar, ScrollBarAction action, int position, Key key)
774 fractal.thread.depth = position;
775 if(action != setRange)
777 fractal.ComputeImage();
778 fractal.Update(null);
781 depthLabel.SetText("%d / %d", fractal.thread.depth, scrollBar.range-1);
787 parent = this, text = "X", size = Size { 166, 19 }, position = Point { 16, 192 };
789 bool NotifyModified(EditBox editBox)
791 fractal.thread.center.a = strtod(editBox.contents, null);
792 fractal.Render(true);
798 parent = this, text = "Y", size = Size { 166, 19 }, position = Point { 16, 240 };
800 bool NotifyModified(EditBox editBox)
802 fractal.thread.center.b = strtod(editBox.contents, null);
803 fractal.Render(true);
809 parent = this, text = "Range", size = Size { 166, 19 }, position = Point { 16, 296 };
811 bool NotifyModified(EditBox editBox)
813 fractal.thread.range = strtod(editBox.contents, null);
814 fractal.Render(true);
820 parent = this, text = "Reset", size = Size { 170, 21 }, position = Point { 16, 328 };
822 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
828 Label depthLabel { parent = this, anchor = Anchor { top = 152, right = 16 } };
829 Label label1 { labeledWindow = exponent, parent = this, position = Point { 16, 64 } };
830 Label label2 { labeledWindow = iterations, parent = this, position = Point { 104, 64 } };
831 Label label4 { labeledWindow = rangeEdit, parent = this, position = Point { 16, 272 } };
832 Label label5 { labeledWindow = centerY, parent = this, position = Point { 16, 224 } };
833 Label label3 { labeledWindow = centerX, parent = this, position = Point { 16, 176 } };
837 this, borderStyle = deep, clientSize = { 124, 18 }, position = { 10, 376 }, range = 5000;
840 void NotifyScrolling(ScrollBar scrollBar, ScrollBarAction action, int position, Key key)
844 position = Max(position, 1);
845 fractal.thread.loop = position;
846 fractal.thread.numScales = numColors / position;
849 loopEdit.SetContents("%d", fractal.thread.loop);
851 fractal.ComputeImage();
852 fractal.Update(null);
857 Label lblLoop { this, labeledWindow = loop, position = { 10, 356 } };
860 this, position = { 60, 356 }, size = { 80, 20 };
862 bool OnKeyHit(Key key, unichar ch)
864 if((SmartKey)key == enter) { Deactivate(); Activate(); }
865 return EditBox::OnKeyHit(key, ch);
868 bool NotifyModified(EditBox editBox)
870 int value = atoi(editBox.contents);
871 if(value != loop.thumbPosition)
872 loop.thumbPosition = value;
878 this, checked = true, isCheckbox = true, position = { 110, 406 }, text = "Loop";
880 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
882 fractal.thread.doLoop = button.checked;
883 fractal.ComputeImage();
884 fractal.Update(null);
891 this, checked = true, isCheckbox = true, position = { 10, 406 }, text = "Black";
893 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
895 fractal.thread.useBlack = button.checked;
896 fractal.ComputeImage();
897 fractal.Update(null);
905 this, borderStyle = deep, clientSize = { 124, 18 }, position = { 10, 450 }, range = 5000;
908 void NotifyScrolling(ScrollBar scrollBar, ScrollBarAction action, int position, Key key)
912 fractal.thread.maxLoops = position;
914 maxLoopEdit.SetContents("%.0f", fractal.thread.maxLoops);
915 fractal.ComputeImage();
916 fractal.Update(null);
921 Label lblMaxLoop { this, labeledWindow = maxLoop, position = { 10, 430 } };
924 this, position = { 70, 430 }, size = { 70, 20 };
926 bool OnKeyHit(Key key, unichar ch)
928 if((SmartKey)key == enter) { Deactivate(); Activate(); }
929 return EditBox::OnKeyHit(key, ch);
932 bool NotifyModified(EditBox editBox)
934 float value = atof(editBox.contents);
935 //if(value != maxLoop.thumbPosition)
937 //thumbPosition = value;
938 fractal.thread.maxLoops = value;
939 fractal.ComputeImage();
940 fractal.Update(null);
947 virtual void UpdateControls()
949 float maxLoops = fractal.thread.maxLoops;
951 exponent.SetContents("%d", fractal.thread.exponent);
952 iterations.SetContents("%d", fractal.thread.iterations);
953 centerX.SetContents("%.20f", fractal.thread.center.a);
954 centerY.SetContents("%.20f", fractal.thread.center.b);
955 rangeEdit.SetContents("%.20f", fractal.thread.range);
956 width.SetContents("%d", fractal.imageSize.w);
957 height.SetContents("%d", fractal.imageSize.h);
959 loop.thumbPosition = (int)fractal.thread.loop;
960 loopEdit.Clear(); loopEdit.SetContents("%d", fractal.thread.loop);
961 maxLoop.thumbPosition = (int)fractal.thread.maxLoops;
962 fractal.thread.maxLoops = maxLoops;
963 maxLoopEdit.Clear(); maxLoopEdit.SetContents("%f", fractal.thread.maxLoops);
964 useBlack.checked = fractal.thread.useBlack;
965 loopCheck.checked = fractal.thread.doLoop;
975 class FractalParamsJulia : FractalParams
977 text = "Julia Parameters";
978 size = Size { 206, 610 };
982 parent = this, text = "Xj", size = Size { 166, 19 }, position = Point { 16, 504 };
984 bool NotifyModified(EditBox editBox)
986 fractal.Render(true);
987 fractal.thread.juliaPoint.a = strtod(editBox.contents, null);
993 parent = this, text = "Yj", size = Size { 166, 19 }, position = Point { 16, 552 };
995 bool NotifyModified(EditBox editBox)
997 fractal.Render(true);
998 fractal.thread.juliaPoint.b = strtod(editBox.contents, null);
1002 Label label7 { labeledWindow = juliaY, parent = this, position = Point { 16, 528 } };
1003 Label label6 { labeledWindow = juliaX, parent = this, position = Point { 16, 480 } };
1005 void UpdateControls()
1007 FractalParams::UpdateControls();
1008 juliaX.SetContents("%.20f", fractal.thread.juliaPoint.a);
1009 juliaY.SetContents("%.20f", fractal.thread.juliaPoint.b);
1013 static FileFilter fractalFilters[] =
1015 { "ECERE Fractal Files (*.frc)", "frc" },
1016 { "All files", null }
1018 static FileType fractalTypes[] =
1020 { "ECERE Fractal", "frc", always },
1023 static FileFilter imageFilters[] =
1026 "Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png, *.gif)",
1027 "jpg, jpeg, bmp, pcx, png, gif"
1029 { "All files", null }
1031 static FileType imageTypes[] =
1033 { "Based on extension", null, always },
1034 { "JPG Image", "jpg", always },
1035 { "BMP Image", "bmp", always },
1036 { "PCX Image", "pcx", always },
1037 { "PNG Image", "png", always },
1038 { "GIF Image", "gif", always }
1041 #define FRC_RECOGNITION { 'e', 'F', 'R', 'C', 11, 12, 3, 0 }
1042 static byte frcRecognition[] = FRC_RECOGNITION;
1044 class FractalsDesigner : Window
1046 text = "Ecere Fractals Explorer";
1047 background = dimGray;
1048 borderStyle = sizable;
1054 size = Size { 1000, 600 };
1057 hasHorzScroll = true;
1058 hasVertScroll = true;
1060 Menu fileMenu { menu, "File", f };
1061 MandelbrotFractal mandelbrot { this, position = Point { 10, 10 }, params = paramsMandelbrot };
1062 FractalParams paramsMandelbrot { this, anchor = Anchor { right = 260, top = 10 }, fractal = mandelbrot };
1063 JuliaFractal julia { this, position = Point { 420, 10 }, params = paramsJulia };
1064 FractalParamsJulia paramsJulia { this, anchor = Anchor { right = 10, top = 10 }, fractal = julia };
1065 GradientDesigner gradientDesigner
1067 this, anchor = { left = 10, bottom = 10 }, stayOnTop = true;
1070 PaletteGradient(palette, numColors, gradient.keys._, gradient.keys.size, gradient.smoothness);
1072 mandelbrot.ComputeImage();
1073 julia.ComputeImage();
1074 mandelbrot.Update(null);
1079 bool LoadFractals(char * fileName)
1081 File f = FileOpen(fileName, read);
1084 static byte frcRead[8];
1085 mandelbrot.ResetDepth();
1088 // First attempt to treat this as an archive file
1089 if(f.Read(frcRead, sizeof(frcRead), 1) == 1 &&
1090 !strncmp(frcRead, frcRecognition, sizeof(frcRecognition)))
1094 mandelbrot.thread.terminate = true;
1095 julia.thread.terminate = true;
1097 mandelbrot.thread.Wait();
1098 julia.thread.Wait();
1101 // New binary format
1102 f.Get(mandelbrot.imageSize);
1103 f.Get(mandelbrot.thread.exponent);
1104 f.Get(mandelbrot.thread.iterations);
1105 f.Get(mandelbrot.thread.center);
1106 f.Get(mandelbrot.thread.range);
1107 f.Get(mandelbrot.thread.depth);
1108 f.Get(mandelbrot.thread.maxDepth);
1110 mandelbrot.thread.buffer.Allocate(mandelbrot.imageSize.w, mandelbrot.imageSize.h);
1113 bufferZ.Read(mandelbrot.thread.buffer.z, sizeof(Complex), mandelbrot.thread.buffer.width * mandelbrot.thread.buffer.height);
1114 bufferZ.Read(mandelbrot.thread.buffer.pixels, sizeof(float), mandelbrot.thread.buffer.width * mandelbrot.thread.buffer.height);
1118 f.Get(julia.imageSize);
1119 f.Get(julia.thread.exponent);
1120 f.Get(julia.thread.iterations);
1121 f.Get(julia.thread.center);
1122 f.Get(julia.thread.range);
1123 f.Get(julia.thread.depth);
1124 f.Get(julia.thread.maxDepth);
1125 //julia.thread.iterations = julia.thread.maxDepth;
1127 julia.thread.buffer.Allocate(julia.imageSize.w, julia.imageSize.h);
1130 bufferZ.Read(julia.thread.buffer.z, sizeof(Complex), julia.thread.buffer.width * julia.thread.buffer.height);
1131 bufferZ.Read(julia.thread.buffer.pixels, sizeof(float), julia.thread.buffer.width * julia.thread.buffer.height);
1135 f.Get(julia.thread.juliaPoint);
1137 f.Get(gradient.smoothness);
1143 gradient.keys.size = size;
1144 f.Read(gradient.keys._, sizeof(ColorKey), gradient.keys.size);
1152 mandelbrot.thread.loop = loop;
1153 f.Get(mandelbrot.thread.maxLoops);
1154 if(mandelbrot.thread.maxLoops < 0.00001) mandelbrot.thread.maxLoops = 4999;
1155 f.Get(mandelbrot.thread.useBlack);
1156 f.Get(mandelbrot.thread.doLoop);
1162 julia.thread.loop = loop;
1163 f.Get(julia.thread.maxLoops);
1164 if(julia.thread.maxLoops < 0.00001) julia.thread.maxLoops = 4999;
1165 f.Get(julia.thread.useBlack);
1166 f.Get(julia.thread.doLoop);
1170 julia.thread.loop = mandelbrot.thread.loop;
1171 julia.thread.maxLoops = mandelbrot.thread.maxLoops;
1172 julia.thread.useBlack = mandelbrot.thread.useBlack;
1173 julia.thread.doLoop = mandelbrot.thread.doLoop;
1177 gradientDesigner.UpdateHandles();
1179 mandelbrot.clientSize = mandelbrot.imageSize;
1180 julia.clientSize = julia.imageSize;
1182 mandelbrot.params.UpdateControls();
1183 julia.params.UpdateControls();
1185 mandelbrot.image.Free();
1186 mandelbrot.image.Allocate(null, mandelbrot.imageSize.w, mandelbrot.imageSize.h, 0, pixelFormat888, false);
1187 mandelbrot.ComputeImage();
1190 julia.image.Allocate(null, julia.imageSize.w, julia.imageSize.h, 0, pixelFormat888, false);
1191 julia.ComputeImage();
1193 julia.thread.terminate = false;
1194 julia.thread.Create();
1196 mandelbrot.thread.terminate = false;
1197 mandelbrot.thread.Create();
1204 mandelbrot.imageSize.w = f.GetValue();
1205 mandelbrot.imageSize.h = f.GetValue();
1206 mandelbrot.thread.exponent = f.GetValue();
1207 mandelbrot.thread.iterations = f.GetValue();
1208 mandelbrot.thread.center.a = f.GetDouble();
1209 mandelbrot.thread.center.b = f.GetDouble();
1210 mandelbrot.thread.range = f.GetDouble();
1212 julia.imageSize.w = f.GetValue();
1213 julia.imageSize.h = f.GetValue();
1214 julia.thread.exponent = f.GetValue();
1215 julia.thread.iterations = f.GetValue();
1216 julia.thread.center.a = f.GetDouble();
1217 julia.thread.center.b = f.GetDouble();
1218 julia.thread.range = f.GetDouble();
1220 julia.thread.juliaPoint.a = f.GetDouble();
1221 julia.thread.juliaPoint.b = f.GetDouble();
1224 int size = f.GetValue();
1228 gradient.keys.size = size;
1229 for(c = 0; c < gradient.keys.size; c++)
1231 gradient.keys._[c].percent = f.GetFloat();
1232 gradient.keys._[c].color.a = 255;
1233 gradient.keys._[c].color.color.r = (byte)f.GetValue();
1234 gradient.keys._[c].color.color.g = (byte)f.GetValue();
1235 gradient.keys._[c].color.color.b = (byte)f.GetValue();
1237 gradient.smoothness = f.GetFloat();
1240 loop = f.GetValue();
1243 mandelbrot.thread.loop = loop;
1244 mandelbrot.thread.maxLoops = f.GetFloat();
1245 mandelbrot.thread.useBlack = f.GetValue();
1246 mandelbrot.thread.doLoop = f.GetValue();
1248 loop = f.GetValue();
1251 julia.thread.loop = loop;
1252 julia.thread.maxLoops = f.GetFloat();
1253 julia.thread.useBlack = f.GetValue();
1254 julia.thread.doLoop = f.GetValue();
1258 julia.thread.loop = mandelbrot.thread.loop;
1259 julia.thread.maxLoops = mandelbrot.thread.maxLoops;
1260 julia.thread.useBlack = mandelbrot.thread.useBlack;
1261 julia.thread.doLoop = mandelbrot.thread.doLoop;
1267 gradientDesigner.UpdateHandles();
1269 paramsJulia.UpdateControls();
1270 paramsMandelbrot.UpdateControls();
1272 julia.scrollArea = julia.imageSize;
1273 julia.clientSize = julia.imageSize;
1275 mandelbrot.scrollArea = mandelbrot.imageSize;
1276 mandelbrot.clientSize = mandelbrot.imageSize;
1279 mandelbrot.Render(true);
1283 this.fileName = fileName;
1290 fileMenu, "Open", o, ctrlO;
1292 bool NotifySelect(MenuItem selection, Modifiers mods)
1294 if(openDialog.Modal() == ok)
1296 if(LoadFractals(openDialog.filePath))
1303 MenuDivider { fileMenu };
1304 MenuPlacement { fileMenu, "Export Image...", e };
1305 MenuPlacement { fileMenu, "Export Image (filtered half)...", f };
1306 MenuDivider { fileMenu };
1307 MenuItem saveItemData
1309 fileMenu, "Save (with data)";
1310 bool NotifySelect(MenuItem selection, Modifiers mods)
1312 return MenuFileSave(selection, mods);
1315 MenuItem saveItemAsData
1317 fileMenu, "Save As (with data)...";
1319 bool NotifySelect(MenuItem selection, Modifiers mods)
1321 return MenuFileSaveAs(selection, mods);
1324 MenuDivider { fileMenu };
1327 fileMenu, "Save", s, ctrlS;
1329 bool NotifySelect(MenuItem selection, Modifiers mods)
1332 MenuFileSave(selection, mods);
1339 fileMenu, "Save As...", a;
1341 bool NotifySelect(MenuItem selection, Modifiers mods)
1344 MenuFileSaveAs(selection, mods);
1349 MenuDivider { fileMenu };
1350 MenuItem exitItem { fileMenu, "Exit", x, altF4, NotifySelect = MenuFileExit };
1352 FileDialog exportDialog
1354 master = this, type = save,
1355 filters = imageFilters, sizeFilters = sizeof(imageFilters),
1356 types = imageTypes, sizeTypes = sizeof(imageTypes)
1358 FileDialog mySaveDialog
1360 master = this, type = save, text = "Save Fractals Settings...",
1361 types = fractalTypes, sizeTypes = sizeof(fractalTypes), filters = fractalFilters, sizeFilters = sizeof(fractalFilters)
1364 FileDialog openDialog
1366 master = this, type = open, text = "Load Fractals Settings...",
1367 types = fractalTypes, sizeTypes = sizeof(fractalTypes), filters = fractalFilters, sizeFilters = sizeof(fractalFilters)
1371 saveDialog = mySaveDialog;
1373 bool OnSaveFile(char * fileName)
1375 File f = FileOpen(fileName, write);
1380 TempFile bufferZ { };
1381 f.Write(frcRecognition, sizeof(frcRecognition), 1);
1382 f.Put(mandelbrot.imageSize);
1383 f.Put(mandelbrot.thread.exponent);
1384 f.Put(mandelbrot.thread.iterations);
1385 f.Put(mandelbrot.thread.center);
1386 f.Put(mandelbrot.thread.range);
1387 f.Put(mandelbrot.thread.depth);
1388 f.Put(mandelbrot.thread.maxDepth);
1390 bufferZ.Write(mandelbrot.thread.buffer.z, sizeof(Complex), mandelbrot.thread.buffer.width * mandelbrot.thread.buffer.height);
1391 bufferZ.Write(mandelbrot.thread.buffer.pixels, sizeof(float), mandelbrot.thread.buffer.width * mandelbrot.thread.buffer.height);
1393 bufferZ.Truncate(0);
1394 bufferZ.Seek(0, start);
1396 f.Put(julia.imageSize);
1397 f.Put(julia.thread.exponent);
1398 f.Put(julia.thread.iterations);
1399 f.Put(julia.thread.center);
1400 f.Put(julia.thread.range);
1401 f.Put(julia.thread.depth);
1402 f.Put(julia.thread.maxDepth);
1404 bufferZ.Write(julia.thread.buffer.z, sizeof(Complex), julia.thread.buffer.width * julia.thread.buffer.height);
1405 bufferZ.Write(julia.thread.buffer.pixels, sizeof(float), julia.thread.buffer.width * julia.thread.buffer.height);
1408 f.Put(julia.thread.juliaPoint);
1410 f.Put(gradient.smoothness);
1411 { int size = gradient.keys.size; f.Put(size); }
1412 f.Write(gradient.keys._, sizeof(ColorKey), gradient.keys.size);
1414 f.Put(mandelbrot.thread.loop);
1415 f.Put(mandelbrot.thread.maxLoops);
1416 f.Put(mandelbrot.thread.useBlack);
1417 f.Put(mandelbrot.thread.doLoop);
1419 f.Put(julia.thread.loop);
1420 f.Put(julia.thread.maxLoops);
1421 f.Put(julia.thread.useBlack);
1422 f.Put(julia.thread.doLoop);
1429 f.Printf("%d\n", mandelbrot.imageSize.w);
1430 f.Printf("%d\n", mandelbrot.imageSize.h);
1431 f.Printf("%d\n", mandelbrot.thread.exponent);
1432 f.Printf("%d\n", mandelbrot.thread.iterations);
1433 f.Printf("%.20f\n", mandelbrot.thread.center.a);
1434 f.Printf("%.20f\n", mandelbrot.thread.center.b);
1435 f.Printf("%.20f\n", mandelbrot.thread.range);
1437 f.Printf("%d\n", julia.imageSize.w);
1438 f.Printf("%d\n", julia.imageSize.h);
1439 f.Printf("%d\n", julia.thread.exponent);
1440 f.Printf("%d\n", julia.thread.iterations);
1441 f.Printf("%.20f\n", julia.thread.center.a);
1442 f.Printf("%.20f\n", julia.thread.center.b);
1443 f.Printf("%.20f\n", julia.thread.range);
1445 f.Printf("%.20f\n", julia.thread.juliaPoint.a);
1446 f.Printf("%.20f\n", julia.thread.juliaPoint.b);
1448 f.Printf("%d\n", gradient.keys.size);
1449 for(c = 0; c < gradient.keys.size; c++)
1451 f.Printf("%.20f\n", gradient.keys._[c].percent);
1452 f.Printf("%d\n", gradient.keys._[c].color.color.r);
1453 f.Printf("%d\n", gradient.keys._[c].color.color.g);
1454 f.Printf("%d\n", gradient.keys._[c].color.color.b);
1456 f.Printf("%.20f\n", gradient.smoothness);
1458 f.Printf("%d\n", mandelbrot.thread.loop);
1459 f.Printf("%.20f\n", mandelbrot.thread.maxLoops);
1460 f.Printf("%d\n", mandelbrot.thread.useBlack);
1461 f.Printf("%d\n", mandelbrot.thread.doLoop);
1463 f.Printf("%d\n", julia.thread.loop);
1464 f.Printf("%.20f\n", julia.thread.maxLoops);
1465 f.Printf("%d\n", julia.thread.useBlack);
1466 f.Printf("%d\n", julia.thread.doLoop);
1476 LoadFractals(app.argv[1]);
1477 mandelbrot.Activate();
1482 FractalsDesigner fractalsDesigner { };