Skip to content

Commit

Permalink
Merge pull request #233 from Xiphereal/limit-memory-usage-for-recentl…
Browse files Browse the repository at this point in the history
…y-opened-documents-preview

Limit big file loading for recent opened files
  • Loading branch information
flabbet committed Nov 12, 2021
2 parents b8984cf + 50073c1 commit 38399fc
Show file tree
Hide file tree
Showing 12 changed files with 142 additions and 6 deletions.
34 changes: 28 additions & 6 deletions PixiEditor/Models/DataHolders/RecentlyOpenedDocument.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Media.Imaging;
using PixiEditor.Helpers;
using PixiEditor.Models.ImageManipulation;
using PixiEditor.Models.IO;
using PixiEditor.Models.Layers;
using PixiEditor.Parser;

namespace PixiEditor.Models.DataHolders
Expand Down Expand Up @@ -75,7 +73,7 @@ private WriteableBitmap LoadPreviewBitmap()
{
if (FileExtension == ".pixi")
{
SerializableDocument serializableDocument = null;
SerializableDocument serializableDocument;

try
{
Expand All @@ -87,9 +85,23 @@ private WriteableBitmap LoadPreviewBitmap()
return null;
}

return BitmapUtils.GeneratePreviewBitmap(serializableDocument.Layers, serializableDocument.Width, serializableDocument.Height, 80, 50);
WriteableBitmap writeableBitmap =
BitmapUtils.GeneratePreviewBitmap(serializableDocument.Layers, serializableDocument.Width, serializableDocument.Height, 80, 50);

const int MaxWidthInPixels = 1080;
const int MaxHeightInPixels = 1080;
PixiFileMaxSizeChecker pixiFileMaxSizeChecker = new PixiFileMaxSizeChecker()
{
MaxAllowedWidthInPixels = MaxWidthInPixels,
MaxAllowedHeightInPixels = MaxHeightInPixels,
MaxAllowedLayerCount = 5,
};

return pixiFileMaxSizeChecker.IsFileUnderMaxSize(serializableDocument) ?
writeableBitmap
: writeableBitmap.Resize(width: MaxWidthInPixels, height: MaxHeightInPixels, WriteableBitmapExtensions.Interpolation.Bilinear);
}
else if (FileExtension == ".png" || FileExtension == ".jpg" || FileExtension == ".jpeg")
else if (FileExtension is ".png" or ".jpg" or ".jpeg")
{
WriteableBitmap bitmap = null;

Expand All @@ -102,7 +114,17 @@ private WriteableBitmap LoadPreviewBitmap()
corrupt = true;
}

return bitmap;
const int MaxWidthInPixels = 2048;
const int MaxHeightInPixels = 2048;
ImageFileMaxSizeChecker imageFileMaxSizeChecker = new ImageFileMaxSizeChecker()
{
MaxAllowedWidthInPixels = MaxWidthInPixels,
MaxAllowedHeightInPixels = MaxHeightInPixels,
};

return imageFileMaxSizeChecker.IsFileUnderMaxSize(bitmap) ?
bitmap
: bitmap.Resize(width: MaxWidthInPixels, height: MaxHeightInPixels, WriteableBitmapExtensions.Interpolation.Bilinear);
}

return null;
Expand Down
20 changes: 20 additions & 0 deletions PixiEditor/Models/IO/ImageFileMaxSizeChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Windows.Media.Imaging;

namespace PixiEditor.Models.IO
{
internal class ImageFileMaxSizeChecker
{
public int MaxAllowedWidthInPixels { get; init; } = 2048;
public int MaxAllowedHeightInPixels { get; init; } = 2048;

public ImageFileMaxSizeChecker()
{
}

public bool IsFileUnderMaxSize(WriteableBitmap fileToCheck)
{
return fileToCheck.PixelWidth <= MaxAllowedWidthInPixels
&& fileToCheck.PixelHeight <= MaxAllowedHeightInPixels;
}
}
}
22 changes: 22 additions & 0 deletions PixiEditor/Models/IO/PixiFileMaxSizeChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using PixiEditor.Parser;

