Search code examples
c#streamuwpinkcanvas

Saving Ink Canvas to stream results in blank .GIF


I am writing a UWP app in C# - it will be a Flashcard application that features two InkCanvases for the "front" and "back" of the cards. The InkCanvas functionality seems to be working fine. The issue is that, when I go to "save" the InkCanvas's stroke container to a .GIF file (as supported in these documents), the .GIF files generated don't contain the ink. Instead, they are mostly blank. Example here:

Blank .GIF files

Can a UWP developer help point me in the right direction? Here is the code in its current form:

CreateFlashCard.xaml.cs:

private void AddToDeck(object sender, RoutedEventArgs e)
    {
        // If there was ink on the canvases
        if (inkCanvas.InkPresenter.StrokeContainer.GetStrokes().Count > 0 
            && inkCanvas2.InkPresenter.StrokeContainer.GetStrokes().Count > 0)
        {
            // Create the FlashCard and add it to the deck
            FlashCard newCard = new FlashCard
            {
                Front = inkCanvas.InkPresenter,
                Back = inkCanvas2.InkPresenter
            };

            // Add to the deck
            if (Deck == null)
            {
                Deck = new List<FlashCard>();
            }
            // Now Add to the Deck
            Deck.Add(newCard);

            // Save the card
            newCard.Save(_FolderName, Deck.Count-1);

            // Now make way for new InkCanvases
            inkCanvas.InkPresenter.StrokeContainer.Clear();
            inkCanvas2.InkPresenter.StrokeContainer.Clear();

        }
        // The user is adding a new card without drawing on the old one
        else
        {
            return;   
        }


    }

FlashCard.cs:

    /// <summary>
    /// Save the canvases to GIF files in the deck's folder.
    /// </summary>
    /// <param name="FolderName"> The folder to save the files in</param>
    /// <param name="CardIndex">The "number" of the card that is being saved</param>
    public async void Save(string FolderName, int CardIndex)
    {
        // Find existing folder
        StorageFolder folder = await ApplicationData.Current.LocalFolder.GetFolderAsync(FolderName);
        if (folder == null)
        {
            // Error!
        } else
        {
            // Use a utility function to write to files
            // Front and Back being InkPresenters from two sep. InkCanvases
            WriteWithStream(folder, CardIndex, 'A', Front );
            WriteWithStream(folder, CardIndex, 'B', Back);

        }

    }

    private async void WriteWithStream(StorageFolder folder, int CardIndex, char Letter, InkPresenter FrontOrBack)
    {
        // Generate the ink files, A and B
        StorageFile inkFile = await folder.CreateFileAsync("Card" + CardIndex + Letter + ".gif", CreationCollisionOption.ReplaceExisting);
        // Prevent changes until we're done
        //CachedFileManager.DeferUpdates(inkFile);
        // Open a stream
        IRandomAccessStream stream = await inkFile.OpenAsync(FileAccessMode.ReadWrite);
        // Write out using the stream
        using (IOutputStream outputStream = stream.GetOutputStreamAt(0))
        {
            await FrontOrBack.StrokeContainer.SaveAsync(outputStream);
            await outputStream.FlushAsync();
        }
        // Dispose of the stream
        stream.Dispose();
        // We are now done with the file
        Windows.Storage.Provider.FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(inkFile);
    }

Thanks everyone!


Solution

  • Solved - the async nature of my "Save function" was conflicting with the clearing of the canvas - I needed to wait for the files to be generated, and THEN clear the canvas.