-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix Bug Update for Issue #6
- Loading branch information
Showing
18 changed files
with
2,010 additions
and
1,357 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Drawing; // note: add reference to System.Drawing assembly | ||
using System.IO; | ||
using System.Linq; | ||
using System.Net.Http; | ||
using System.Net.Http.Headers; | ||
|
||
namespace Utilities | ||
{ | ||
// largely credited to https://stackoverflow.com/a/112711/3838199 for the image-specific code | ||
public static class ImageUtilities | ||
{ | ||
private const string ErrorMessage = "Could not read image data"; | ||
private const int ChunkSize = 1024; | ||
private static readonly Dictionary<byte[], Func<BinaryReader, Size>> ImageFormatDecoders = new Dictionary<byte[], Func<BinaryReader, Size>>() | ||
{ | ||
{ new byte[]{ 0x42, 0x4D }, DecodeBitmap}, | ||
{ new byte[]{ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif }, | ||
{ new byte[]{ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif }, | ||
{ new byte[]{ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng }, | ||
{ new byte[]{ 0xff, 0xd8 }, DecodeJfif }, | ||
}; | ||
|
||
/// <summary> | ||
/// Retrieve the dimensions of an online image, downloading as little as possible | ||
/// </summary> | ||
public static Size GetWebDimensions(Uri uri) | ||
{ | ||
var moreBytes = true; | ||
var currentStart = 0; | ||
byte[] allBytes = { }; | ||
|
||
while (moreBytes) | ||
{ | ||
try | ||
{ | ||
var newBytes = GetSomeBytes(uri, currentStart, currentStart + ChunkSize - 1); | ||
if (newBytes.Length < ChunkSize) moreBytes = false; | ||
allBytes = Combine(allBytes, newBytes); | ||
return GetDimensions(new BinaryReader(new MemoryStream(allBytes))); | ||
} | ||
catch | ||
{ | ||
currentStart += ChunkSize; | ||
} | ||
} | ||
|
||
return new Size(0, 0); | ||
} | ||
|
||
private static byte[] GetSomeBytes(Uri uri, int startRange, int endRange) | ||
{ | ||
using (var client = new HttpClient()) | ||
{ | ||
var request = new HttpRequestMessage { RequestUri = uri }; | ||
request.Headers.Range = new RangeHeaderValue(startRange, endRange); | ||
try | ||
{ | ||
var response = client.SendAsync(request).Result; | ||
return response.Content.ReadAsByteArrayAsync().Result; | ||
} | ||
catch { } | ||
} | ||
return new byte[] { }; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the dimensions of an image. | ||
/// </summary> | ||
/// <returns>The dimensions of the specified image.</returns> | ||
/// <exception cref="ArgumentException">The image was of an unrecognized format.</exception> | ||
public static Size GetDimensions(BinaryReader binaryReader) | ||
{ | ||
int maxMagicBytesLength = ImageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length; | ||
|
||
byte[] magicBytes = new byte[maxMagicBytesLength]; | ||
|
||
for (int i = 0; i < maxMagicBytesLength; i += 1) | ||
{ | ||
magicBytes[i] = binaryReader.ReadByte(); | ||
|
||
foreach (var kvPair in ImageFormatDecoders) | ||
{ | ||
if (magicBytes.StartsWith(kvPair.Key)) | ||
{ | ||
return kvPair.Value(binaryReader); | ||
} | ||
} | ||
} | ||
|
||
throw new ArgumentException(ErrorMessage, nameof(binaryReader)); | ||
} | ||
public static Size GetDimensions(string path) | ||
{ | ||
try | ||
{ | ||
using (BinaryReader binaryReader = new BinaryReader(File.OpenRead(path))) | ||
{ | ||
try | ||
{ | ||
return GetDimensions(binaryReader); | ||
} | ||
catch (ArgumentException e) | ||
{ | ||
string newMessage = string.Format("{0} file: '{1}' ", e.Message, path); | ||
|
||
throw new ArgumentException(newMessage, "path", e); | ||
} | ||
} | ||
} | ||
catch (ArgumentException) | ||
{ | ||
//do it the old fashioned way | ||
|
||
using (Bitmap b = new Bitmap(path)) | ||
{ | ||
return b.Size; | ||
} | ||
} | ||
} | ||
// from https://stackoverflow.com/a/415839/3838199 | ||
private static byte[] Combine(byte[] first, byte[] second) | ||
{ | ||
byte[] ret = new byte[first.Length + second.Length]; | ||
Buffer.BlockCopy(first, 0, ret, 0, first.Length); | ||
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length); | ||
return ret; | ||
} | ||
|
||
private static bool StartsWith(this byte[] thisBytes, byte[] thatBytes) | ||
{ | ||
for (int i = 0; i < thatBytes.Length; i += 1) | ||
{ | ||
if (thisBytes[i] != thatBytes[i]) | ||
{ | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
private static short ReadLittleEndianInt16(this BinaryReader binaryReader) | ||
{ | ||
byte[] bytes = new byte[sizeof(short)]; | ||
for (int i = 0; i < sizeof(short); i += 1) | ||
{ | ||
bytes[sizeof(short) - 1 - i] = binaryReader.ReadByte(); | ||
} | ||
return BitConverter.ToInt16(bytes, 0); | ||
} | ||
|
||
private static int ReadLittleEndianInt32(this BinaryReader binaryReader) | ||
{ | ||
byte[] bytes = new byte[sizeof(int)]; | ||
for (int i = 0; i < sizeof(int); i += 1) | ||
{ | ||
bytes[sizeof(int) - 1 - i] = binaryReader.ReadByte(); | ||
} | ||
return BitConverter.ToInt32(bytes, 0); | ||
} | ||
|
||
private static Size DecodeBitmap(BinaryReader binaryReader) | ||
{ | ||
binaryReader.ReadBytes(16); | ||
int width = binaryReader.ReadInt32(); | ||
int height = binaryReader.ReadInt32(); | ||
return new Size(width, height); | ||
} | ||
|
||
private static Size DecodeGif(BinaryReader binaryReader) | ||
{ | ||
int width = binaryReader.ReadInt16(); | ||
int height = binaryReader.ReadInt16(); | ||
return new Size(width, height); | ||
} | ||
|
||
private static Size DecodePng(BinaryReader binaryReader) | ||
{ | ||
binaryReader.ReadBytes(8); | ||
int width = binaryReader.ReadLittleEndianInt32(); | ||
int height = binaryReader.ReadLittleEndianInt32(); | ||
return new Size(width, height); | ||
} | ||
|
||
private static Size DecodeJfif(BinaryReader binaryReader) | ||
{ | ||
while (binaryReader.ReadByte() == 0xff) | ||
{ | ||
byte marker = binaryReader.ReadByte(); | ||
short chunkLength = binaryReader.ReadLittleEndianInt16(); | ||
|
||
if (marker == 0xc0 || marker == 0xc1 || marker == 0xc2) | ||
{ | ||
binaryReader.ReadByte(); | ||
|
||
int height = binaryReader.ReadLittleEndianInt16(); | ||
int width = binaryReader.ReadLittleEndianInt16(); | ||
return new Size(width, height); | ||
} | ||
|
||
binaryReader.ReadBytes(chunkLength - 2); | ||
} | ||
|
||
throw new ArgumentException(ErrorMessage); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
namespace DataGetter | ||
using System.Collections.Generic; | ||
|
||
namespace DataGetter | ||
{ | ||
class JsonClass | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Converters; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
|
||
namespace DataGetter | ||
{ | ||
public partial class poedbJson | ||
{ | ||
[JsonProperty("caption")] | ||
public string Caption { get; set; } | ||
|
||
[JsonProperty("data")] | ||
public List<List<string>> Data { get; set; } | ||
|
||
[JsonProperty("columns")] | ||
public List<Column> Columns { get; set; } | ||
} | ||
|
||
public partial class Column | ||
{ | ||
[JsonProperty("title")] | ||
public string Title { get; set; } | ||
} | ||
|
||
public partial class poedbJson | ||
{ | ||
public static poedbJson FromJson(string json) => JsonConvert.DeserializeObject<poedbJson>(json, DataGetter.Converter.Settings); | ||
} | ||
|
||
public static class Serialize | ||
{ | ||
public static string ToJson(this poedbJson self) => JsonConvert.SerializeObject(self, DataGetter.Converter.Settings); | ||
} | ||
|
||
internal class Converter | ||
{ | ||
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings | ||
{ | ||
MetadataPropertyHandling = MetadataPropertyHandling.Ignore, | ||
DateParseHandling = DateParseHandling.None, | ||
Converters = { | ||
new IsoDateTimeConverter() | ||
{ | ||
DateTimeStyles = DateTimeStyles.AssumeUniversal, | ||
}, | ||
}, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.