Skip to content

Commit

Permalink
Improved image loading in GKv3/Eto (fix #533)
Browse files Browse the repository at this point in the history
  • Loading branch information
Serg-Norseman committed Feb 16, 2024
1 parent b4e674f commit b8adf64
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 102 deletions.
10 changes: 2 additions & 8 deletions projects/GKCore/GKCore/BaseContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1303,14 +1303,8 @@ public IImage LoadMediaImage(GDMMultimediaRecord mmRec, int thumbWidth, int thum
}
}

if (inputStream != null) {
try {
if (inputStream.Length != 0) {
result = gfxProvider.LoadImage(inputStream, thumbWidth, thumbHeight, cutoutArea);
}
} finally {
inputStream.Dispose();
}
if (inputStream != null && inputStream.Length != 0) {
result = gfxProvider.LoadImage(inputStream, thumbWidth, thumbHeight, cutoutArea, cachedFile);
}
} catch (MediaFileNotFoundException) {
throw;
Expand Down
4 changes: 2 additions & 2 deletions projects/GKCore/GKCore/Design/Graphics/IGraphicsProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* "GEDKeeper", the personal genealogical database editor.
* Copyright (C) 2009-2023 by Sergey V. Zhdanovskih.
* Copyright (C) 2009-2024 by Sergey V. Zhdanovskih.
*
* This file is part of "GEDKeeper".
*
Expand Down Expand Up @@ -48,7 +48,7 @@ public interface IGraphicsProvider

IFont CreateFont(string fontName, float size, bool bold);

IImage LoadImage(Stream stream, int thumbWidth, int thumbHeight, ExtRect cutoutArea);
IImage LoadImage(Stream stream, int thumbWidth, int thumbHeight, ExtRect cutoutArea, string cachedFile);

/// <summary>
/// Loading an image from a file (already cached by other functions or service images/icons of application).
Expand Down
2 changes: 1 addition & 1 deletion projects/GKTests/Stubs/GfxProviderStub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public Stream CheckOrientation(Stream inputStream)
return inputStream;
}

public IImage LoadImage(Stream stream, int thumbWidth, int thumbHeight, ExtRect cutoutArea)
public IImage LoadImage(Stream stream, int thumbWidth, int thumbHeight, ExtRect cutoutArea, string cachedFile)
{
return Substitute.For<IImage>();
}
Expand Down
94 changes: 49 additions & 45 deletions projects/GKv2/GKComponents/GKUI/Platform/WFGfxProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* "GEDKeeper", the personal genealogical database editor.
* Copyright (C) 2009-2023 by Sergey V. Zhdanovskih.
* Copyright (C) 2009-2024 by Sergey V. Zhdanovskih.
*
* This file is part of "GEDKeeper".
*
Expand Down Expand Up @@ -106,62 +106,66 @@ public Stream CheckOrientation(Stream inputStream)
return transformStream;
}

