Skip to content

Commit

Permalink
Fixed some things
Browse files Browse the repository at this point in the history
  • Loading branch information
devedse committed Apr 9, 2017
1 parent cf7192a commit 263370f
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 5 deletions.
2 changes: 1 addition & 1 deletion DeveImageOptimizer/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
public static class Constants
{
public static string[] ValidExtensions { get; } = new string[] { ".PNG", ".JPG", ".JPEG", ".GIF" };
public static string[] ValidExtensions { get; } = new string[] { ".PNG", ".JPG", ".JPEG", ".GIF", ".BMP" };
public const string TempDirectoryName = "Temp";
}
}
6 changes: 5 additions & 1 deletion DeveImageOptimizer/DeveImageOptimizer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C9030AAD-A097-4494-89D5-B8E16FD1CB62}</ProjectGuid>
<OutputType>WinExe</OutputType>
<OutputType>Exe</OutputType>
<RootNamespace>DeveImageOptimizer</RootNamespace>
<AssemblyName>DeveImageOptimizer</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
Expand Down Expand Up @@ -35,6 +35,9 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="GalaSoft.MvvmLight, Version=5.3.0.19026, Culture=neutral, PublicKeyToken=e7570ab207bcb616, processorArchitecture=MSIL">
<HintPath>..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.dll</HintPath>
Expand Down Expand Up @@ -83,6 +86,7 @@
<Compile Include="Helpers\AsyncFileHelper.cs" />
<Compile Include="Helpers\FolderHelperMethods.cs" />
<Compile Include="Helpers\ImageComparer.cs" />
<Compile Include="Helpers\LockImage.cs" />
<Compile Include="Helpers\ProcessRunner.cs" />
<Compile Include="State\IChangable.cs" />
<Compile Include="State\ProcessingState\ProcessingStateData.cs" />
Expand Down
25 changes: 24 additions & 1 deletion DeveImageOptimizer/FileProcessing/FileOptimizerProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,32 @@ public async Task<bool> OptimizeFile(string fileToOptimize)
{
CreateNoWindow = true
};
processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;

await ProcessRunner.RunProcessAsync(processStartInfo);

return await ImageComparer.AreImagesEqualAsync(fileToOptimize, tempFilePath);
var imagesEqual = await ImageComparer.AreImagesEqualAsync2(fileToOptimize, tempFilePath);

if (imagesEqual)
{
await AsyncFileHelper.CopyFileAsync(tempFilePath, fileToOptimize, true);
File.Delete(tempFilePath);
}
else
{
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileToOptimize);
var fileExtension = Path.GetExtension(fileToOptimize);
var newFileName = $"{fileNameWithoutExtension}_FAILED{fileExtension}";

var directoryOfFileToOptimize = Path.GetDirectoryName(fileToOptimize);
var newFilePath = Path.Combine(directoryOfFileToOptimize, newFileName);

//Write a file as Blah_FAILED.png
await AsyncFileHelper.CopyFileAsync(tempFilePath, newFilePath, true);
File.Delete(tempFilePath);
}

return imagesEqual;
}
}
}
73 changes: 71 additions & 2 deletions DeveImageOptimizer/Helpers/ImageComparer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
using System.Drawing;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading.Tasks;

namespace DeveImageOptimizer.Helpers
Expand All @@ -7,21 +11,32 @@ public static class ImageComparer
{
public static async Task<bool> AreImagesEqualAsync(string image1Path, string image2Path)
{
//on bitmap asynchronously
return await Task.Run(() =>
{
return AreImagesEqual(image1Path, image2Path);
});
}

public static async Task<bool> AreImagesEqualAsync2(string image1Path, string image2Path)
{
return await Task.Run(() =>
{
return AreImagesEqual2(image1Path, image2Path);
});
}

public static bool AreImagesEqual(string image1Path, string image2Path)
{
var w = Stopwatch.StartNew();

using (var image1 = new Bitmap(image1Path))
{
using (var image2 = new Bitmap(image2Path))
{
if (image1.Size != image2.Size)
{
return false;
}

for (int y = 0; y < image1.Height; y++)
{
Expand All @@ -31,12 +46,66 @@ public static bool AreImagesEqual(string image1Path, string image2Path)
var pixel2 = image2.GetPixel(x, y);

if (pixel1 != pixel2)
{
if (pixel1.A == 0 && pixel2.A == 0)
{
//Optimization that happens to better be able to compress png's sometimes
return true;
}
return false;
}
}
}
}
}

Console.WriteLine($"Elapsed for Equal1: " + w.Elapsed.TotalSeconds);

return true;
}

