Compare commits

...

24 Commits
v1.3 ... master

Author SHA1 Message Date
Manuel Kamper 6f1e371d33 fixed #35 2022-12-02 13:15:02 +01:00
Manuel Kamper be84e1e144 button undo unvisible at app start and only be visible for 1 undo where possible so far #32
improved handling with undo #26
improved handling for autoload and fixed button "load api" #34
implemented checking of valid api before saving #33
2022-12-02 13:00:28 +01:00
Manuel Kamper 33941b3518 fixed #31 2022-11-01 16:16:51 +01:00
Manuel Kamper 4df68efc51 partially done #26 2022-11-01 13:41:47 +01:00
Manuel Kamper aa070cd06b fixed #30
partially implemented #26
2022-11-01 13:31:11 +01:00
Manuel Kamper d29d4298eb „README.md“ ändern 2022-11-01 12:14:15 +00:00
Manuel Kamper 9c62348c7c implemented #27 2022-11-01 13:05:18 +01:00
Manuel Kamper ca035abae6 implemented #28 2022-11-01 13:00:15 +01:00
Manuel Kamper ad9d216657 Merge branch 'master' of https://git.kmpr.at/kamp/Mk0.Software.Bildduplikate 2022-10-31 21:08:26 +01:00
Manuel Kamper e1e31c34ad implemented keybard usage improvement #25 2022-10-31 21:08:22 +01:00
Manuel Kamper 64da2fc385 „README.md“ ändern 2022-10-31 20:06:42 +00:00
Manuel Kamper fbac50019c „README.md“ ändern 2022-10-31 19:10:51 +00:00
Manuel Kamper 7ebf9eea1d fixed rtf issue with path #23 2022-10-31 20:03:26 +01:00
Manuel Kamper 73dec49ac7 implemented enhanced keyboard control #22
implemented adjustment of possible worst duplicate #21
2022-10-31 19:39:12 +01:00
Manuel Kamper 7b74eca31b „README.md“ ändern 2022-10-31 18:04:13 +00:00
Manuel Kamper 0ab311b800 „README.md“ ändern 2022-10-31 18:03:26 +00:00
Manuel Kamper f5fb5d9fbb „README.md“ ändern 2022-10-31 17:59:15 +00:00
Manuel Kamper f1c0c98c40 „README.md“ ändern 2022-10-31 17:58:13 +00:00
Manuel Kamper 65ef154df8 implemented total amount of API #19 2022-10-31 18:48:36 +01:00
Manuel Kamper 8a22d68fb2 implemented auto reload from api #11 2022-10-31 18:04:05 +01:00
Manuel Kamper 4ee53f2fda implemented highlights in info values #8
added path to info values #12
implemented gighlighting of button for expected worse duplicate #20
2022-10-31 17:55:02 +01:00
Manuel Kamper 814a6e404a implemented minimum window size #13
main window on startup at center of screen #14
implemented remembering window state #15
implemented adjustable image amount loaded from API #16
fixed message when done #10
handled API connection errors #17
fixed empty replace path #18
added some comments
2022-10-31 16:39:12 +01:00
Manuel Kamper be9459e78d „README.md“ ändern 2022-10-28 13:10:21 +00:00
Manuel Kamper 3ba1f4d384 implemented API #9 2022-10-28 15:01:12 +02:00
18 changed files with 1599 additions and 294 deletions

185
Mk0.Software.Bildduplikate/API.Designer.cs generated Normal file
View File

@ -0,0 +1,185 @@

