Added background type option to image beautifier

This commit is contained in:
Jaex 2023-04-30 23:26:17 +03:00
parent 8ab7f77e0a
commit 8dac754484
8 changed files with 269 additions and 68 deletions

View file

@ -49,18 +49,22 @@ public class GradientInfo
[JsonIgnore]
public bool IsTransparent => IsValid && Colors.Any(x => x.Color.IsTransparent());
public GradientInfo()
public GradientInfo() : this(LinearGradientMode.Vertical)
{
Type = LinearGradientMode.Vertical;
}
public GradientInfo(LinearGradientMode type)
{
Type = type;
Colors = new List<GradientStop>();
}
public GradientInfo(params GradientStop[] colors) : this()
public GradientInfo(LinearGradientMode type, params GradientStop[] colors) : this(type)
{
Colors = colors.ToList();
}
public GradientInfo(params Color[] colors) : this()
public GradientInfo(LinearGradientMode type, params Color[] colors) : this(type)
{
for (int i = 0; i < colors.Length; i++)
{
@ -68,6 +72,14 @@ public GradientInfo(params Color[] colors) : this()
}
}
public GradientInfo(params GradientStop[] colors) : this(LinearGradientMode.Vertical, colors)
{
}
public GradientInfo(params Color[] colors) : this(LinearGradientMode.Vertical, colors)
{
}
public void Clear()
{
Colors.Clear();

View file

@ -1021,5 +1021,14 @@ public static bool IsDefaultSettings<T>(IEnumerable<T> current, IEnumerable<T> s
return true;
}
public static string GetDesktopWallpaperFilePath()
{
byte[] transcodedImageCache = (byte[])RegistryHelpers.GetValue(@"Control Panel\Desktop", "TranscodedImageCache");
byte[] transcodedImageCacheDest = new byte[transcodedImageCache.Length - 24];
Array.Copy(transcodedImageCache, 24, transcodedImageCacheDest, 0, transcodedImageCacheDest.Length);
string wallpaperFilePath = Encoding.Unicode.GetString(transcodedImageCacheDest);
return wallpaperFilePath.TrimEnd('\0');
}
}
}

View file

@ -229,18 +229,15 @@ private static Bitmap ApplyCutOutEffect(Bitmap bmp, AnchorStyles effectEdge, Cut
{
case CutOutEffectType.None:
return bmp;
case CutOutEffectType.ZigZag:
return TornEdges(bmp, effectSize, effectSize, effectEdge, false, false);
case CutOutEffectType.TornEdge:
return TornEdges(bmp, effectSize, effectSize * 2, effectEdge, false, true);
case CutOutEffectType.Wave:
return WavyEdges(bmp, effectSize, effectSize * 5, effectEdge);
}
throw new NotImplementedException(); // should not be reachable
throw new NotImplementedException();
}
public static Bitmap CutOutBitmapMiddle(Bitmap bmp, Orientation orientation, int start, int size, CutOutEffectType effectType, int effectSize)
@ -509,6 +506,48 @@ public static Bitmap AddCanvas(Image img, Padding margin, Color canvasColor)
return bmp;
}
public static Bitmap AddBackgroundImage(Bitmap bmp, Bitmap backgroundImage)
{
if (backgroundImage != null)
{
using (bmp)
using (backgroundImage)
{
Bitmap result = new Bitmap(bmp.Width, bmp.Height);
float aspectRatio = (float)backgroundImage.Width / backgroundImage.Height;
int width = result.Width;
int height = (int)(width / aspectRatio);
if (height < result.Height)
{
height = result.Height;
width = (int)(height * aspectRatio);
}
int centerX = (result.Width - width) / 2;
int centerY = (result.Height - height) / 2;
using (Graphics graphics = Graphics.FromImage(result))
{
graphics.DrawImage(backgroundImage, centerX, centerY, width, height);
graphics.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height);
}
return result;
}
}
return bmp;
}
public static Bitmap AddBackgroundImage(Bitmap bmp, string backgroundImageFilePath)
{
Bitmap backgroundImage = LoadImage(backgroundImageFilePath);
return AddBackgroundImage(bmp, backgroundImage);
}
public static Bitmap RoundedCorners(Bitmap bmp, int cornerRadius)
{
Bitmap bmpResult = bmp.CreateEmptyBitmap();

View file

@ -58,4 +58,13 @@ public enum ConverterVideoCodecs
[Description("APNG")]
apng
}
public enum ImageBeautifierBackgroundType
{
Gradient,
Color,
Image,
Desktop,
Transparent
}
}

View file

