async void LoadAndStartAnimation()
        {
            // Show total bitmap storage
            TallyBitmapSizes();

            // Create progressReporter for async operation
            Progress <double> progressReporter =
                new Progress <double>((double progress) => progressBar.Progress = progress);

            // Create (unused) CancellationTokenSource for async operation
            CancellationTokenSource cancelTokenSource = new CancellationTokenSource();

            // Loop through all the zoom levels
            for (int zoomLevel = 0; zoomLevel < COUNT; zoomLevel++)
            {
                // If the file exists, load it
                if (File.Exists(FilePath(zoomLevel)))
                {
                    statusLabel.Text = $"Loading bitmap for zoom level {zoomLevel}";

                    using (Stream stream = File.OpenRead(FilePath(zoomLevel)))
                    {
                        bitmaps[zoomLevel] = SKBitmap.Decode(stream);
                    }
                }
                // Otherwise, create a new bitmap
                else
                {
                    statusLabel.Text = $"Creating bitmap for zoom level {zoomLevel}";

                    CancellationToken cancelToken = cancelTokenSource.Token;

                    // Do the (generally lengthy) Mandelbrot calculation
                    BitmapInfo bitmapInfo =
                        await Mandelbrot.CalculateAsync(center,
                                                        4 / Math.Pow(2, zoomLevel),
                                                        4 / Math.Pow(2, zoomLevel),
                                                        BITMAP_SIZE, BITMAP_SIZE,
                                                        (int)Math.Pow(2, 10), progressReporter, cancelToken);

                    // Create bitmap & get pointer to the pixel bits
                    SKBitmap bitmap  = new SKBitmap(BITMAP_SIZE, BITMAP_SIZE, SKColorType.Rgba8888, SKAlphaType.Opaque);
                    IntPtr   basePtr = bitmap.GetPixels();

                    // Set pixel bits to color based on iteration count
                    for (int row = 0; row < bitmap.Width; row++)
                    {
                        for (int col = 0; col < bitmap.Height; col++)
                        {
                            int  iterationCount = bitmapInfo.IterationCounts[row * bitmap.Width + col];
                            uint pixel          = 0xFF000000;   // black

                            if (iterationCount != -1)
                            {
                                double proportion = (iterationCount / 32.0) % 1;
                                byte   red = 0, green = 0, blue = 0;

                                if (proportion < 0.5)
                                {
                                    red  = (byte)(255 * (1 - 2 * proportion));
                                    blue = (byte)(255 * 2 * proportion);
                                }
                                else
                                {
                                    proportion = 2 * (proportion - 0.5);
                                    green      = (byte)(255 * proportion);
                                    blue       = (byte)(255 * (1 - proportion));
                                }

                                pixel = MakePixel(0xFF, red, green, blue);
                            }

                            // Calculate pointer to pixel
                            IntPtr pixelPtr = basePtr + 4 * (row * bitmap.Width + col);

                            unsafe     // requires compiling with unsafe flag
                            {
                                *(uint *)pixelPtr.ToPointer() = pixel;
                            }
                        }
                    }

                    // Save as PNG file
                    SKData data = SKImage.FromBitmap(bitmap).Encode();

                    try
                    {
                        File.WriteAllBytes(FilePath(zoomLevel), data.ToArray());
                    }
                    catch
                    {
                        // Probably out of space, but just ignore
                    }

                    // Store in array
                    bitmaps[zoomLevel] = bitmap;

                    // Show new bitmap sizes
                    TallyBitmapSizes();
                }

                // Display the bitmap
                bitmapIndex = zoomLevel;
                canvasView.InvalidateSurface();
            }

            // Now do the animation
            stopwatch.Start();
            int cycle = 6000 * COUNT;       // total cycle length in milliseconds

            while (true)
            {
                // Time in milliseconds from 0 to cycle
                int time = (int)(stopwatch.ElapsedMilliseconds % cycle);

                // Make it sinusoidal, including bitmap index and gradation between bitmaps
                double progress = COUNT * 0.5 * (1 + Math.Sin(2 * Math.PI * time / cycle - Math.PI / 2));

                // These are the field values that the PaintSurface handler uses
                bitmapIndex    = (int)progress;
                bitmapProgress = progress - bitmapIndex;

                // It doesn't often happen that we get up to COUNT, but an exception would be raised
                if (bitmapIndex < COUNT)
                {
                    // Show progress in UI
                    statusLabel.Text     = $"Displaying bitmap for zoom level {bitmapIndex}";
                    progressBar.Progress = bitmapProgress;

                    // Update the canvas
                    canvasView.InvalidateSurface();
                }

                // Wait 16 milliseconds
                await Task.Delay(16);
            }
        }