public static bool AreImagesEqual2(string image1Path, string image2Path)
{
var w = Stopwatch.StartNew();

using (var image1 = new Bitmap(image1Path))
{
using (var image2 = new Bitmap(image2Path))
{
if (image1.Size != image2.Size)
{
return false;
}

var lockImage1 = new LockBitmap(image1);
var lockImage2 = new LockBitmap(image2);

lockImage1.LockBits();
lockImage2.LockBits();

for (int y = 0; y < lockImage1.Height; y++)
{
for (int x = 0; x < lockImage2.Width; x++)
{
var pixel1 = lockImage1.GetPixel(x, y);
var pixel2 = lockImage2.GetPixel(x, y);

if (pixel1 != pixel2)
{
if (pixel1.A == 0 && pixel2.A == 0)
{
//Optimization that happens to better be able to compress png's sometimes
return true;
}
return false;
}
}
}
}
}

Console.WriteLine($"Elapsed for Equal2: " + w.Elapsed.TotalSeconds);

return true;
}
}
Expand Down
149 changes: 149 additions & 0 deletions DeveImageOptimizer/Helpers/LockImage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace DeveImageOptimizer.Helpers
{
public class LockBitmap
{
private Bitmap source = null;
private IntPtr Iptr = IntPtr.Zero;
private BitmapData bitmapData = null;

public byte[] Pixels { get; set; }
public int Depth { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; }

public LockBitmap(Bitmap source)
{
this.source = source;

// Get width and height of bitmap
Width = source.Width;
Height = source.Height;
}

public void LockBits()
{
// get total locked pixels count
int pixelCount = Width * Height;

// Create rectangle to lock
Rectangle rect = new Rectangle(0, 0, Width, Height);

// get source bitmap pixel format size
Depth = Image.GetPixelFormatSize(source.PixelFormat);

// Check if bpp (Bits Per Pixel) is 8, 24, or 32

if (Depth == 4)
{
//God knows what to do here, so we just fallback to good old getpixel method
return;
}
if (Depth != 8 && Depth != 24 && Depth != 32 && Depth != 1)
{
throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
}

// Lock bitmap and return bitmap data
bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat);

// create byte array to copy pixel values
int step = (int)(Depth / 8.0f + 1.0f);
Pixels = new byte[pixelCount * step];
Iptr = bitmapData.Scan0;

// Copy data from pointer to array
Marshal.Copy(Iptr, Pixels, 0, Pixels.Length);
}

public void UnlockBits()
{
// Copy data from byte array to pointer
Marshal.Copy(Pixels, 0, Iptr, Pixels.Length);

// Unlock bitmap data
source.UnlockBits(bitmapData);
}

public Color GetPixel(int x, int y)
{
if (Depth == 4)
{
//Don't really know how to do this
return source.GetPixel(x, y);
}

// Get color components count
int cCount = Depth / 8;

// Get start index of the specified pixel
int i = ((y * Width) + x) * cCount;

if (i > Pixels.Length - cCount)
throw new IndexOutOfRangeException();

if (Depth == 32) // For 32 bpp get Red, Green, Blue and Alpha
{
byte b = Pixels[i];
byte g = Pixels[i + 1];
byte r = Pixels[i + 2];
byte a = Pixels[i + 3]; // a
return Color.FromArgb(a, r, g, b);
}
else if (Depth == 24) // For 24 bpp get Red, Green and Blue
{
byte b = Pixels[i];
byte g = Pixels[i + 1];
byte r = Pixels[i + 2];
return Color.FromArgb(r, g, b);
}
else if (Depth == 8)
// For 8 bpp get color value (Red, Green and Blue values are the same)
{
if (source.PixelFormat == PixelFormat.Format8bppIndexed)
{
byte c = Pixels[i];
return source.Palette.Entries[c];
}
else
{
byte c = Pixels[i];
return Color.FromArgb(c, c, c);
}
}
else if (Depth == 1)
{
byte c = Pixels[i];
if (source.PixelFormat == PixelFormat.Format1bppIndexed)
{
var bitNumber = i % 8;
var bit = (c & (1 << bitNumber - 1)) != 0;
if (bit)
{
return Color.Black;
}
else
{
return Color.White;
}
}
else
{
throw new FormatException("Don't know but it's broken");
}
}
else
{
throw new FormatException($"An image with depth {Depth} is not supported");
}
}
}
}
Binary file not shown.

0 comments on commit 263370f

Please sign in to comment.