@ -46,6 +46,7 @@ private void InitializeComponent()
this.tlpMain = new System.Windows.Forms.TableLayoutPanel();
this.pbPreview = new ShareX.HelpersLib.MyPictureBox();
this.pOptions = new System.Windows.Forms.Panel();
this.cbBackgroundType = new System.Windows.Forms.ComboBox();
this.btnPrint = new System.Windows.Forms.Button();
this.btnSave = new System.Windows.Forms.Button();
this.btnUpload = new System.Windows.Forms.Button();
@ -53,6 +54,8 @@ private void InitializeComponent()
this.btnCopy = new System.Windows.Forms.Button();
this.pbBackground = new System.Windows.Forms.PictureBox();
this.ttMain = new System.Windows.Forms.ToolTip(this.components);
this.btnBackgroundImageFilePathBrowse = new System.Windows.Forms.Button();
this.lblBackgroundImageFilePath = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.tbMargin)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.tbPadding)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.tbRoundedCorner)).BeginInit();
@ -240,6 +243,9 @@ private void InitializeComponent()
//
// pOptions
//
this.pOptions.Controls.Add(this.lblBackgroundImageFilePath);
this.pOptions.Controls.Add(this.btnBackgroundImageFilePathBrowse);
this.pOptions.Controls.Add(this.cbBackgroundType);
this.pOptions.Controls.Add(this.btnPrint);
this.pOptions.Controls.Add(this.btnSave);
this.pOptions.Controls.Add(this.btnUpload);
@ -266,6 +272,16 @@ private void InitializeComponent()
this.pOptions.Size = new System.Drawing.Size(329, 755);
this.pOptions.TabIndex = 0;
//
// cbBackgroundType
//
this.cbBackgroundType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbBackgroundType.FormattingEnabled = true;
this.cbBackgroundType.Location = new System.Drawing.Point(16, 360);
this.cbBackgroundType.Name = "cbBackgroundType";
this.cbBackgroundType.Size = new System.Drawing.Size(296, 25);
this.cbBackgroundType.TabIndex = 19;
this.cbBackgroundType.SelectedIndexChanged += new System.EventHandler(this.cbBackgroundType_SelectedIndexChanged);
//
// btnPrint
//
this.btnPrint.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
@ -329,13 +345,30 @@ private void InitializeComponent()
// pbBackground
//
this.pbBackground.Cursor = System.Windows.Forms.Cursors.Hand;
this.pbBackground.Location = new System.Drawing.Point(16, 360);
this.pbBackground.Location = new System.Drawing.Point(16, 392);
this.pbBackground.Name = "pbBackground";
this.pbBackground.Size = new System.Drawing.Size(296, 40);
this.pbBackground.TabIndex = 14;
this.pbBackground.TabStop = false;
this.pbBackground.Click += new System.EventHandler(this.pbBackground_Click);
//
// btnBackgroundImageFilePathBrowse
//
this.btnBackgroundImageFilePathBrowse.Location = new System.Drawing.Point(16, 392);
this.btnBackgroundImageFilePathBrowse.Name = "btnBackgroundImageFilePathBrowse";
this.btnBackgroundImageFilePathBrowse.Size = new System.Drawing.Size(296, 32);
this.btnBackgroundImageFilePathBrowse.TabIndex = 21;
this.btnBackgroundImageFilePathBrowse.Text = "Browse image file...";
this.btnBackgroundImageFilePathBrowse.UseVisualStyleBackColor = true;
this.btnBackgroundImageFilePathBrowse.Click += new System.EventHandler(this.btnBackgroundImageFilePathBrowse_Click);
//
// lblBackgroundImageFilePath
//
this.lblBackgroundImageFilePath.Location = new System.Drawing.Point(13, 432);
this.lblBackgroundImageFilePath.Name = "lblBackgroundImageFilePath";
this.lblBackgroundImageFilePath.Size = new System.Drawing.Size(296, 120);
this.lblBackgroundImageFilePath.TabIndex = 22;
//
// ImageBeautifierForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
@ -344,7 +377,7 @@ private void InitializeComponent()
this.Controls.Add(this.tlpMain);
this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.MinimumSize = new System.Drawing.Size(1000, 600);
this.MinimumSize = new System.Drawing.Size(1000, 700);
this.Name = "ImageBeautifierForm";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
@ -387,5 +420,8 @@ private void InitializeComponent()
private System.Windows.Forms.Button btnCopy;
private System.Windows.Forms.Button btnPrint;
private System.Windows.Forms.ToolTip ttMain;
private System.Windows.Forms.ComboBox cbBackgroundType;
private System.Windows.Forms.Button btnBackgroundImageFilePathBrowse;
private System.Windows.Forms.Label lblBackgroundImageFilePath;
}
}

View file