Пример #2
0
        async void LoadAndStartAnimation()
        {
            // Show total bitmap storage
            TallyBitmapSizes();

            // Create progressReporter for async operation
            Progress <double> progressReporter =
                new Progress <double>((double progress) => progressBar.Progress = progress);

            // Create (unused) CancellationTokenSource for async operation
            CancellationTokenSource cancelTokenSource = new CancellationTokenSource();

            // Loop through all the zoom levels
            for (int zoomLevel = 0; zoomLevel < COUNT; zoomLevel++)
            {
                // If the file exists, load it
                if (File.Exists(FilePath(zoomLevel)))
                {
                    statusLabel.Text = $"Loading bitmap for zoom level {zoomLevel}";

                    using (Stream stream = File.OpenRead(FilePath(zoomLevel)))
                    {
                        bitmaps[zoomLevel] = SKBitmap.Decode(stream);
                    }
                }
                // Otherwise, create a new bitmap
                else
                {
                    statusLabel.Text = $"Creating bitmap for zoom level {zoomLevel}";

                    CancellationToken cancelToken = cancelTokenSource.Token;

                    // Do the (generally lengthy) Mandelbrot calculation
                    BitmapInfo bitmapInfo =
                        await Mandelbrot.CalculateAsync(center,
                                                        4 / Math.Pow(2, zoomLevel),
                                                        4 / Math.Pow(2, zoomLevel),
                                                        BITMAP_SIZE, BITMAP_SIZE,
                                                        (int)Math.Pow(2, 10), progressReporter, cancelToken);

                    // Create bitmap & get pointer to the pixel bits
                    SKBitmap bitmap  = new SKBitmap(BITMAP_SIZE, BITMAP_SIZE, SKColorType.Rgba8888, SKAlphaType.Opaque);
                    IntPtr   basePtr = bitmap.GetPixels();

                    // Set pixel bits to color based on iteration count
                    for (int row = 0; row < bitmap.Width; row++)
                    {
                        for (int col = 0; col < bitmap.Height; col++)
                        {
                            int  iterationCount = bitmapInfo.IterationCounts[row * bitmap.Width + col];
                            uint pixel          = 0xFF000000;   // black

                            if (iterationCount != -1)
                            {
                                double proportion = (iterationCount / 32.0) % 1;
                                byte   red = 0, green = 0, blue = 0;

                                if (proportion < 0.5)
                                {
                                    red  = (byte)(255 * (1 - 2 * proportion));
                                    blue = (byte)(255 * 2 * proportion);
                                }
                                else
                                {
                                    proportion = 2 * (proportion - 0.5);
                                    green      = (byte)(255 * proportion);
                                    blue       = (byte)(255 * (1 - proportion));
                                }

                                pixel = MakePixel(0xFF, red, green, blue);
                            }

                            // Calculate pointer to pixel
                            IntPtr pixelPtr = basePtr + 4 * (row * bitmap.Width + col);

                            unsafe     // requires compiling with unsafe flag
                            {
                                *(uint *)pixelPtr.ToPointer() = pixel;
                            }
                        }
                    }

                    // Save as PNG file
                    SKData data = SKImage.FromBitmap(bitmap).Encode();

                    try
                    {
                        File.WriteAllBytes(FilePath(zoomLevel), data.ToArray());
                    }
                    catch
                    {
                        // Probably out of space, but just ignore
                    }

                    // Store in array
                    bitmaps[zoomLevel] = bitmap;

                    // Show new bitmap sizes
                    TallyBitmapSizes();
                }

                // Display the bitmap
                bitmapIndex = zoomLevel;
                canvasView.InvalidateSurface();
            }

            // Now start the animation
            stopwatch.Start();
            Device.StartTimer(TimeSpan.FromMilliseconds(16), OnTimerTick);
        }