Skip to content

Commit 1f44023

Browse files
committed
use WIC to load image >=10000 pixels
1 parent 5dcbdf7 commit 1f44023

File tree

3 files changed

+83
-28
lines changed

3 files changed

+83
-28
lines changed

Source/Components/ImageGlass.Base/Photoing/Codecs/IgImgData.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,13 @@ public IgImgData(IgMagickReadData data)
136136
Source = WicBitmapDecoder.Load(new MemoryStream(bytes) { Position = 0 });
137137
}
138138
}
139-
// single frame
139+
// single frame: WIC bitmap source
140+
else if (data.SingleFrameSource != null)
141+
{
142+
HasAlpha = true; // assume the image source has alpha
143+
Image = data.SingleFrameSource;
144+
}
145+
// single frame: ImageMagick source
140146
else
141147
{
142148
HasAlpha = data.SingleFrameImage?.HasAlpha ?? false;

Source/Components/ImageGlass.Base/Photoing/Codecs/IgMagickReadData.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
1717
along with this program. If not, see <https://www.gnu.org/licenses/>.
1818
*/
1919
using ImageMagick;
20+
using WicNet;
2021

2122
namespace ImageGlass.Base.Photoing.Codecs;
2223

@@ -72,6 +73,7 @@ public virtual void Dispose()
7273

7374
public MagickImageCollection? MultiFrameImage { get; set; } = null;
7475
public MagickImage? SingleFrameImage { get; set; } = null;
76+
public WicBitmapSource? SingleFrameSource { get; set; } = null;
7577

7678
public IColorProfile? ColorProfile { get; set; } = null;
7779
public IExifProfile? ExifProfile { get; set; } = null;

Source/Components/ImageGlass.Base/Photoing/Codecs/PhotoCodec.cs

Lines changed: 74 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ public static async Task<IgImgData> LoadAsync(string filePath,
261261
{
262262
Width = width,
263263
Height = height,
264+
MinDimensionToUseWIC = 0,
264265
FirstFrameOnly = true,
265266
UseEmbeddedThumbnailRawFormats = true,
266267
UseEmbeddedThumbnailOtherFormats = true,
@@ -939,10 +940,13 @@ private static (bool loadSuccessful, IgImgData result, string ext, MagickReadSet
939940
var ms = BHelper.ToMemoryStream(wic);
940941

941942
var imgM = new MagickImage(ms);
942-
var processResult = ProcessMagickImage(imgM, options, ext, true);
943-
if (processResult.ThumbM != null)
943+
var profiles = GetProfiles(imgM);
944+
var thumbM = ProcessMagickImageAndReturnThumbnail(imgM, options, ext, true, profiles.ColorProfile, profiles.ExifProfile);
945+
946+
if (thumbM != null)
944947
{
945-
imgM = processResult.ThumbM;
948+
imgM?.Dispose();
949+
imgM = thumbM;
946950
}
947951

948952

@@ -1046,7 +1050,7 @@ private static async Task<IgMagickReadData> ReadMagickImageAsync(
10461050
var i = 0;
10471051
foreach (var imgFrameM in imgColl)
10481052
{
1049-
ProcessMagickImage((MagickImage)imgFrameM, options, ext, false);
1053+
using var imgThumbFrameM = ProcessMagickImageAndReturnThumbnail((MagickImage)imgFrameM, options, ext, false, null, null);
10501054

10511055
// apply transformation
10521056
if (i == transform?.FrameIndex || transform?.FrameIndex == -1)
@@ -1066,6 +1070,11 @@ private static async Task<IgMagickReadData> ReadMagickImageAsync(
10661070
var imgM = new MagickImage();
10671071
var hasRequestedThumbnail = false;
10681072

1073+
// get image profiles
1074+
var profiles = GetProfiles(imgColl[0]);
1075+
result.ColorProfile = profiles.ColorProfile;
1076+
result.ExifProfile = profiles.ExifProfile;
1077+
10691078

10701079
if (options.UseEmbeddedThumbnailRawFormats is true)
10711080
{
@@ -1094,26 +1103,52 @@ private static async Task<IgMagickReadData> ReadMagickImageAsync(
10941103
if (!hasRequestedThumbnail)
10951104
{
10961105
imgM.Dispose();
1097-
imgM = (MagickImage)await InitializeSingleMagickImageAsync(filePath,
1098-
imgColl[0].BaseWidth, imgColl[0].BaseHeight, settings, options, cancelToken);
1099-
}
1106+
imgM = null;
11001107

1108+
// check if the image size is not huge
1109+
var imgWidth = imgColl[0].BaseWidth;
1110+
var imgHeight = imgColl[0].BaseHeight;
1111+
var isHuge = imgWidth >= options.MinDimensionToUseWIC
1112+
|| imgHeight >= options.MinDimensionToUseWIC;
1113+
var canOpenWithWIC = WicDecoder.SupportsFileExtensionForDecoding(ext);
11011114

1102-
// process image
1103-
var processResult = ProcessMagickImage(imgM, options, ext, true);
1115+
// use WIC to load huge image
1116+
if (isHuge && canOpenWithWIC)
1117+
{
1118+
// we will open with WIC later
1119+
}
1120+
else
1121+
{
1122+
imgM = (MagickImage)await InitializeSingleMagickImageAsync(filePath,
1123+
imgWidth, imgHeight, settings, options, cancelToken);
1124+
}
1125+
}
11041126

1105-
if (processResult.ThumbM != null)
1127+
if (imgM != null)
11061128
{
1107-
imgM = processResult.ThumbM;
1108-
}
1129+
// process image
1130+
var thumbM = ProcessMagickImageAndReturnThumbnail(imgM, options, ext, true, result.ColorProfile, result.ExifProfile);
1131+
if (thumbM != null)
1132+
{
1133+
imgM.Dispose();
1134+
imgM = thumbM;
1135+
}
11091136

1137+
// apply final changes
1138+
TransformImage(imgM, transform);
11101139

1111-
// apply final changes
1112-
TransformImage(imgM, transform);
1140+
result.SingleFrameImage = imgM;
1141+
}
1142+
// use WIC to load huge image
1143+
else
1144+
{
1145+
var bmpSrc = WicBitmapSource.Load(filePath);
1146+
1147+
// apply final changes
1148+
TransformImage(bmpSrc, transform);
11131149

1114-
result.SingleFrameImage = imgM;
1115-
result.ColorProfile = processResult.ColorProfile;
1116-
result.ExifProfile = processResult.ExifProfile;
1150+
result.SingleFrameSource = bmpSrc;
1151+
}
11171152

11181153

11191154
imgColl.Dispose();
@@ -1237,28 +1272,40 @@ private static Size GetMaxImageRenderSize(uint srcWidth, uint srcHeight, uint ma
12371272

12381273

12391274
/// <summary>
1240-
/// Processes single-frame Magick image
1275+
/// Gets Color profile & Exif profile.
12411276
/// </summary>
1242-
/// <param name="refImgM">Input Magick image to process</param>
1243-
private static (IColorProfile? ColorProfile, IExifProfile? ExifProfile, MagickImage? ThumbM) ProcessMagickImage(MagickImage refImgM, CodecReadOptions options, string ext, bool requestThumbnail)
1277+
public static (IColorProfile? ColorProfile, IExifProfile? ExifProfile) GetProfiles(IMagickImage imgM)
12441278
{
12451279
IColorProfile? colorProfile = null;
12461280
IExifProfile? exifProfile = null;
1247-
IMagickImage? thumbM = null;
1248-
1249-
// preprocess image, read embedded thumbnail if any
1250-
refImgM.Quality = 100;
12511281

12521282
try
12531283
{
12541284
// get the color profile of image
1255-
colorProfile = refImgM.GetColorProfile();
1285+
colorProfile = imgM.GetColorProfile();
12561286

12571287
// Get Exif information
1258-
exifProfile = refImgM.GetExifProfile();
1288+
exifProfile = imgM.GetExifProfile();
12591289
}
12601290
catch { }
12611291

1292+
return (colorProfile, exifProfile);
1293+
}
1294+
1295+
1296+
/// <summary>
1297+
/// Processes single-frame Magick image
1298+
/// </summary>
1299+
/// <param name="refImgM">Input Magick image to process</param>
1300+
private static MagickImage? ProcessMagickImageAndReturnThumbnail(MagickImage refImgM,
1301+
CodecReadOptions options, string ext, bool requestThumbnail,
1302+
IColorProfile? colorProfile, IExifProfile? exifProfile)
1303+
{
1304+
IMagickImage? thumbM = null;
1305+
1306+
// preprocess image, read embedded thumbnail if any
1307+
refImgM.Quality = 100;
1308+
12621309
// Use embedded thumbnails if specified
12631310
if (requestThumbnail && exifProfile != null && options.UseEmbeddedThumbnailOtherFormats)
12641311
{
@@ -1313,7 +1360,7 @@ private static (IColorProfile? ColorProfile, IExifProfile? ExifProfile, MagickIm
13131360
}
13141361

13151362

1316-
return (colorProfile, exifProfile, (MagickImage?)thumbM);
1363+
return (MagickImage?)thumbM;
13171364
}
13181365

13191366

0 commit comments

Comments
 (0)