@ -60,6 +60,9 @@ private ImageBeautifierForm(ImageBeautifierOptions options = null)
cbSmartPadding.Checked = Options.SmartPadding;
tbRoundedCorner.SetValue(Options.RoundedCorner);
tbShadowSize.SetValue(Options.ShadowSize);
cbBackgroundType.Items.AddRange(Helpers.GetLocalizedEnumDescriptions<ImageBeautifierBackgroundType>());
cbBackgroundType.SelectedIndex = (int)Options.BackgroundType;
lblBackgroundImageFilePath.Text = Options.BackgroundImageFilePath;
UpdateUI();
UpdateBackgroundPreview();
@ -83,12 +86,41 @@ private void UpdateUI()
lblPaddingValue.Text = tbPadding.Value.ToString();
lblRoundedCornerValue.Text = tbRoundedCorner.Value.ToString();
lblShadowSizeValue.Text = tbShadowSize.Value.ToString();
lblBackgroundImageFilePath.Text = Options.BackgroundImageFilePath;
}
private void UpdateBackgroundPreview()
{
pbBackground.Image?.Dispose();
pbBackground.Image = Options.Background.CreateGradientPreview(pbBackground.ClientRectangle.Width, pbBackground.ClientRectangle.Height, true, true);
pbBackground.Image = null;
switch (Options.BackgroundType)
{
case ImageBeautifierBackgroundType.Gradient:
pbBackground.Visible = true;
lblBackgroundImageFilePath.Visible = false;
btnBackgroundImageFilePathBrowse.Visible = false;
pbBackground.Image = Options.BackgroundGradient.CreateGradientPreview(pbBackground.ClientRectangle.Width, pbBackground.ClientRectangle.Height, true, true);
break;
case ImageBeautifierBackgroundType.Color:
pbBackground.Visible = true;
lblBackgroundImageFilePath.Visible = false;
btnBackgroundImageFilePathBrowse.Visible = false;
pbBackground.Image = new GradientInfo(Options.BackgroundColor).
CreateGradientPreview(pbBackground.ClientRectangle.Width, pbBackground.ClientRectangle.Height, true, true);
break;
case ImageBeautifierBackgroundType.Image:
pbBackground.Visible = false;
lblBackgroundImageFilePath.Visible = true;
btnBackgroundImageFilePathBrowse.Visible = true;
break;
case ImageBeautifierBackgroundType.Desktop:
case ImageBeautifierBackgroundType.Transparent:
pbBackground.Visible = false;
lblBackgroundImageFilePath.Visible = false;
btnBackgroundImageFilePathBrowse.Visible = false;
break;
}
}
private async Task UpdatePreview()
@ -107,7 +139,7 @@ private async Task UpdatePreview()
UpdateOptions();
Bitmap resultImage = await RenderPreviewAsync(SourceImage, Options);
Bitmap resultImage = await Options.RenderAsync(SourceImage);
PreviewImage?.Dispose();
PreviewImage = resultImage;
pbPreview.LoadImage(PreviewImage);
@ -124,52 +156,6 @@ private async Task UpdatePreview()
}
}
private static async Task<Bitmap> RenderPreviewAsync(Bitmap sourceImage, ImageBeautifierOptions options)
{
return await Task.Run(() =>
{
Bitmap resultImage = (Bitmap)sourceImage.Clone();
if (options.SmartPadding)
{
resultImage = ImageHelpers.AutoCropImage(resultImage, true, AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right, options.Padding);
}
else if (options.Padding > 0)
{
Color color = resultImage.GetPixel(0, 0);
Bitmap resultImageNew = ImageHelpers.AddCanvas(resultImage, options.Padding, color);
resultImage.Dispose();
resultImage = resultImageNew;
}
if (options.RoundedCorner > 0)
{
resultImage = ImageHelpers.RoundedCorners(resultImage, options.RoundedCorner);
}
if (options.Margin > 0)
{
Bitmap resultImageNew = ImageHelpers.AddCanvas(resultImage, options.Margin);
resultImage.Dispose();
resultImage = resultImageNew;
}
if (options.ShadowSize > 0)
{
resultImage = ImageHelpers.AddShadow(resultImage, 1f, options.ShadowSize, 0f, Color.Black, new Point(0, 0), false);
}
if (options.Background != null && options.Background.IsValid)
{
Bitmap resultImageNew = ImageHelpers.FillBackground(resultImage, options.Background);
resultImage.Dispose();
resultImage = resultImageNew;
}
return resultImage;
});
}
private void UpdateOptions()
{
Options.Margin = tbMargin.Value;
@ -264,17 +250,51 @@ private async void tbShadowSize_Scroll(object sender, EventArgs e)
await UpdatePreview();
}
private async void cbBackgroundType_SelectedIndexChanged(object sender, EventArgs e)
{
Options.BackgroundType = (ImageBeautifierBackgroundType)cbBackgroundType.SelectedIndex;
UpdateBackgroundPreview();
await UpdatePreview();
}
private async void pbBackground_Click(object sender, EventArgs e)
{
using (GradientPickerForm gradientPickerForm = new GradientPickerForm(Options.Background.Copy()))
switch (Options.BackgroundType)
{
if (gradientPickerForm.ShowDialog() == DialogResult.OK)
{
Options.Background = gradientPickerForm.Gradient;
UpdateBackgroundPreview();
case ImageBeautifierBackgroundType.Gradient:
using (GradientPickerForm gradientPickerForm = new GradientPickerForm(Options.BackgroundGradient.Copy()))
{
if (gradientPickerForm.ShowDialog() == DialogResult.OK)
{
Options.BackgroundGradient = gradientPickerForm.Gradient;
UpdateBackgroundPreview();
await UpdatePreview();
}
await UpdatePreview();
}
}
break;
case ImageBeautifierBackgroundType.Color:
if (ColorPickerForm.PickColor(Options.BackgroundColor, out Color newColor, this))
{
Options.BackgroundColor = newColor;
UpdateBackgroundPreview();
await UpdatePreview();
}
break;
}
}
private async void btnBackgroundImageFilePathBrowse_Click(object sender, EventArgs e)
{
string filePath = ImageHelpers.OpenImageFileDialog(this);
if (!string.IsNullOrEmpty(filePath))
{
Options.BackgroundImageFilePath = filePath;
await UpdatePreview();
}
}
}