namespace Mk0.Software.Bildduplikate
{
partial class API
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.textBoxApiUrl = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.textBoxPath1 = new System.Windows.Forms.TextBox();
this.textBoxPath2 = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.buttonSave = new System.Windows.Forms.Button();
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.label4 = new System.Windows.Forms.Label();
this.checkBoxAutoLoad = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(43, 13);
this.label1.TabIndex = 0;
this.label1.Text = "API Url:";
//
// textBoxApiUrl
//
this.textBoxApiUrl.Location = new System.Drawing.Point(15, 25);
this.textBoxApiUrl.Name = "textBoxApiUrl";
this.textBoxApiUrl.Size = new System.Drawing.Size(446, 20);
this.textBoxApiUrl.TabIndex = 1;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 67);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(75, 13);
this.label2.TabIndex = 2;
this.label2.Text = "Replace Path:";
//
// textBoxPath1
//
this.textBoxPath1.Location = new System.Drawing.Point(15, 83);
this.textBoxPath1.Name = "textBoxPath1";
this.textBoxPath1.Size = new System.Drawing.Size(206, 20);
this.textBoxPath1.TabIndex = 3;
//
// textBoxPath2
//
this.textBoxPath2.Location = new System.Drawing.Point(15, 122);
this.textBoxPath2.Name = "textBoxPath2";
this.textBoxPath2.Size = new System.Drawing.Size(206, 20);
this.textBoxPath2.TabIndex = 4;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 106);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(29, 13);
this.label3.TabIndex = 5;
this.label3.Text = "with:";
//
// buttonSave
//
this.buttonSave.Location = new System.Drawing.Point(386, 141);
this.buttonSave.Name = "buttonSave";
this.buttonSave.Size = new System.Drawing.Size(75, 23);
this.buttonSave.TabIndex = 6;
this.buttonSave.Text = "Save";
this.buttonSave.UseVisualStyleBackColor = true;
this.buttonSave.Click += new System.EventHandler(this.ButtonSave_Click);
//
// numericUpDown1
//
this.numericUpDown1.Location = new System.Drawing.Point(248, 83);
this.numericUpDown1.Maximum = new decimal(new int[] {
1000,
0,
0,
0});
this.numericUpDown1.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(78, 20);
this.numericUpDown1.TabIndex = 7;
this.numericUpDown1.Value = new decimal(new int[] {
1,
0,
0,
0});
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(245, 67);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(228, 13);
this.label4.TabIndex = 8;
this.label4.Text = "Amount of images loaded per request from API:";
//
// checkBoxAutoLoad
//
this.checkBoxAutoLoad.AutoSize = true;
this.checkBoxAutoLoad.Location = new System.Drawing.Point(246, 122);
this.checkBoxAutoLoad.Name = "checkBoxAutoLoad";
this.checkBoxAutoLoad.Size = new System.Drawing.Size(179, 17);
this.checkBoxAutoLoad.TabIndex = 9;
this.checkBoxAutoLoad.Text = "Load images from API on startup";
this.checkBoxAutoLoad.UseVisualStyleBackColor = true;
//
// API
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(476, 180);
this.Controls.Add(this.checkBoxAutoLoad);
this.Controls.Add(this.label4);
this.Controls.Add(this.numericUpDown1);
this.Controls.Add(this.buttonSave);
this.Controls.Add(this.label3);
this.Controls.Add(this.textBoxPath2);
this.Controls.Add(this.textBoxPath1);
this.Controls.Add(this.label2);
this.Controls.Add(this.textBoxApiUrl);
this.Controls.Add(this.label1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "API";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "API Settings";
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBoxApiUrl;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox textBoxPath1;
private System.Windows.Forms.TextBox textBoxPath2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button buttonSave;
private System.Windows.Forms.NumericUpDown numericUpDown1;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.CheckBox checkBoxAutoLoad;
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Net;
using System.Windows.Forms;
namespace Mk0.Software.Bildduplikate
{
public partial class API : Form
{
public API()
{
InitializeComponent();
textBoxApiUrl.Text = Properties.Settings.Default.ApiUrl;
textBoxPath1.Text = Properties.Settings.Default.ReplacePath;
textBoxPath2.Text = Properties.Settings.Default.ReplaceWith;
numericUpDown1.Value = Properties.Settings.Default.imagesFromAPI;
checkBoxAutoLoad.Checked = Properties.Settings.Default.autoload;
}
private void ButtonSave_Click(object sender, EventArgs e)
{
if (!CheckWebsite(textBoxApiUrl.Text.Trim() + "?test"))
{
MessageBox.Show("The URL of the API is not valid!" + Environment.NewLine + "Settings not saved!", "No valid API", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
Properties.Settings.Default.ApiUrl = textBoxApiUrl.Text.Trim();
Properties.Settings.Default.ReplacePath = textBoxPath1.Text.Trim();
Properties.Settings.Default.ReplaceWith = textBoxPath2.Text.Trim();
Properties.Settings.Default.imagesFromAPI = (int)numericUpDown1.Value;
Properties.Settings.Default.autoload = checkBoxAutoLoad.Checked;
Properties.Settings.Default.Save();
}
}
public bool CheckWebsite(string URL)
{
try
{
WebClient wc = new WebClient();
string HTMLSource = wc.DownloadString(URL);
if (HTMLSource.Contains("API is working properly"))
{
return true;
}
return false;
}
catch (Exception)
{
return false;
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace Mk0.Software.Bildduplikate
{
class APIResponse
{
public string response_code { get; set; }
public string response_desc { get; set; }
public List<APIResponsePayload> payload { get; set; }
public string totalDuplicates { get; set; }
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace Mk0.Software.Bildduplikate
{
class APIResponsePayload
{
public string id { get; set; }
public string file1 { get; set; }
public string file2 { get; set; }
public DateTime date { get; set; }
}
}

View File

@ -1,6 +1,61 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="Mk0.Software.Bildduplikate.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<userSettings>
<Mk0.Software.Bildduplikate.Properties.Settings>
<setting name="ApiUrl" serializeAs="String">
<value />
</setting>
<setting name="ReplacePath" serializeAs="String">
<value />
</setting>
<setting name="ReplaceWith" serializeAs="String">
<value />
</setting>
<setting name="lastWidth" serializeAs="String">
<value>0</value>
</setting>
<setting name="lastHeight" serializeAs="String">
<value>0</value>
</setting>
<setting name="lastTop" serializeAs="String">
<value>0</value>
</setting>
<setting name="lastLeft" serializeAs="String">
<value>0</value>
</setting>
<setting name="fullScreen" serializeAs="String">
<value>False</value>
</setting>
<setting name="imagesFromAPI" serializeAs="String">
<value>100</value>
</setting>
<setting name="autoload" serializeAs="String">
<value>False</value>
</setting>
</Mk0.Software.Bildduplikate.Properties.Settings>
</userSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -4,6 +4,7 @@
{
private string image1;
private string image2;
private string id;
public string Path1
{
@ -13,11 +14,16 @@
{
get { return image2; }
}
public string ID
{
get { return id; }
}
public Duplicate(string image1, string image2)
public Duplicate(string image1, string image2, string id = "")
{
this.image1 = image1;
this.image2 = image2;
this.id = id;
}
}
}

View File

@ -1,216 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Mk0.Software.Bildduplikate
{
public partial class Form1 : Form
{
static readonly string[] suffixes = { "Bytes", "KB", "MB", "GB", "TB", "PB" };
private int line = 0, total = 0, offset = 0;
private string file;
private List<Duplicate> duplicates = new List<Duplicate>();
public Form1()
{
InitializeComponent();
}
private void ButtonCSV_Click(object sender, EventArgs e)
{
openFileDialog1.Title = "Select CSV";
openFileDialog1.DefaultExt = "csv";
openFileDialog1.Filter = "CSV (*.csv)|*.csv";
openFileDialog1.FilterIndex = 2;
openFileDialog1.CheckFileExists = true;
openFileDialog1.CheckPathExists = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
LoadCSV(openFileDialog1.FileName);
}
}
private void LoadCSV(string fileName)
{
line = 0;
total = 0;
file = fileName;
offset = 0;
duplicates.Clear();
using (StreamReader reader = new StreamReader(fileName))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
Duplicate d = new Duplicate(values[0], values[1]);
duplicates.Add(d);
}
}
total = duplicates.Count;
LoadDuplicates(line);
}
private void LoadDuplicates(int lineDup)
{
if (duplicates.Count > lineDup)
{
if (File.Exists(duplicates.ElementAt(lineDup).Path1) && File.Exists(duplicates.ElementAt(lineDup).Path2))
{
Image img1 = GetCopyImage(duplicates.ElementAt(lineDup).Path1);
Image img2 = GetCopyImage(duplicates.ElementAt(lineDup).Path2);
pictureBox1.Image = img1;
pictureBox2.Image = img2;
FileInfo f1 = new FileInfo(duplicates.ElementAt(lineDup).Path1);
FileInfo f2 = new FileInfo(duplicates.ElementAt(lineDup).Path2);
label1.Text = Path.GetFileName(duplicates.ElementAt(lineDup).Path1) + Environment.NewLine + FormatSize(f1.Length) + Environment.NewLine + f1.LastWriteTime + Environment.NewLine + img1.Width + "x" + img1.Height;
label2.Text = Path.GetFileName(duplicates.ElementAt(lineDup).Path2) + Environment.NewLine + FormatSize(f2.Length) + Environment.NewLine + f2.LastWriteTime + Environment.NewLine + img2.Width + "x" + img2.Height;
label3.Text = total + " Duplikate";
UIElementsVisible(true);
}
else
{
File_DeleteLine(lineDup);
total--;
line++;
LoadDuplicates(line);
}
}
else
{
MessageBox.Show("Alle Duplikate in CSV abgearbeitet", "Fertig!", MessageBoxButtons.OK, MessageBoxIcon.Information);
UIElementsVisible(false);
}
}
private void UIElementsVisible(bool vis)
{
label1.Visible = vis;
label2.Visible = vis;
label3.Visible = vis;
buttonDel1.Visible = vis;
buttonDel2.Visible = vis;
buttonKeinDuplikat.Visible = vis;
pictureBox1.Visible = vis;
pictureBox2.Visible = vis;
}
private string FormatSize(long length)
{
int counter = 0;
decimal number = (decimal)length;
while (Math.Round(number / 1024) >= 1)
{
number /= 1024;
counter++;
}
return string.Format("{0:n1}{1}", number, suffixes[counter]);
}
private void ButtonKeinDuplikat_Click(object sender, EventArgs e)
{
File_DeleteLine(line);
line++;
total--;
LoadDuplicates(line);
}
private void ButtonDel1_Click(object sender, EventArgs e)
{
File.Delete(duplicates.ElementAt(line).Path1);
File_DeleteLine(line);
line++;
total--;
LoadDuplicates(line);
}
private void ButtonDel2_Click(object sender, EventArgs e)
{
File.Delete(duplicates.ElementAt(line).Path2);
File_DeleteLine(line);
line++;
total--;
LoadDuplicates(line);
}
private Image GetCopyImage(string path)
{
using (Image image = Image.FromFile(path))
{
Bitmap bitmap = new Bitmap(image);
return bitmap;
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.C)
{
ButtonCSV_Click(sender, e);
}
else if (e.KeyCode == Keys.D1 || e.KeyCode == Keys.NumPad1)
{
ButtonDel1_Click(sender, e);
}
else if (e.KeyCode == Keys.D2 || e.KeyCode == Keys.NumPad2)
{
ButtonDel2_Click(sender, e);
}
else if (e.KeyCode == Keys.D0 || e.KeyCode == Keys.NumPad0)
{
ButtonKeinDuplikat_Click(sender, e);
}
else if (e.KeyCode == Keys.R)
{
ButtonReload_Click(sender, e);
}
}
private void ButtonReload_Click(object sender, EventArgs e)
{
LoadDuplicates(line);
}
private void File_DeleteLine(int lineFile)
{
int linetodelete = lineFile + 1 - offset;
offset++;
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(file))
{
int Countup = 0;
while (!sr.EndOfStream)
{
Countup++;
if (Countup != linetodelete)
{
using (StringWriter sw = new StringWriter(sb))
{
sw.WriteLine(sr.ReadLine());
}
}
else
{
sr.ReadLine();
}
}
}
using (StreamWriter sw = new StreamWriter(file))
{
sw.Write(sb.ToString());
}
Debug.Print("lösche Zeile " + linetodelete);
}
}
}

View File

@ -1,7 +1,7 @@

namespace Mk0.Software.Bildduplikate
{
partial class Form1
partial class Main
{
/// <summary>
/// Erforderliche Designervariable.
@ -29,12 +29,10 @@ namespace Mk0.Software.Bildduplikate
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Main));
this.buttonCSV = new System.Windows.Forms.Button();
this.buttonDel1 = new System.Windows.Forms.Button();
this.buttonDel2 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.pictureBox2 = new System.Windows.Forms.PictureBox();
this.buttonKeinDuplikat = new System.Windows.Forms.Button();
@ -43,6 +41,11 @@ namespace Mk0.Software.Bildduplikate
this.label3 = new System.Windows.Forms.Label();
this.buttonReload = new System.Windows.Forms.Button();
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
this.richTextBoxDesc1 = new System.Windows.Forms.RichTextBox();
this.richTextBoxDesc2 = new System.Windows.Forms.RichTextBox();
this.buttonAPISetting = new System.Windows.Forms.Button();
this.buttonAPILoad = new System.Windows.Forms.Button();
this.buttonUndo = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
@ -68,7 +71,7 @@ namespace Mk0.Software.Bildduplikate
// buttonDel1
//
this.buttonDel1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.buttonDel1.Location = new System.Drawing.Point(313, 3);
this.buttonDel1.Location = new System.Drawing.Point(405, 3);
this.buttonDel1.Name = "buttonDel1";
this.buttonDel1.Size = new System.Drawing.Size(75, 23);
this.buttonDel1.TabIndex = 2;
@ -88,34 +91,13 @@ namespace Mk0.Software.Bildduplikate
this.buttonDel2.Visible = false;
this.buttonDel2.Click += new System.EventHandler(this.ButtonDel2_Click);
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label1.Location = new System.Drawing.Point(-219, 29);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(604, 50);
this.label1.TabIndex = 4;
this.label1.Text = "label1";
this.label1.TextAlign = System.Drawing.ContentAlignment.TopRight;
this.label1.Visible = false;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(3, 29);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(35, 13);
this.label2.TabIndex = 5;
this.label2.Text = "label2";
this.label2.Visible = false;
//
// pictureBox1
//
this.pictureBox1.BackColor = System.Drawing.SystemColors.Control;
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(388, 315);
this.pictureBox1.Size = new System.Drawing.Size(480, 385);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBox1.TabIndex = 6;
this.pictureBox1.TabStop = false;
@ -128,7 +110,7 @@ namespace Mk0.Software.Bildduplikate
this.pictureBox2.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox2.Location = new System.Drawing.Point(0, 0);
this.pictureBox2.Name = "pictureBox2";
this.pictureBox2.Size = new System.Drawing.Size(384, 315);
this.pictureBox2.Size = new System.Drawing.Size(476, 385);
this.pictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBox2.TabIndex = 7;
this.pictureBox2.TabStop = false;
@ -138,7 +120,7 @@ namespace Mk0.Software.Bildduplikate
// buttonKeinDuplikat
//
this.buttonKeinDuplikat.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.buttonKeinDuplikat.Location = new System.Drawing.Point(280, 12);
this.buttonKeinDuplikat.Location = new System.Drawing.Point(385, 12);
this.buttonKeinDuplikat.Name = "buttonKeinDuplikat";
this.buttonKeinDuplikat.Size = new System.Drawing.Size(217, 23);
this.buttonKeinDuplikat.TabIndex = 8;
@ -163,15 +145,15 @@ namespace Mk0.Software.Bildduplikate
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.pictureBox2);
this.splitContainer1.Size = new System.Drawing.Size(776, 315);
this.splitContainer1.SplitterDistance = 388;
this.splitContainer1.Size = new System.Drawing.Size(960, 385);
this.splitContainer1.SplitterDistance = 480;
this.splitContainer1.TabIndex = 9;
this.splitContainer1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
//
// label3
//
this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label3.Location = new System.Drawing.Point(598, 17);
this.label3.Location = new System.Drawing.Point(782, 17);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(190, 23);
this.label3.TabIndex = 10;
@ -193,28 +175,95 @@ namespace Mk0.Software.Bildduplikate
//
this.splitContainer2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.splitContainer2.Location = new System.Drawing.Point(12, 362);
this.splitContainer2.Location = new System.Drawing.Point(12, 429);
this.splitContainer2.Name = "splitContainer2";
//
// splitContainer2.Panel1
//
this.splitContainer2.Panel1.Controls.Add(this.richTextBoxDesc1);
this.splitContainer2.Panel1.Controls.Add(this.buttonDel1);
this.splitContainer2.Panel1.Controls.Add(this.label1);
//
// splitContainer2.Panel2
//
this.splitContainer2.Panel2.Controls.Add(this.richTextBoxDesc2);
this.splitContainer2.Panel2.Controls.Add(this.buttonDel2);
this.splitContainer2.Panel2.Controls.Add(this.label2);
this.splitContainer2.Size = new System.Drawing.Size(775, 81);
this.splitContainer2.SplitterDistance = 388;
this.splitContainer2.Size = new System.Drawing.Size(959, 115);
this.splitContainer2.SplitterDistance = 480;
this.splitContainer2.TabIndex = 12;
this.splitContainer2.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
//
// Form1
// richTextBoxDesc1
//
this.richTextBoxDesc1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.richTextBoxDesc1.BackColor = System.Drawing.SystemColors.Control;
this.richTextBoxDesc1.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.richTextBoxDesc1.Location = new System.Drawing.Point(3, 32);
this.richTextBoxDesc1.Name = "richTextBoxDesc1";
this.richTextBoxDesc1.ReadOnly = true;
this.richTextBoxDesc1.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
this.richTextBoxDesc1.Size = new System.Drawing.Size(474, 78);
this.richTextBoxDesc1.TabIndex = 4;
this.richTextBoxDesc1.Text = "";
this.richTextBoxDesc1.Visible = false;
//
// richTextBoxDesc2
//
this.richTextBoxDesc2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.richTextBoxDesc2.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.richTextBoxDesc2.Location = new System.Drawing.Point(0, 32);
this.richTextBoxDesc2.Name = "richTextBoxDesc2";
this.richTextBoxDesc2.ReadOnly = true;
this.richTextBoxDesc2.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
this.richTextBoxDesc2.Size = new System.Drawing.Size(469, 78);
this.richTextBoxDesc2.TabIndex = 5;
this.richTextBoxDesc2.Text = "";
this.richTextBoxDesc2.Visible = false;
//
// buttonAPISetting
//
this.buttonAPISetting.Location = new System.Drawing.Point(174, 12);
this.buttonAPISetting.Name = "buttonAPISetting";
this.buttonAPISetting.Size = new System.Drawing.Size(75, 23);
this.buttonAPISetting.TabIndex = 13;
this.buttonAPISetting.Text = "API Setting";
this.buttonAPISetting.UseVisualStyleBackColor = true;
this.buttonAPISetting.Click += new System.EventHandler(this.ButtonAPI_Click);
//
// buttonAPILoad
//
this.buttonAPILoad.Location = new System.Drawing.Point(255, 12);
this.buttonAPILoad.Name = "buttonAPILoad";
this.buttonAPILoad.Size = new System.Drawing.Size(75, 23);
this.buttonAPILoad.TabIndex = 14;
this.buttonAPILoad.Text = "Load API";
this.buttonAPILoad.UseVisualStyleBackColor = true;
this.buttonAPILoad.Visible = false;
this.buttonAPILoad.Click += new System.EventHandler(this.ButtonAPILoad_Click);
//
// buttonUndo
//
this.buttonUndo.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.buttonUndo.Location = new System.Drawing.Point(608, 12);
this.buttonUndo.Name = "buttonUndo";
this.buttonUndo.Size = new System.Drawing.Size(75, 23);
this.buttonUndo.TabIndex = 15;
this.buttonUndo.Text = "undo";
this.buttonUndo.UseVisualStyleBackColor = true;
this.buttonUndo.Visible = false;
this.buttonUndo.Click += new System.EventHandler(this.ButtonUndo_Click);
//
// Main
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.ClientSize = new System.Drawing.Size(984, 551);
this.Controls.Add(this.buttonUndo);
this.Controls.Add(this.buttonAPILoad);
this.Controls.Add(this.buttonAPISetting);
this.Controls.Add(this.splitContainer2);
this.Controls.Add(this.buttonReload);
this.Controls.Add(this.label3);
@ -223,8 +272,12 @@ namespace Mk0.Software.Bildduplikate
this.Controls.Add(this.buttonCSV);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.KeyPreview = true;
this.Name = "Form1";
this.Text = "Bildduplikate v1.3 by kmpr.at";
this.MinimumSize = new System.Drawing.Size(1000, 590);
this.Name = "Main";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Bildduplikate v1.10 by kmpr.at";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Main_FormClosing);
this.Shown += new System.EventHandler(this.Main_Shown);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
@ -234,7 +287,6 @@ namespace Mk0.Software.Bildduplikate
this.splitContainer1.ResumeLayout(false);
this.splitContainer2.Panel1.ResumeLayout(false);
this.splitContainer2.Panel2.ResumeLayout(false);
this.splitContainer2.Panel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
this.splitContainer2.ResumeLayout(false);
this.ResumeLayout(false);
@ -246,8 +298,6 @@ namespace Mk0.Software.Bildduplikate
private System.Windows.Forms.Button buttonCSV;
private System.Windows.Forms.Button buttonDel1;
private System.Windows.Forms.Button buttonDel2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.PictureBox pictureBox2;
private System.Windows.Forms.Button buttonKeinDuplikat;
@ -256,6 +306,11 @@ namespace Mk0.Software.Bildduplikate
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button buttonReload;
private System.Windows.Forms.SplitContainer splitContainer2;
private System.Windows.Forms.Button buttonAPISetting;
private System.Windows.Forms.Button buttonAPILoad;
private System.Windows.Forms.RichTextBox richTextBoxDesc1;
private System.Windows.Forms.RichTextBox richTextBoxDesc2;
private System.Windows.Forms.Button buttonUndo;
}
}

View File

@ -0,0 +1,827 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Web.Script.Serialization;
namespace Mk0.Software.Bildduplikate
{
public partial class Main : Form
{
static readonly string[] suffixes = { "Bytes", "KB", "MB", "GB", "TB", "PB" };
private int line = 0, total = 0, offset = 0;
private string file;
private bool api = false;
private int worst = 0;
private int lastStep = 0;
private List<Duplicate> duplicates = new List<Duplicate>();
internal List<Duplicate> Duplicates { get => duplicates; set => duplicates = value; }
public Main()
{
InitializeComponent();
}
/// <summary>
/// Select CSV with possible duplicates
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonCSV_Click(object sender, EventArgs e)
{
openFileDialog1.Title = "Select CSV";
openFileDialog1.DefaultExt = "csv";
openFileDialog1.Filter = "CSV (*.csv)|*.csv";
openFileDialog1.FilterIndex = 2;
openFileDialog1.CheckFileExists = true;
openFileDialog1.CheckPathExists = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
LoadCSV(openFileDialog1.FileName);
}
}
/// <summary>
/// Load possible duplicates from CSV
/// </summary>
/// <param name="fileName"></param>
private void LoadCSV(string fileName)
{
line = 0;
total = 0;
file = fileName;
offset = 0;
Duplicates.Clear();
using (StreamReader reader = new StreamReader(fileName))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
Duplicate d = new Duplicate(values[0], values[1]);
Duplicates.Add(d);
}
}
total = Duplicates.Count;
api = false;
LoadDuplicates(line);
}
/// <summary>
/// Process for manual duplicate processing
/// </summary>
/// <param name="lineDup"></param>
/// <param name="api"></param>
private void LoadDuplicates(int lineDup, bool api = false)
{
if (Duplicates.Count > lineDup)
{
if (File.Exists(Duplicates.ElementAt(lineDup).Path1) && File.Exists(Duplicates.ElementAt(lineDup).Path2))
{
Image img1 = GetCopyImage(Duplicates.ElementAt(lineDup).Path1);
Image img2 = GetCopyImage(Duplicates.ElementAt(lineDup).Path2);
pictureBox1.Image = img1;
pictureBox2.Image = img2;
FileInfo f1 = new FileInfo(Duplicates.ElementAt(lineDup).Path1);
FileInfo f2 = new FileInfo(Duplicates.ElementAt(lineDup).Path2);
int dup1 = 0, dup2 = 0;
string size1, size2;
if (f1.Length == f2.Length)
{
size1 = @" \b " + FormatSize(f1.Length) + @" \b0 ";
size2 = @" \b " + FormatSize(f2.Length) + @" \b0 ";
dup1++;
dup1++;
dup2++;
dup2++;
}
else if (f1.Length > f2.Length)
{
size1 = @" \b " + FormatSize(f1.Length) + @" \b0 ";
size2 = FormatSize(f2.Length);
dup1++;
dup1++;
}
else
{
size1 = FormatSize(f1.Length);
size2 = @" \b " + FormatSize(f2.Length) + @" \b0 ";
dup2++;
dup2++;
}
string filePath1 = GetRtfUnicodeEscapedString(Path.GetDirectoryName(Duplicates.ElementAt(lineDup).Path1));
string filePath2 = GetRtfUnicodeEscapedString(Path.GetDirectoryName(Duplicates.ElementAt(lineDup).Path2));
if (filePath1 == filePath2)
{
filePath1 = @" \b " + filePath1 + @" \b0 ";
filePath2 = @" \b " + filePath2 + @" \b0 ";
dup1++;
dup2++;
}
string fileName1 = Path.GetFileName(Duplicates.ElementAt(lineDup).Path1);
string fileName2 = Path.GetFileName(Duplicates.ElementAt(lineDup).Path2);
if (fileName1 == fileName2)
{
fileName1 = @" \b " + GetRtfUnicodeEscapedString(fileName1) + @" \b0 ";
fileName2 = @" \b " + GetRtfUnicodeEscapedString(fileName2) + @" \b0 ";
dup1++;
dup2++;
}
else
{
if (fileName1.Count(Char.IsDigit) < fileName2.Count(Char.IsDigit))
{
fileName1 = @" \b " + GetRtfUnicodeEscapedString(fileName1) + @" \b0 ";
fileName2 = GetRtfUnicodeEscapedString(fileName2);
dup1++;
}
else if (fileName2.Count(Char.IsDigit) < fileName1.Count(Char.IsDigit))
{
fileName1 = GetRtfUnicodeEscapedString(fileName1);
fileName2 = @" \b " + GetRtfUnicodeEscapedString(fileName2) + @" \b0 ";
dup2++;
}
else
{
if (fileName1.Length > fileName2.Length)
{
fileName1 = GetRtfUnicodeEscapedString(fileName1);
fileName2 = @" \b " + GetRtfUnicodeEscapedString(fileName2) + @" \b0 ";
dup2++;
}
else if (fileName2.Length > fileName1.Length)
{
fileName1 = @" \b " + GetRtfUnicodeEscapedString(fileName1) + @" \b0 ";
fileName2 = GetRtfUnicodeEscapedString(fileName2);
dup1++;
}
else
{
}
}
}
DateTime lastTime1 = f1.LastWriteTime;
DateTime lastTime2 = f2.LastWriteTime;
string lastTime1str, lastTime2str;
if (lastTime1 == lastTime2)
{
lastTime1str = @" \b " + lastTime1.ToString() + @" \b0 ";
lastTime2str = @" \b " + lastTime2.ToString() + @" \b0 ";
dup1++;
dup2++;
}
else if (lastTime1 > lastTime2)
{
lastTime1str = @" \b " + lastTime1.ToString() + @" \b0 ";
lastTime2str = lastTime2.ToString();
dup1++;
}
else
{
lastTime1str = lastTime1.ToString();
lastTime2str = @" \b " + lastTime2.ToString() + @" \b0 ";
dup2++;
}
float res1 = img1.HorizontalResolution;
float res2 = img2.HorizontalResolution;
string res1str, res2str;
if (res1 == res2)
{
if (img1.Height == img2.Height && img1.Width == img2.Width)
{
res1str = @" \b " + img1.Width + "x" + img1.Height + " @ " + res1 + " DPI" + @" \b0 ";
res2str = @" \b " + img2.Width + "x" + img2.Height + " @ " + res2 + " DPI" + @" \b0 ";
dup1++;
dup1++;
dup2++;
dup2++;
}
else if (img1.Height > img2.Height && img1.Width > img2.Width)
{
res1str = @" \b " + img1.Width + "x" + img1.Height + " @ " + res1 + " DPI" + @" \b0 ";
res2str = img2.Width + "x" + img2.Height + " @ " + res2 + " DPI";
dup1++;
dup1++;
}
else if (img2.Height > img1.Height && img2.Width > img1.Width)
{
res1str = img1.Width + "x" + img1.Height + " @ " + res1 + " DPI";
res2str = @" \b " + img2.Width + "x" + img2.Height + " @ " + res2 + " DPI" + @" \b0 ";
dup2++;
dup2++;
}
else
{
res1str = img1.Width + "x" + img1.Height + " @ " + res1 + " DPI";
res2str = img2.Width + "x" + img2.Height + " @ " + res2 + " DPI";
}
}
else if (res1 > res2)
{
res1str = @" \b " + img1.Width + "x" + img1.Height + " @ " + res1 + " DPI" + @" \b0 ";
res2str = img2.Width + "x" + img2.Height + " @ " + res2 + " DPI";
dup1++;
dup1++;
}
else
{
res1str = img1.Width + "x" + img1.Height + " @ " + res1 + " DPI";
res2str = @" \b " + img2.Width + "x" + img2.Height + " @ " + res2 + " DPI" + @" \b0 ";
dup2++;
dup2++;
}
richTextBoxDesc1.Rtf = @"{\rtf1\ansi " + filePath1 + @" \line " + fileName1 + @" \line " + size1 + @" \line " + lastTime1str + @" \line " + res1str + " }";
richTextBoxDesc2.Rtf = @"{\rtf1\ansi " + filePath2 + @" \line " + fileName2 + @" \line " + size2 + @" \line " + lastTime2str + @" \line " + res2str + " }";
richTextBoxDesc1.SelectAll();
richTextBoxDesc1.SelectionAlignment = HorizontalAlignment.Right;
label3.Text = total + " Duplikate";
ButtonHighlight(dup1, dup2);
UIElementsVisible(true);
}
else
{
if (api)
{
try
{
WebClient webClient = new WebClient();
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
string json = webClient.UploadString(Properties.Settings.Default.ApiUrl + "?isDuplicate", "{\"duplicateId\":" + Duplicates.ElementAt(lineDup).ID + "}");
var resObj = new JavaScriptSerializer().Deserialize<APIResponse>(json);
if (resObj.response_code != "200") { MessageBox.Show(resObj.response_desc, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); }
else
{
total--;
line++;
LoadDuplicates(line, api);
}
}
catch (Exception ex)
{
MessageBox.Show("Fehler bei der Kommunikation mit der API:" + Environment.NewLine + ex.ToString(), "API Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
File_DeleteLine(lineDup);
total--;
line++;
LoadDuplicates(line, api);
}
}
}
else
{
if (api)
{
ButtonAPILoad_Click(null, null);
}
else
{
UIElementsVisible(false);
MessageBox.Show("Alle Duplikate in CSV abgearbeitet", "Fertig!", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
/// <summary>
/// Highlight Button which is possibly the worst duplicate
/// </summary>
/// <param name="dup1"></param>
/// <param name="dup2"></param>
private void ButtonHighlight(int dup1, int dup2)
{
if (dup1 < dup2)
{
buttonDel1.Font = new Font(buttonDel1.Font.Name, buttonDel1.Font.Size, FontStyle.Bold);
buttonDel2.Font = new Font(buttonDel2.Font.Name, buttonDel2.Font.Size, FontStyle.Regular);
worst = 1;
}
else if (dup2 < dup1)
{
buttonDel1.Font = new Font(buttonDel1.Font.Name, buttonDel1.Font.Size, FontStyle.Regular);
buttonDel2.Font = new Font(buttonDel2.Font.Name, buttonDel2.Font.Size, FontStyle.Bold);
worst = 2;
}
else
{
buttonDel1.Font = new Font(buttonDel1.Font.Name, buttonDel1.Font.Size, FontStyle.Regular);
buttonDel2.Font = new Font(buttonDel2.Font.Name, buttonDel2.Font.Size, FontStyle.Regular);
worst = 0;
}
}
/// <summary>
/// Helper for RTF Unicode
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private static string GetRtfUnicodeEscapedString(string s)
{
var sb = new StringBuilder();
foreach (var c in s)
{
if (c == '\\' || c == '{' || c == '}')
sb.Append(@"\" + c);
else if (c <= 0x7f)
sb.Append(c);
else
sb.Append("\\u" + Convert.ToUInt32(c) + "?");
}
return sb.ToString();
}
/// <summary>
/// UI-Elements shown or not shown
/// </summary>
/// <param name="vis"></param>
private void UIElementsVisible(bool vis)
{
richTextBoxDesc1.Visible = vis;
richTextBoxDesc2.Visible = vis;
label3.Visible = vis;
buttonDel1.Visible = vis;
buttonDel2.Visible = vis;
buttonKeinDuplikat.Visible = vis;
pictureBox1.Visible = vis;
pictureBox2.Visible = vis;
}
/// <summary>
/// Format string of file size
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
private string FormatSize(long length)
{
int counter = 0;
decimal number = (decimal)length;
while (Math.Round(number / 1024) >= 1)
{
number /= 1024;
counter++;
}
return string.Format("{0:n1}{1}", number, suffixes[counter]);
}
/// <summary>
/// Mark images as non-duplicates
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonKeinDuplikat_Click(object sender, EventArgs e)
{
if (api)
{
try
{
WebClient webClient = new WebClient();
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
string json = webClient.UploadString(Properties.Settings.Default.ApiUrl + "?noDuplicate", "{\"duplicateId\":" + Duplicates.ElementAt(line).ID + "}");
var resObj = new JavaScriptSerializer().Deserialize<APIResponse>(json);
if (resObj.response_code != "200") { MessageBox.Show(resObj.response_desc, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); }
else
{
total--;
line++;
LoadDuplicates(line, api);
lastStep = 1;
}
}
catch (Exception ex)
{
MessageBox.Show("Fehler bei der Kommunikation mit der API:" + Environment.NewLine + ex.ToString(), "API Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
buttonUndo.Visible = true;
}
else
{
File_DeleteLine(line);
total--;
line++;
LoadDuplicates(line, api);
lastStep = 0;
}
}
/// <summary>
/// Delete duplicate file1
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonDel1_Click(object sender, EventArgs e)
{
if (api)
{
try
{
WebClient webClient = new WebClient();
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
string json = webClient.UploadString(Properties.Settings.Default.ApiUrl + "?isDuplicate", "{\"duplicateId\":" + Duplicates.ElementAt(line).ID + "}");
var resObj = new JavaScriptSerializer().Deserialize<APIResponse>(json);
if (resObj.response_code != "200") { MessageBox.Show(resObj.response_desc, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); }
else
{
File.Delete(Duplicates.ElementAt(line).Path1);
total--;
line++;
LoadDuplicates(line, api);
lastStep = 2;
}
//todo erst einkommentieren, wenn es die möglichkeit gibt, gelöschte wiederherzustellen
//buttonUndo.Visible = true;
}
catch (Exception ex)
{
MessageBox.Show("Fehler bei der Kommunikation mit der API:" + Environment.NewLine + ex.ToString(), "API Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
File.Delete(Duplicates.ElementAt(line).Path1);
File_DeleteLine(line);
line++;
total--;
LoadDuplicates(line);
lastStep = 0;
}
}
/// <summary>
/// Delete duplicate file2
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonDel2_Click(object sender, EventArgs e)
{
if (api)
{
try
{
WebClient webClient = new WebClient();
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
string json = webClient.UploadString(Properties.Settings.Default.ApiUrl + "?isDuplicate", "{\"duplicateId\":" + Duplicates.ElementAt(line).ID + "}");
var resObj = new JavaScriptSerializer().Deserialize<APIResponse>(json);
if (resObj.response_code != "200") { MessageBox.Show(resObj.response_desc, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); }
else
{
File.Delete(Duplicates.ElementAt(line).Path2);
total--;
line++;
LoadDuplicates(line, api);
lastStep = 2;
}
//todo erst einkommentieren, wenn es die möglichkeit gibt, gelöschte wiederherzustellen
//buttonUndo.Visible = true;
}
catch (Exception ex)
{
MessageBox.Show("Fehler bei der Kommunikation mit der API:" + Environment.NewLine + ex.ToString(), "API Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
File.Delete(Duplicates.ElementAt(line).Path2);
File_DeleteLine(line);
line++;
total--;
LoadDuplicates(line);
lastStep = 0;
}
}
/// <summary>
/// Helper for showing images and being able to delete them
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private Image GetCopyImage(string path)
{
using (Image image = Image.FromFile(path))
{
Bitmap bitmap = new Bitmap(image);
return bitmap;
}
}
/// <summary>
/// Keyboard control handling for duplicate processing
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.C)
{
ButtonCSV_Click(sender, e);
}
else if (e.KeyCode == Keys.D1 || e.KeyCode == Keys.NumPad1)
{
ButtonDel1_Click(sender, e);
}
else if (e.KeyCode == Keys.D2 || e.KeyCode == Keys.NumPad2)
{
ButtonDel2_Click(sender, e);
}
else if (e.KeyCode == Keys.D0 || e.KeyCode == Keys.NumPad0 || e.KeyCode == Keys.K)
{
ButtonKeinDuplikat_Click(sender, e);
}
else if (e.KeyCode == Keys.R)
{
ButtonReload_Click(sender, e);
}
else if (e.KeyCode == Keys.D)
{
DeleteWorstDuplicate();
}
else if (e.KeyCode == Keys.A)
{
ButtonAPI_Click(sender, e);
}
else if (e.KeyCode == Keys.C)
{
ButtonCSV_Click(sender, e);
}
else if (e.KeyCode == Keys.L)
{
ButtonAPILoad_Click(sender, e);
}
}
/// <summary>
/// Deletes the most probably worst duplicate
/// </summary>
private void DeleteWorstDuplicate()
{
if (worst == 1)
{
ButtonDel1_Click(null, null);
}
else if (worst == 2)
{
ButtonDel2_Click(null, null);
}
else
{
ButtonDel2_Click(null, null);
//MessageBox.Show("Keines der beiden Bilder konnte als besser oder schlechter erkannt werden, bitte wählen sie selbst!", "Ooops...", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
/// <summary>
/// Show API Settings Dialog
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonAPI_Click(object sender, EventArgs e)
{
API api = new API();
api.ShowDialog();
if (Properties.Settings.Default.ApiUrl != String.Empty)
{
buttonAPILoad.Visible = true;
if (Properties.Settings.Default.autoload)
{
ButtonAPILoad_Click(null, null);
}
}
else
{
buttonAPILoad.Visible = false;
}
}
/// <summary>
/// Loads possible duplicates from API
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonAPILoad_Click(object sender, EventArgs e)
{
try
{
WebClient webClient = new WebClient();
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
string json = webClient.UploadString(Properties.Settings.Default.ApiUrl + "?getDuplicates", "{\"amount\":" + Properties.Settings.Default.imagesFromAPI + "}");
var resObj = new JavaScriptSerializer().Deserialize<APIResponse>(json);
if (resObj.response_code != "200") { MessageBox.Show(resObj.response_desc, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); }
else
{
Duplicates.Clear();
line = 0;
total = 0;
file = "";
api = true;
offset = 0;
foreach (APIResponsePayload pl in resObj.payload)
{
Duplicate d = new Duplicate(ReplacePath(pl.file1), ReplacePath(pl.file2), pl.id);
Duplicates.Add(d);
}
WebClient webClient2 = new WebClient();
webClient2.Headers[HttpRequestHeader.ContentType] = "application/json";
string json2 = webClient.UploadString(Properties.Settings.Default.ApiUrl + "?totalDuplicates", "");
var resObj2 = new JavaScriptSerializer().Deserialize<APIResponse>(json2);
if (resObj2.response_code != "200") { MessageBox.Show(resObj2.response_desc, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); }
else
{
total = int.Parse(resObj2.totalDuplicates);
}
if (total == 0)
{
UIElementsVisible(false);
MessageBox.Show("Alle Duplikate von API abgearbeitet", "Fertig!", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
LoadDuplicates(line, true);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Fehler bei der Kommunikation mit der API:" + Environment.NewLine + ex.ToString(), "API Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// Replaces API saved path with local (or network) path
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
private string ReplacePath(string file)
{
if (Properties.Settings.Default.ReplacePath == String.Empty)
{
return file;
}
return file.Replace(Properties.Settings.Default.ReplacePath, Properties.Settings.Default.ReplaceWith);
}
/// <summary>
/// Handling when Window is closing
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Main_FormClosing(object sender, FormClosingEventArgs e)
{
Properties.Settings.Default.lastWidth = Width;
Properties.Settings.Default.lastHeight = Height;
Properties.Settings.Default.lastTop = Top;
Properties.Settings.Default.lastLeft = Left;
Properties.Settings.Default.fullScreen = WindowState == FormWindowState.Maximized;
Properties.Settings.Default.Save();
}
/// <summary>
/// Window handling when Window is Shown Event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Main_Shown(object sender, EventArgs e)
{
if (Properties.Settings.Default.fullScreen)
{
WindowState = FormWindowState.Maximized;
}
else
{
if (Properties.Settings.Default.lastHeight >= MinimumSize.Height)
{
Height = Properties.Settings.Default.lastHeight;
}
if (Properties.Settings.Default.lastWidth >= MinimumSize.Width)
{
Width = Properties.Settings.Default.lastWidth;
}
if (Properties.Settings.Default.lastTop <= Screen.PrimaryScreen.Bounds.Height && Properties.Settings.Default.lastTop >= 0)
{
Top = Properties.Settings.Default.lastTop;
}
if (Properties.Settings.Default.lastLeft <= Screen.PrimaryScreen.Bounds.Width && Properties.Settings.Default.lastLeft >= 0)
{
Left = Properties.Settings.Default.lastLeft;
}
}
if (Properties.Settings.Default.ApiUrl != String.Empty)
{
buttonAPILoad.Visible = true;
if (Properties.Settings.Default.autoload)
{
ButtonAPILoad_Click(null, null);
}
}
}
/// <summary>
/// Undo last processing step
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonUndo_Click(object sender, EventArgs e)
{
if (lastStep == 1)
{
//undo mark as non-duplicate
try
{
WebClient webClient = new WebClient();
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
string json = webClient.UploadString(Properties.Settings.Default.ApiUrl + "?undoDuplicate", "{\"duplicateId\":" + Duplicates.ElementAt(line - 1).ID + "}");
var resObj = new JavaScriptSerializer().Deserialize<APIResponse>(json);
if (resObj.response_code != "200") { MessageBox.Show(resObj.response_desc, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); }
else
{
File.Delete(Duplicates.ElementAt(line).Path2);
total++;
line--;
LoadDuplicates(line, api);
lastStep = 1;
}
}
catch (Exception ex)
{
MessageBox.Show("Fehler bei der Kommunikation mit der API:" + Environment.NewLine + ex.ToString(), "API Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
buttonUndo.Visible = false;
}
else if (lastStep == 2)
{
//undo delete duplicate
lastStep = 0;
}
else
{
MessageBox.Show("Keine Aktion die Rückgängig gemacht werden kann. Undo funktioniert grundsätzlich nur bei API Bildvergleichen, nicht bei CSV.", "Nix da", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
//lastStep = 0;
}
/// <summary>
/// Reloads CSV / API
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ButtonReload_Click(object sender, EventArgs e)
{
LoadDuplicates(line);
}
/// <summary>
/// Delete specified line in CSV file
/// </summary>
/// <param name="lineFile"></param>
private void File_DeleteLine(int lineFile)
{
int linetodelete = lineFile + 1 - offset;
offset++;
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(file))
{
int Countup = 0;
while (!sr.EndOfStream)
{
Countup++;
if (Countup != linetodelete)
{
using (StringWriter sw = new StringWriter(sb))
{
sw.WriteLine(sr.ReadLine());
}
}
else
{
sr.ReadLine();
}
}
}
using (StreamWriter sw = new StreamWriter(file))
{
sw.Write(sb.ToString());
}
Debug.Print("lösche Zeile " + linetodelete);
}
}
}

View File

@ -24,7 +24,7 @@
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.3.0.0</ApplicationVersion>
<ApplicationVersion>1.10.0.0</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
@ -65,7 +65,18 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@ -77,17 +88,28 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="APIResponse.cs" />
<Compile Include="APIResponsePayload.cs" />
<Compile Include="Duplicate.cs" />
<Compile Include="Form1.cs">
<Compile Include="Main.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
<Compile Include="Main.Designer.cs">
<DependentUpon>Main.cs</DependentUpon>
</Compile>
<Compile Include="API.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="API.Designer.cs">
<DependentUpon>API.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
<EmbeddedResource Include="API.resx">
<DependentUpon>API.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Main.resx">
<DependentUpon>Main.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
@ -99,6 +121,7 @@
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Mk0.Software.Bildduplikate_TemporaryKey.pfx" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>

View File

@ -16,7 +16,7 @@ namespace Mk0.Software.Bildduplikate
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
Application.Run(new Main());
}
}
}

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
// indem Sie "*" wie unten gezeigt eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.3.0.0")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyVersion("1.10.0.0")]
[assembly: AssemblyFileVersion("1.10.0.0")]

View File

@ -1,29 +1,146 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Mk0.Software.Bildduplikate.Properties
{
namespace Mk0.Software.Bildduplikate.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string ApiUrl {
get {
return ((string)(this["ApiUrl"]));
}
set {
this["ApiUrl"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string ReplacePath {
get {
return ((string)(this["ReplacePath"]));
}
set {
this["ReplacePath"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string ReplaceWith {
get {
return ((string)(this["ReplaceWith"]));
}
set {
this["ReplaceWith"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int lastWidth {
get {
return ((int)(this["lastWidth"]));
}
set {
this["lastWidth"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int lastHeight {
get {
return ((int)(this["lastHeight"]));
}
set {
this["lastHeight"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int lastTop {
get {
return ((int)(this["lastTop"]));
}
set {
this["lastTop"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int lastLeft {
get {
return ((int)(this["lastLeft"]));
}
set {
this["lastLeft"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool fullScreen {
get {
return ((bool)(this["fullScreen"]));
}
set {
this["fullScreen"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("100")]
public int imagesFromAPI {
get {
return ((int)(this["imagesFromAPI"]));
}
set {
this["imagesFromAPI"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool autoload {
get {
return ((bool)(this["autoload"]));
}
set {
this["autoload"] = value;
}
}
}
}

View File

@ -1,7 +1,36 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Mk0.Software.Bildduplikate.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="ApiUrl" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="ReplacePath" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="ReplaceWith" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="lastWidth" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="lastHeight" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="lastTop" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="lastLeft" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="fullScreen" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="imagesFromAPI" Type="System.Int32" Scope="User">
<Value Profile="(Default)">100</Value>
</Setting>
<Setting Name="autoload" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
<package id="System.Memory" version="4.5.5" targetFramework="net48" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.3" targetFramework="net48" />
</packages>

View File

@ -1 +1,20 @@
This program allows to compare possible image duplicates from a CSV (you can use python script https://git.kmpr.at/kamp/SimilarImages to find them and generate the CSV file) and delete one of the duplicates.
# Bildduplikate
## About
This program allows to compare possible image duplicates from a CSV (you can use python script https://git.kmpr.at/kamp/SimilarImages to find them and generate the CSV file) or an API (https://git.kmpr.at/kamp/DuplicateAPI which can be fed by the same python script) and delete one of the duplicates or mark the duplicates as non-duplicates (for API).
## Features
* Can read possible duplicates from a CSV files
* Can read possible duplicates from an API
* suggestion of most probably "worse" duplicate to delete
* keyboard control functions for faster processing
## Keyboard Control
[1] - delete first possible duplicate
[2] - delete second possible duplicate
[0] or [K] - mark images as non-duplicates
[D] delete most probably worst indicated duplicate (which has the bold delete button)
[A] Opens API Settings
[C] Load CSV
[R] Reload
[L] Load from API