public IImage LoadImage(Stream stream, int thumbWidth, int thumbHeight, ExtRect cutoutArea)
public IImage LoadImage(Stream stream, int thumbWidth, int thumbHeight, ExtRect cutoutArea, string cachedFile)
{
if (stream == null)
throw new ArgumentNullException("stream");

Bitmap bmp = new Bitmap(stream);
Bitmap result = null;

try {
int imgWidth, imgHeight;

bool cutoutIsEmpty = cutoutArea.IsEmpty();
if (cutoutIsEmpty) {
imgWidth = bmp.Width;
imgHeight = bmp.Height;
} else {
imgWidth = cutoutArea.Width;
imgHeight = cutoutArea.Height;
}
Bitmap bmp = new Bitmap(stream);
Bitmap result = null;

try {
int imgWidth, imgHeight;

bool cutoutIsEmpty = cutoutArea.IsEmpty();
if (cutoutIsEmpty) {
imgWidth = bmp.Width;
imgHeight = bmp.Height;
} else {
imgWidth = cutoutArea.Width;
imgHeight = cutoutArea.Height;
}

bool thumbIsEmpty = (thumbWidth <= 0 && thumbHeight <= 0);
if (!thumbIsEmpty) {
float ratio = GfxHelper.ZoomToFit(imgWidth, imgHeight, thumbWidth, thumbHeight);
imgWidth = (int)(imgWidth * ratio);
imgHeight = (int)(imgHeight * ratio);
}
bool thumbIsEmpty = (thumbWidth <= 0 && thumbHeight <= 0);
if (!thumbIsEmpty) {
float ratio = GfxHelper.ZoomToFit(imgWidth, imgHeight, thumbWidth, thumbHeight);
imgWidth = (int)(imgWidth * ratio);
imgHeight = (int)(imgHeight * ratio);
}

if (cutoutIsEmpty && thumbIsEmpty) {
result = bmp;
} else {
Bitmap newImage = new Bitmap(imgWidth, imgHeight, PixelFormat.Format24bppRgb);
using (Graphics graphic = Graphics.FromImage(newImage)) {
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;

if (cutoutIsEmpty) {
graphic.DrawImage(bmp, 0, 0, imgWidth, imgHeight);
} else {
//Rectangle srcRect = cutoutArea.ToRectangle();
var destRect = new Rectangle(0, 0, imgWidth, imgHeight);
graphic.DrawImage(bmp, destRect,
cutoutArea.Left, cutoutArea.Top,
cutoutArea.Width, cutoutArea.Height,
GraphicsUnit.Pixel);
if (cutoutIsEmpty && thumbIsEmpty) {
result = bmp;
} else {
Bitmap newImage = new Bitmap(imgWidth, imgHeight, PixelFormat.Format24bppRgb);
using (Graphics graphic = Graphics.FromImage(newImage)) {
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;

if (cutoutIsEmpty) {
graphic.DrawImage(bmp, 0, 0, imgWidth, imgHeight);
} else {
//Rectangle srcRect = cutoutArea.ToRectangle();
var destRect = new Rectangle(0, 0, imgWidth, imgHeight);
graphic.DrawImage(bmp, destRect,
cutoutArea.Left, cutoutArea.Top,
cutoutArea.Width, cutoutArea.Height,
GraphicsUnit.Pixel);
}
}
result = newImage;
}
result = newImage;
} finally {
if (result != bmp)
bmp.Dispose();
}

return new ImageHandler(result);
} finally {
if (result != bmp)
bmp.Dispose();
stream.Close();
}

return new ImageHandler(result);
}

public IImage LoadImage(string fileName)
Expand Down
98 changes: 57 additions & 41 deletions projects/GKv3/GKComponents/GKUI/Platform/EtoGfxProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* "GEDKeeper", the personal genealogical database editor.
* Copyright (C) 2017-2023 by Sergey V. Zhdanovskih.
* Copyright (C) 2017-2024 by Sergey V. Zhdanovskih.
*
* This file is part of "GEDKeeper".
*
Expand Down Expand Up @@ -46,59 +46,75 @@ public Stream CheckOrientation(Stream inputStream)
return transformStream;
}

public IImage LoadImage(Stream stream, int thumbWidth, int thumbHeight, ExtRect cutoutArea)
public IImage LoadImage(Stream stream, int thumbWidth, int thumbHeight, ExtRect cutoutArea, string cachedFile)
{
if (stream == null)
throw new ArgumentNullException("stream");

Bitmap bmp = new Bitmap(stream);
Bitmap result = null;

try {
int imgWidth, imgHeight;

bool cutoutIsEmpty = cutoutArea.IsEmpty();
if (cutoutIsEmpty) {
imgWidth = bmp.Width;
imgHeight = bmp.Height;
} else {
imgWidth = cutoutArea.Width;
imgHeight = cutoutArea.Height;
Bitmap bmp;
try {
bmp = new Bitmap(stream);
} catch {
try {
stream = ImageProcess.LoadProblemImage(stream, cachedFile);
bmp = new Bitmap(stream);
} catch (Exception ex2) {
Logger.WriteError("EtoGfxProvider.LoadImage()", ex2);
return null;
}
}

bool thumbIsEmpty = (thumbWidth <= 0 && thumbHeight <= 0);
if (!thumbIsEmpty) {
float ratio = GfxHelper.ZoomToFit(imgWidth, imgHeight, thumbWidth, thumbHeight);
imgWidth = (int)(imgWidth * ratio);
imgHeight = (int)(imgHeight * ratio);
}
Bitmap result = null;

try {
int imgWidth, imgHeight;

bool cutoutIsEmpty = cutoutArea.IsEmpty();
if (cutoutIsEmpty) {
imgWidth = bmp.Width;
imgHeight = bmp.Height;
} else {
imgWidth = cutoutArea.Width;
imgHeight = cutoutArea.Height;
}

bool thumbIsEmpty = (thumbWidth <= 0 && thumbHeight <= 0);
if (!thumbIsEmpty) {
float ratio = GfxHelper.ZoomToFit(imgWidth, imgHeight, thumbWidth, thumbHeight);
imgWidth = (int)(imgWidth * ratio);
imgHeight = (int)(imgHeight * ratio);
}

if (cutoutIsEmpty && thumbIsEmpty) {
result = bmp;
} else {
Bitmap newImage = new Bitmap(imgWidth, imgHeight, PixelFormat.Format24bppRgb);
using (Graphics graphic = new Graphics(newImage)) {
graphic.AntiAlias = true;
graphic.ImageInterpolation = ImageInterpolation.High;
graphic.PixelOffsetMode = PixelOffsetMode.Half;

if (cutoutIsEmpty) {
graphic.DrawImage(bmp, 0, 0, imgWidth, imgHeight);
} else {
var sourRect = new RectangleF(cutoutArea.Left, cutoutArea.Top, cutoutArea.Width, cutoutArea.Height);
var destRect = new RectangleF(0, 0, imgWidth, imgHeight);

graphic.DrawImage(bmp, sourRect, destRect);
if (cutoutIsEmpty && thumbIsEmpty) {
result = bmp;
} else {
Bitmap newImage = new Bitmap(imgWidth, imgHeight, PixelFormat.Format24bppRgb);
using (Graphics graphic = new Graphics(newImage)) {
graphic.AntiAlias = true;
graphic.ImageInterpolation = ImageInterpolation.High;
graphic.PixelOffsetMode = PixelOffsetMode.Half;

if (cutoutIsEmpty) {
graphic.DrawImage(bmp, 0, 0, imgWidth, imgHeight);
} else {
var sourRect = new RectangleF(cutoutArea.Left, cutoutArea.Top, cutoutArea.Width, cutoutArea.Height);
var destRect = new RectangleF(0, 0, imgWidth, imgHeight);

graphic.DrawImage(bmp, sourRect, destRect);
}
}
result = newImage;
}
result = newImage;
} finally {
if (result != bmp)
bmp.Dispose();
}

return new ImageHandler(result);
} finally {
if (result != bmp)
bmp.Dispose();
stream.Close();
}

return new ImageHandler(result);
}

public IImage LoadImage(string fileName)
Expand Down
17 changes: 16 additions & 1 deletion projects/GKv3/GKComponents/GKUI/Platform/ImageProcess.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* "GEDKeeper", the personal genealogical database editor.
* Copyright (C) 2009-2023 by Sergey V. Zhdanovskih, Ruslan Garipov.
* Copyright (C) 2009-2024 by Sergey V. Zhdanovskih.
*
* This file is part of "GEDKeeper".
*
Expand Down Expand Up @@ -66,5 +66,20 @@ public static Stream AutoOrient(Stream inputStream)
}
return outputStream;
}

public static Stream LoadProblemImage(Stream inputStream, string outputFileName)
{
var outputStream = new FileStream(outputFileName, FileMode.Create);
using (var image = Image.Load<Bgr565>(inputStream)) {
image.Mutate(x => x.AutoOrient());
var encoder = new BmpEncoder() { BitsPerPixel = BmpBitsPerPixel.Pixel16 };
image.SaveAsBmp(outputStream, encoder);

inputStream.Close();

outputStream.Seek(0, SeekOrigin.Begin);
}
return outputStream;
}
}
}
12 changes: 8 additions & 4 deletions projects/GKvX/GEDKeeperX/GKUI/Platform/XFGfxProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* "GEDKeeper", the personal genealogical database editor.
* Copyright (C) 2009-2023 by Sergey V. Zhdanovskih.
* Copyright (C) 2009-2024 by Sergey V. Zhdanovskih.
*
* This file is part of "GEDKeeper".
*
Expand Down Expand Up @@ -44,13 +44,17 @@ public Stream CheckOrientation(Stream inputStream)
return inputStream;
}

public IImage LoadImage(Stream stream, int thumbWidth, int thumbHeight, ExtRect cutoutArea)
public IImage LoadImage(Stream stream, int thumbWidth, int thumbHeight, ExtRect cutoutArea, string cachedFile)
{
if (stream == null)
throw new ArgumentNullException("stream");

var img = SKImage.FromEncodedData(stream);
return new SKImageHandler(img);
try {
var img = SKImage.FromEncodedData(stream);
return new SKImageHandler(img);
} finally {
stream.Close();
}
}

public IImage LoadImage(string fileName)
Expand Down

0 comments on commit b8adf64

Please sign in to comment.