View file

@ -120,6 +120,9 @@
<metadata name="ttMain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="ttMain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>58</value>
</metadata>

View file

@ -26,6 +26,8 @@
using ShareX.HelpersLib;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ShareX.MediaLib
{
@ -36,9 +38,80 @@ public class ImageBeautifierOptions
public bool SmartPadding { get; set; } = true;
public int RoundedCorner { get; set; } = 20;
public int ShadowSize { get; set; } = 30;
public GradientInfo Background { get; set; } = new GradientInfo(Color.FromArgb(255, 81, 47), Color.FromArgb(221, 36, 118))
public ImageBeautifierBackgroundType BackgroundType { get; set; } = ImageBeautifierBackgroundType.Gradient;
public GradientInfo BackgroundGradient { get; set; } = new GradientInfo(LinearGradientMode.ForwardDiagonal, Color.FromArgb(255, 81, 47), Color.FromArgb(221, 36, 118));
public Color BackgroundColor { get; set; } = Color.DarkGray;
public string BackgroundImageFilePath { get; set; } = "";
public Bitmap Render(Bitmap image)
{
Type = LinearGradientMode.ForwardDiagonal
};
Bitmap resultImage = (Bitmap)image.Clone();
if (SmartPadding)
{
resultImage = ImageHelpers.AutoCropImage(resultImage, true, AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right, Padding);
}
else if (Padding > 0)
{
Color color = resultImage.GetPixel(0, 0);
Bitmap resultImageNew = ImageHelpers.AddCanvas(resultImage, Padding, color);
resultImage.Dispose();
resultImage = resultImageNew;
}
if (RoundedCorner > 0)
{
resultImage = ImageHelpers.RoundedCorners(resultImage, RoundedCorner);
}
if (Margin > 0)
{
Bitmap resultImageNew = ImageHelpers.AddCanvas(resultImage, Margin);
resultImage.Dispose();
resultImage = resultImageNew;
}
if (ShadowSize > 0)
{
resultImage = ImageHelpers.AddShadow(resultImage, 1f, ShadowSize, 0f, Color.Black, new Point(0, 0), false);
}
switch (BackgroundType)
{
case ImageBeautifierBackgroundType.Gradient:
if (BackgroundGradient != null && BackgroundGradient.IsVisible)
{
Bitmap resultImageNew = ImageHelpers.FillBackground(resultImage, BackgroundGradient);
resultImage.Dispose();
resultImage = resultImageNew;
}
break;
case ImageBeautifierBackgroundType.Color:
if (!BackgroundColor.IsTransparent())
{
Bitmap resultImageNew = ImageHelpers.FillBackground(resultImage, BackgroundColor);
resultImage.Dispose();
resultImage = resultImageNew;
}
break;
case ImageBeautifierBackgroundType.Image:
resultImage = ImageHelpers.AddBackgroundImage(resultImage, BackgroundImageFilePath);
break;
case ImageBeautifierBackgroundType.Desktop:
string desktopWallpaperFilePath = Helpers.GetDesktopWallpaperFilePath();
resultImage = ImageHelpers.AddBackgroundImage(resultImage, desktopWallpaperFilePath);
break;
default:
case ImageBeautifierBackgroundType.Transparent:
break;
}
return resultImage;
}
public async Task<Bitmap> RenderAsync(Bitmap image)
{
return await Task.Run(() => Render(image));
}
}
}