namespace PixiEditor.Models.IO
{
internal class PixiFileMaxSizeChecker
{
public int MaxAllowedWidthInPixels { get; init; } = 1080;
public int MaxAllowedHeightInPixels { get; init; } = 1080;
public int MaxAllowedLayerCount { get; init; } = 5;

public PixiFileMaxSizeChecker()
{
}

public bool IsFileUnderMaxSize(SerializableDocument fileToCheck)
{
return fileToCheck.Width <= MaxAllowedWidthInPixels
&& fileToCheck.Height <= MaxAllowedHeightInPixels
&& fileToCheck.Layers.Count <= MaxAllowedLayerCount;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using PixiEditor.Models.DataHolders;
using PixiEditor.Parser;
using System;
using Xunit;

namespace PixiEditorTests.ModelsTests.DataHoldersTests
{
[Collection("Application collection")]
public class RecentlyOpenedDocumentTests
{
[Fact]
public void TestThatForBigPixiFilesPreviewImageIsResizedToMaxSize()
{
string bigFilePath = $@"{Environment.CurrentDirectory}\..\..\..\ModelsTests\IO\BigPixiFile.pixi";
RecentlyOpenedDocument recentlyOpenedDocument = new RecentlyOpenedDocument(bigFilePath);

var bigPixiFilePreviewImage = recentlyOpenedDocument.PreviewBitmap;

const int MaxWidthInPixels = 1080;
Assert.True(bigPixiFilePreviewImage.PixelWidth <= MaxWidthInPixels);

const int MaxHeightInPixels = 1080;
Assert.True(bigPixiFilePreviewImage.PixelHeight <= MaxHeightInPixels);

// This is a workaround for checking the Pixi file layers.
Assert.True(PixiParser.Deserialize(bigFilePath).Layers.Count <= 5);
}

[Fact]
public void TestThatForSmallEnoughPixiFilesPreviewImageIsLoaded()
{
string smallEnoughFilePath = $@"{Environment.CurrentDirectory}\..\..\..\ModelsTests\IO\SmallEnoughPixiFile.pixi";
RecentlyOpenedDocument recentlyOpenedDocument = new RecentlyOpenedDocument(smallEnoughFilePath);

var smallEnoughFilePreviewImage = recentlyOpenedDocument.PreviewBitmap;

Assert.NotNull(smallEnoughFilePreviewImage);
}

[Theory]
[InlineData("png")]
[InlineData("jpg")]
[InlineData("jpeg")]
public void TestThatForBigImageFilesPreviewImageIsResizedToMaxSize(string imageFormat)
{
string bigImageFilePath = $@"{Environment.CurrentDirectory}\..\..\..\ModelsTests\IO\BigImage.{imageFormat}";
RecentlyOpenedDocument recentlyOpenedDocument = new RecentlyOpenedDocument(bigImageFilePath);

var bigImagePreviewImage = recentlyOpenedDocument.PreviewBitmap;

const int MaxWidthInPixels = 2048;
Assert.True(bigImagePreviewImage.PixelWidth <= MaxWidthInPixels);

const int MaxHeightInPixels = 2048;
Assert.True(bigImagePreviewImage.PixelHeight <= MaxHeightInPixels);
}

[Theory]
[InlineData("png")]
[InlineData("jpg")]
[InlineData("jpeg")]
public void TestThatForSmallEnoughImageFilesPreviewImageIsLoaded(string imageFormat)
{
string smallEnoughImageFilePath = $@"{Environment.CurrentDirectory}\..\..\..\ModelsTests\IO\SmallEnoughImage.{imageFormat}";
RecentlyOpenedDocument recentlyOpenedDocument = new RecentlyOpenedDocument(smallEnoughImageFilePath);

var smallEnoughImagePreviewImage = recentlyOpenedDocument.PreviewBitmap;

Assert.NotNull(smallEnoughImagePreviewImage);
}
}
}
Binary file added PixiEditorTests/ModelsTests/IO/BigImage.jpeg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added PixiEditorTests/ModelsTests/IO/BigImage.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added PixiEditorTests/ModelsTests/IO/BigImage.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added PixiEditorTests/ModelsTests/IO/BigPixiFile.pixi
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.

0 comments on commit 38399fc

Please sign in to comment.