Compare commits
13 Commits
Author | SHA1 | Date |
---|---|---|
Valeriy Mironov | 9c028a9c07 | |
Valeriy Mironov | 4ad3537a26 | |
Valeriy Mironov | baa352661d | |
Valeriy Mironov | 948fd521cc | |
Valeriy Mironov | 1c3663b65d | |
Valeriy Mironov | 10273531cf | |
Valeriy Mironov | 7d0938b569 | |
Valeriy Mironov | 37ca2a8142 | |
Valeriy Mironov | f2cc221072 | |
Valeriy Mironov | b09c78a2a2 | |
Valeriy Mironov | dd2421c7b4 | |
Valeriy Mironov | cfff020bc0 | |
Valeriy Mironov | 985fd1688e |
|
@ -4,6 +4,7 @@
|
|||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:String x:Key="/Default/Environment/Hierarchy/PsiConfigurationSettingsKey/CustomLocation/@EntryValue">C:\Users\valeronm\AppData\Local\JetBrains\Transient\ReSharperPlatformVs15\v11_048a238b\SolutionCaches</s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
|
||||
|
|
23
Changelog.md
|
@ -3,7 +3,22 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [Unreleased]
|
||||
## [1.0.2.12] - 2018-05-01
|
||||
### Added
|
||||
- Added support for air quality index value;
|
||||
- Aanimated preview now shows discharging battery instead of charging.
|
||||
|
||||
## [1.0.2.11] - 2018-05-01
|
||||
### Changed
|
||||
- Improved speed of all operations by tuning logging options
|
||||
|
||||
## [1.0.2.10] - 2018-05-01
|
||||
### Added
|
||||
- Skipped storing empty paramter lists. It was possible to brick watches with this :( (Thanks to Luca Venturini for the report)
|
||||
|
||||
## [1.0.2.9] - 2018-03-25
|
||||
### Added
|
||||
- Added sorting of image palette for correct repacking font images added in 0.1.1.15 firmware (RES 32) (#23)
|
||||
|
||||
## [1.0.2.8] - 2018-02-02
|
||||
### Added
|
||||
|
@ -86,7 +101,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
|
|||
- Implemented watchfaces unpacking and packing.
|
||||
- Implemented .res file unpacking.
|
||||
|
||||
[Unreleased]: https://bitbucket.org/valeronm/amazfitbiptools/branches/compare/HEAD..1.0.2.8
|
||||
[Unreleased]: https://bitbucket.org/valeronm/amazfitbiptools/branches/compare/HEAD..1.0.2.12
|
||||
[1.0.2.12]: https://bitbucket.org/valeronm/amazfitbiptools/branches/compare/1.0.2.12..1.0.2.11
|
||||
[1.0.2.11]: https://bitbucket.org/valeronm/amazfitbiptools/branches/compare/1.0.2.11..1.0.2.10
|
||||
[1.0.2.10]: https://bitbucket.org/valeronm/amazfitbiptools/branches/compare/1.0.2.10..1.0.2.9
|
||||
[1.0.2.9]: https://bitbucket.org/valeronm/amazfitbiptools/branches/compare/1.0.2.9..1.0.2.8
|
||||
[1.0.2.8]: https://bitbucket.org/valeronm/amazfitbiptools/branches/compare/1.0.2.8..1.0.2.7
|
||||
[1.0.2.7]: https://bitbucket.org/valeronm/amazfitbiptools/branches/compare/1.0.2.7..1.0.2.6
|
||||
[1.0.2.6]: https://bitbucket.org/valeronm/amazfitbiptools/branches/compare/1.0.2.6..1.0.2.5
|
||||
|
|
|
@ -18,12 +18,16 @@ namespace Resources
|
|||
|
||||
public void Extract(string outputDirectory)
|
||||
{
|
||||
for (var i = 0; i < _descriptor.Images.Count; i++)
|
||||
for (var i = 0; i < _descriptor.Resources.Count; i++)
|
||||
{
|
||||
var resource = _descriptor.Resources[i];
|
||||
var numericPart = i.ToString().PadLeft(ImageLoader.NumericPartLength, '0');
|
||||
var fileName = Path.Combine(outputDirectory, numericPart + ".png");
|
||||
|
||||
var fileName = Path.Combine(outputDirectory, numericPart + resource.Extension);
|
||||
Logger.Debug("Extracting {0}...", fileName);
|
||||
_descriptor.Images[i].Save(fileName, ImageFormat.Png);
|
||||
|
||||
using (var fileStream = File.OpenWrite(fileName))
|
||||
resource.ExportTo(fileStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace Resources
|
|||
ResourcesCount = header.ResourcesCount,
|
||||
Version = header.Version,
|
||||
Unknown = (header as NewHeader)?.Unknown,
|
||||
Images = new Reader(stream).Read(header.ResourcesCount)
|
||||
Resources = new Reader(stream).Read(header.ResourcesCount)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,14 +29,14 @@ namespace Resources
|
|||
WriteOldHeader(descriptor);
|
||||
|
||||
Logger.Trace("Writing images...");
|
||||
new Writer(_stream).Write(descriptor.Images);
|
||||
new Writer(_stream).Write(descriptor.Resources);
|
||||
}
|
||||
|
||||
private void WriteOldHeader(FileDescriptor descriptor)
|
||||
{
|
||||
var header = new Header
|
||||
{
|
||||
ResourcesCount = (uint)descriptor.Images.Count,
|
||||
ResourcesCount = (uint)descriptor.Resources.Count,
|
||||
Version = descriptor.Version.Value
|
||||
};
|
||||
Logger.Trace("Writing resources header...");
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using BumpKit;
|
||||
using NLog;
|
||||
|
@ -29,10 +28,20 @@ namespace Resources.Image
|
|||
{
|
||||
var signature = _reader.ReadChars(4);
|
||||
if (signature[0] != 'B' || signature[1] != 'M')
|
||||
throw new ArgumentException("Image signature doesn't match.");
|
||||
throw new InvalidResourceException("Image signature doesn't match.");
|
||||
|
||||
ReadHeader();
|
||||
ReadPalette();
|
||||
if (_paletteColors > 256)
|
||||
throw new InvalidResourceException(
|
||||
"Too many palette colors.");
|
||||
|
||||
if (_paletteColors > 0)
|
||||
ReadPalette();
|
||||
else if (_bitsPerPixel == 8 || _bitsPerPixel == 16 || _bitsPerPixel == 24 || _bitsPerPixel == 32)
|
||||
Logger.Trace("The image doesn't use a palette.");
|
||||
else
|
||||
throw new InvalidResourceException(
|
||||
"The image format is not supported. Please report the issue on https://bitbucket.org/valeronm/amazfitbiptools");
|
||||
return ReadImage();
|
||||
}
|
||||
|
||||
|
@ -66,7 +75,6 @@ namespace Resources.Image
|
|||
if (padding != 0) Logger.Warn("Palette item {0} last byte is not zero: {1:X2}", i, padding);
|
||||
|
||||
var isColorValid = (r == 0 || r == 0xff) && (g == 0 || g == 0xff) && (b == 0 || b == 0xff);
|
||||
|
||||
if (isColorValid)
|
||||
Logger.Trace("Palette item {0}: R {1:X2}, G {2:X2}, B {3:X2}", i, r, g, b);
|
||||
else
|
||||
|
@ -78,6 +86,16 @@ namespace Resources.Image
|
|||
}
|
||||
|
||||
private Bitmap ReadImage()
|
||||
{
|
||||
if (_paletteColors > 0) return ReadPaletteImage();
|
||||
if (_bitsPerPixel == 8) return Read8BitImage();
|
||||
if (_bitsPerPixel == 16) return Read16BitImage();
|
||||
if (_bitsPerPixel == 24) return Read24BitImage();
|
||||
if (_bitsPerPixel == 32) return Read32BitImage();
|
||||
throw new InvalidResourceException($"Unsupported bits per pixel value: {_bitsPerPixel}");
|
||||
}
|
||||
|
||||
private Bitmap ReadPaletteImage()
|
||||
{
|
||||
var image = new Bitmap(_width, _height);
|
||||
using (var context = image.CreateUnsafeContext())
|
||||
|
@ -89,11 +107,104 @@ namespace Resources.Image
|
|||
for (var x = 0; x < _width; x++)
|
||||
{
|
||||
var pixelColorIndex = bitReader.ReadBits(_bitsPerPixel);
|
||||
var color = _palette[(int) pixelColorIndex];
|
||||
var color = _palette[(int)pixelColorIndex];
|
||||
context.SetPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private Bitmap Read8BitImage()
|
||||
{
|
||||
var image = new Bitmap(_width, _height);
|
||||
using (var context = image.CreateUnsafeContext())
|
||||
{
|
||||
for (var y = 0; y < _height; y++)
|
||||
{
|
||||
var rowBytes = _reader.ReadBytes(_rowLengthInBytes);
|
||||
for (var x = 0; x < _width; x++)
|
||||
{
|
||||
var data = rowBytes[x];
|
||||
var color = Color.FromArgb(0xff, data, data, data);
|
||||
context.SetPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private Bitmap Read16BitImage()
|
||||
{
|
||||
var image = new Bitmap(_width, _height);
|
||||
using (var context = image.CreateUnsafeContext())
|
||||
{
|
||||
for (var y = 0; y < _height; y++)
|
||||
{
|
||||
var rowBytes = _reader.ReadBytes(_rowLengthInBytes);
|
||||
var bitReader = new BitReader(rowBytes);
|
||||
for (var x = 0; x < _width; x++)
|
||||
{
|
||||
var firstByte = (int)bitReader.ReadByte();
|
||||
var secondByte = (int)bitReader.ReadByte();
|
||||
var b = (byte)((secondByte >> 3) & 0x1f) << 3;
|
||||
var g = (byte)(((firstByte >> 5) & 0x7) | ((secondByte & 0x07) << 3)) << 2;
|
||||
var r = (byte)(firstByte & 0x1f) << 3;
|
||||
var color = Color.FromArgb(0xff, r, g, b);
|
||||
context.SetPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private Bitmap Read24BitImage()
|
||||
{
|
||||
var image = new Bitmap(_width, _height);
|
||||
using (var context = image.CreateUnsafeContext())
|
||||
{
|
||||
for (var y = 0; y < _height; y++)
|
||||
{
|
||||
var rowBytes = _reader.ReadBytes(_rowLengthInBytes);
|
||||
var bitReader = new BitReader(rowBytes);
|
||||
for (var x = 0; x < _width; x++)
|
||||
{
|
||||
var alpha = (int)bitReader.ReadByte();
|
||||
var b = (int)(bitReader.ReadBits(5) << 3);
|
||||
var g = (int)(bitReader.ReadBits(6) << 2);
|
||||
var r = (int)(bitReader.ReadBits(5) << 3);
|
||||
var color = Color.FromArgb(0xff - alpha, r, g, b);
|
||||
context.SetPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private Bitmap Read32BitImage()
|
||||
{
|
||||
var image = new Bitmap(_width, _height);
|
||||
using (var context = image.CreateUnsafeContext())
|
||||
{
|
||||
for (var y = 0; y < _height; y++)
|
||||
{
|
||||
var rowBytes = _reader.ReadBytes(_rowLengthInBytes);
|
||||
for (var x = 0; x < _width; x++)
|
||||
{
|
||||
var r = rowBytes[x * 4];
|
||||
var g = rowBytes[x * 4 + 1];
|
||||
var b = rowBytes[x * 4 + 2];
|
||||
var alpha = rowBytes[x * 4 + 3];
|
||||
var color = Color.FromArgb(0xff - alpha, r, g, b);
|
||||
context.SetPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,42 +1,71 @@
|
|||
using System.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using Resources.Image;
|
||||
using Resources.Models;
|
||||
|
||||
namespace Resources
|
||||
{
|
||||
public class ImageLoader
|
||||
{
|
||||
public static readonly int NumericPartLength = 3;
|
||||
public static readonly int NumericPartLength = 4;
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public static Bitmap LoadImageForNumber(string directory, long index)
|
||||
public static IResource LoadResourceForNumber(string directory, long index)
|
||||
{
|
||||
var strIndex = index.ToString();
|
||||
var numericParts = new[]
|
||||
{
|
||||
index.ToString().PadLeft(NumericPartLength, '0'),
|
||||
index.ToString()
|
||||
};
|
||||
strIndex.PadLeft(4, '0'), strIndex.PadLeft(3, '0'), strIndex.PadLeft(2, '0'), strIndex
|
||||
}.Distinct();
|
||||
|
||||
foreach (var numericPart in numericParts.Distinct())
|
||||
foreach (var numericPart in numericParts)
|
||||
{
|
||||
var fullFileName = Path.Combine(directory, numericPart + ".png");
|
||||
if (!File.Exists(fullFileName))
|
||||
{
|
||||
Logger.Trace("File {0} doesn't exists.", fullFileName);
|
||||
continue;
|
||||
}
|
||||
var resource = TryLoadBitmap(directory, numericPart);
|
||||
if (resource != null) return resource;
|
||||
|
||||
var image = (Bitmap) System.Drawing.Image.FromFile(fullFileName);
|
||||
Logger.Trace("Image was loaded from file {0}", fullFileName);
|
||||
return ApplyDithering(image);
|
||||
resource = TryLoadBlob(directory, numericPart);
|
||||
if (resource != null) return resource;
|
||||
}
|
||||
|
||||
throw new FileNotFoundException($"File referenced by index {index} not found.");
|
||||
}
|
||||
|
||||
private static IResource TryLoadBitmap(string directory, string numericPart)
|
||||
{
|
||||
var fullFileName = Path.Combine(directory, numericPart + Models.Image.ResourceExtension);
|
||||
if (!File.Exists(fullFileName))
|
||||
{
|
||||
Logger.Trace("File {0} doesn't exists.", fullFileName);
|
||||
return null;
|
||||
}
|
||||
|
||||
var image = (Bitmap) System.Drawing.Image.FromFile(fullFileName);
|
||||
Logger.Trace("Image was loaded from file {0}", fullFileName);
|
||||
var ditheredBitmap = ApplyDithering(image);
|
||||
return new Models.Image(ditheredBitmap);
|
||||
}
|
||||
|
||||
private static IResource TryLoadBlob(string directory, string numericPart)
|
||||
{
|
||||
var fullFileName = Path.Combine(directory, numericPart + Blob.ResourceExtension);
|
||||
if (!File.Exists(fullFileName))
|
||||
{
|
||||
Logger.Trace("File {0} doesn't exists.", fullFileName);
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var fileStream = File.OpenRead(fullFileName))
|
||||
{
|
||||
var data = new byte[fileStream.Length];
|
||||
fileStream.Read(data, 0, data.Length);
|
||||
return new Blob(data);
|
||||
}
|
||||
}
|
||||
|
||||
private static Bitmap ApplyDithering(Bitmap image)
|
||||
{
|
||||
var clone = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb);
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace Resources
|
||||
{
|
||||
public class InvalidResourceException : Exception
|
||||
{
|
||||
public InvalidResourceException(string message) : base(message) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using System.IO;
|
||||
|
||||
namespace Resources.Models
|
||||
{
|
||||
public class Blob : IResource
|
||||
{
|
||||
public static string ResourceExtension = ".dat";
|
||||
private readonly byte[] _data;
|
||||
|
||||
public Blob(byte[] data)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
|
||||
public string Extension => ResourceExtension;
|
||||
|
||||
public void WriteTo(Stream stream)
|
||||
{
|
||||
stream.Write(_data, 0, _data.Length);
|
||||
}
|
||||
|
||||
public void ExportTo(Stream stream)
|
||||
{
|
||||
stream.Write(_data, 0, _data.Length);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Resources.Models
|
||||
|
@ -12,6 +13,6 @@ namespace Resources.Models
|
|||
public byte? Version { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public List<Bitmap> Images { get; set; } = new List<Bitmap>();
|
||||
public List<IResource> Resources { get; set; } = new List<IResource>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using System.IO;
|
||||
|
||||
namespace Resources.Models
|
||||
{
|
||||
public interface IResource
|
||||
{
|
||||
string Extension { get; }
|
||||
void WriteTo(Stream stream);
|
||||
void ExportTo(Stream stream);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
|
||||
namespace Resources.Models
|
||||
{
|
||||
public class Image: IResource
|
||||
{
|
||||
public Bitmap Bitmap { get; }
|
||||
|
||||
public Image(Bitmap bitmap)
|
||||
{
|
||||
Bitmap = bitmap;
|
||||
}
|
||||
|
||||
public static string ResourceExtension = ".png";
|
||||
public string Extension => ResourceExtension;
|
||||
|
||||
public void WriteTo(Stream stream)
|
||||
{
|
||||
new Resources.Image.Writer(stream).Write(Bitmap);
|
||||
}
|
||||
|
||||
public void ExportTo(Stream stream)
|
||||
{
|
||||
Bitmap.Save(stream, ImageFormat.Png);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using Resources.Models;
|
||||
|
||||
namespace Resources
|
||||
{
|
||||
|
@ -20,32 +19,54 @@ namespace Resources
|
|||
_binaryReader = new BinaryReader(_stream);
|
||||
}
|
||||
|
||||
public List<Bitmap> Read(uint imagesTableLength)
|
||||
public List<IResource> Read(uint resourcesCount)
|
||||
{
|
||||
var offsetsTableLength = (int) (imagesTableLength * OffsetTableItemLength);
|
||||
var offsetsTableLength = (int) (resourcesCount * OffsetTableItemLength);
|
||||
Logger.Trace("Reading resources offsets table with {0} elements ({1} bytes)",
|
||||
imagesTableLength, offsetsTableLength
|
||||
resourcesCount, offsetsTableLength
|
||||
);
|
||||
var imagesOffsets = _binaryReader.ReadBytes(offsetsTableLength);
|
||||
var imagesOffset = _stream.Position;
|
||||
|
||||
Logger.Debug("Reading {0} images...", imagesTableLength);
|
||||
var images = new List<Bitmap>((int) imagesTableLength);
|
||||
for (var i = 0; i < imagesTableLength; i++)
|
||||
var offsets = new int[resourcesCount];
|
||||
for (var i = 0; i < resourcesCount; i++)
|
||||
offsets[i] = _binaryReader.ReadInt32();
|
||||
|
||||
var resourcesOffset = (int) _stream.Position;
|
||||
var fileSize = (int) _stream.Length;
|
||||
|
||||
Logger.Debug("Reading {0} resources...", resourcesCount);
|
||||
var resources = new List<IResource>((int) resourcesCount);
|
||||
for (var i = 0; i < resourcesCount; i++)
|
||||
{
|
||||
var imageOffset = BitConverter.ToUInt32(imagesOffsets, i * OffsetTableItemLength);
|
||||
var realOffset = imageOffset + imagesOffset;
|
||||
Logger.Trace("Image {0} offset is {1}...", i, imageOffset);
|
||||
if (_stream.Position != realOffset)
|
||||
var offset = offsets[i] + resourcesOffset;
|
||||
var nextOffset = i + 1 < resourcesCount ? offsets[i + 1] + resourcesOffset : fileSize;
|
||||
var length = nextOffset - offset;
|
||||
Logger.Trace("Resource {0} offset: {1}, length: {2}...", i, offset, length);
|
||||
if (_stream.Position != offset)
|
||||
{
|
||||
var bytesGap = realOffset - _stream.Position;
|
||||
var bytesGap = offset - _stream.Position;
|
||||
Logger.Warn("Found {0} bytes gap before resource number {1}", bytesGap, i);
|
||||
_stream.Seek(realOffset, SeekOrigin.Begin);
|
||||
_stream.Seek(offset, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
Logger.Debug("Reading resource {0}...", i);
|
||||
try
|
||||
{
|
||||
var bitmap = new Image.Reader(_stream).Read();
|
||||
var image = new Models.Image(bitmap);
|
||||
resources.Add(image);
|
||||
}
|
||||
catch (InvalidResourceException)
|
||||
{
|
||||
Logger.Warn("Resource is not an image");
|
||||
_stream.Seek(offset, SeekOrigin.Begin);
|
||||
var data = new byte[length];
|
||||
_stream.Read(data, 0, length);
|
||||
var blob = new Blob(data);
|
||||
resources.Add(blob);
|
||||
}
|
||||
Logger.Debug("Reading image {0}...", i);
|
||||
images.Add(new Image.Reader(_stream).Read());
|
||||
}
|
||||
return images;
|
||||
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Resources
|
||||
{
|
||||
interface IResource
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -35,12 +35,15 @@
|
|||
<HintPath>..\packages\Bumpkit.1.0.2\lib\BumpKit.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.12\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.4.5.6\lib\net40-client\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
|
@ -50,6 +53,10 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="Extractor.cs" />
|
||||
<Compile Include="ImageLoader.cs" />
|
||||
<Compile Include="InvalidResourceException.cs" />
|
||||
<Compile Include="Models\Blob.cs" />
|
||||
<Compile Include="Models\Image.cs" />
|
||||
<Compile Include="Models\IResource.cs" />
|
||||
<Compile Include="Models\FileDescriptor.cs" />
|
||||
<Compile Include="Models\Header.cs" />
|
||||
<Compile Include="Utils\BitReader.cs" />
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Drawing;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using Resources.Models;
|
||||
|
||||
namespace Resources
|
||||
{
|
||||
|
@ -18,30 +19,30 @@ namespace Resources
|
|||
_stream = stream;
|
||||
}
|
||||
|
||||
public void Write(List<Bitmap> images)
|
||||
public void Write(List<IResource> resources)
|
||||
{
|
||||
var offsetsTable = new byte[images.Count * OffsetTableItemLength];
|
||||
var encodedImages = new MemoryStream[images.Count];
|
||||
var offsetsTable = new byte[resources.Count * OffsetTableItemLength];
|
||||
var encodedResources = new MemoryStream[resources.Count];
|
||||
|
||||
var offset = (uint) 0;
|
||||
for (var i = 0; i < images.Count; i++)
|
||||
for (var i = 0; i < resources.Count; i++)
|
||||
{
|
||||
Logger.Trace("Image {0} offset is {1}...", i, offset);
|
||||
Logger.Trace("Resource {0} offset is {1}...", i, offset);
|
||||
var offsetBytes = BitConverter.GetBytes(offset);
|
||||
offsetBytes.CopyTo(offsetsTable, i * OffsetTableItemLength);
|
||||
|
||||
var encodedImage = new MemoryStream();
|
||||
Logger.Debug("Encoding image {0}...", i);
|
||||
new Image.Writer(encodedImage).Write(images[i]);
|
||||
Logger.Debug("Encoding resource {0}...", i);
|
||||
resources[i].WriteTo(encodedImage);
|
||||
offset += (uint) encodedImage.Length;
|
||||
encodedImages[i] = encodedImage;
|
||||
encodedResources[i] = encodedImage;
|
||||
}
|
||||
|
||||
Logger.Trace("Writing images offsets table");
|
||||
Logger.Trace("Writing resources offsets table");
|
||||
_stream.Write(offsetsTable, 0, offsetsTable.Length);
|
||||
|
||||
Logger.Debug("Writing images");
|
||||
foreach (var encodedImage in encodedImages)
|
||||
Logger.Debug("Writing resources");
|
||||
foreach (var encodedImage in encodedResources)
|
||||
{
|
||||
encodedImage.Seek(0, SeekOrigin.Begin);
|
||||
encodedImage.CopyTo(_stream);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Bumpkit" version="1.0.2" targetFramework="net40-client" />
|
||||
<package id="NLog" version="4.4.12" targetFramework="net40-client" />
|
||||
<package id="NLog" version="4.5.6" targetFramework="net40-client" />
|
||||
</packages>
|
|
@ -15,5 +15,8 @@ namespace WatchFace.Parser.Elements.ActivityElements
|
|||
[ParameterId(3)]
|
||||
[ParameterImageIndex]
|
||||
public long? DecimalPointImageIndex { get; set; }
|
||||
|
||||
[ParameterId(4)]
|
||||
public long? SuffixMilesImageIndex { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using WatchFace.Parser.Attributes;
|
||||
using WatchFace.Parser.Models;
|
||||
|
||||
namespace WatchFace.Parser.Elements.BasicElements
|
||||
{
|
||||
public class UnknownType
|
||||
{
|
||||
[ParameterId(1)]
|
||||
public long TopLeftX { get; set; }
|
||||
|
||||
[ParameterId(2)]
|
||||
public long TopLeftY { get; set; }
|
||||
|
||||
[ParameterId(3)]
|
||||
public long BottomRightX { get; set; }
|
||||
|
||||
[ParameterId(4)]
|
||||
public long BottomRightY { get; set; }
|
||||
|
||||
[ParameterId(5)]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public TextAlignment Alignment { get; set; }
|
||||
|
||||
[ParameterId(6)]
|
||||
public long Spacing { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using WatchFace.Parser.Attributes;
|
||||
using WatchFace.Parser.Models;
|
||||
|
||||
namespace WatchFace.Parser.Elements.BasicElements
|
||||
{
|
||||
public class UnknownType14d6
|
||||
{
|
||||
[ParameterId(1)]
|
||||
public Coordinates Unknown1 { get; set; }
|
||||
|
||||
[ParameterId(2)]
|
||||
public Coordinates Unknown2 { get; set; }
|
||||
|
||||
[ParameterId(3)]
|
||||
public long? Unknown3 { get; set; }
|
||||
}
|
||||
}
|
|
@ -13,5 +13,11 @@ namespace WatchFace.Parser.Elements
|
|||
|
||||
[ParameterId(3)]
|
||||
public Scale Scale { get; set; }
|
||||
|
||||
[ParameterId(5)]
|
||||
public long? Unknown5 { get; set; }
|
||||
|
||||
[ParameterId(6)]
|
||||
public long? Unknown6 { get; set; }
|
||||
}
|
||||
}
|
|
@ -11,5 +11,11 @@ namespace WatchFace.Parser.Elements
|
|||
|
||||
[ParameterId(2)]
|
||||
public ImageSet WeekDay { get; set; }
|
||||
|
||||
[ParameterId(3)]
|
||||
public DateUnknown3 Unknown3 { get; set; }
|
||||
|
||||
[ParameterId(4)]
|
||||
public Coordinates Unknown4 { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using WatchFace.Parser.Attributes;
|
||||
using WatchFace.Parser.Elements.BasicElements;
|
||||
|
||||
namespace WatchFace.Parser.Elements.DateElements
|
||||
{
|
||||
public class DateUnknown3
|
||||
{
|
||||
[ParameterId(2)]
|
||||
public UnknownType Unknown2 { get; set; }
|
||||
}
|
||||
}
|
|
@ -22,5 +22,8 @@ namespace WatchFace.Parser.Elements
|
|||
[JsonConverter(typeof(DrawingOrderJsonConverter))]
|
||||
[ParameterId(5)]
|
||||
public long? DrawingOrder { get; set; }
|
||||
|
||||
[ParameterId(9)]
|
||||
public long? Unknown9 { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using Newtonsoft.Json;
|
||||
using WatchFace.Parser.Attributes;
|
||||
using WatchFace.Parser.Elements.BasicElements;
|
||||
using WatchFace.Parser.Elements.TimeElements;
|
||||
using WatchFace.Parser.JsonConverters;
|
||||
|
||||
namespace WatchFace.Parser.Elements
|
||||
{
|
||||
public class UnknownType14
|
||||
{
|
||||
[ParameterId(1)]
|
||||
public TwoDigits Unknown1 { get; set; }
|
||||
|
||||
[ParameterId(2)]
|
||||
public TwoDigits Unknown2 { get; set; }
|
||||
|
||||
[ParameterId(6)]
|
||||
public UnknownType14d6 Unknown6 { get; set; }
|
||||
|
||||
[ParameterId(7)]
|
||||
public UnknownType14d6 Unknown7 { get; set; }
|
||||
|
||||
[ParameterId(8)]
|
||||
public UnknownType14d6 Unknown8 { get; set; }
|
||||
}
|
||||
}
|
|
@ -5,7 +5,8 @@ namespace WatchFace.Parser.Elements.WeatherElements
|
|||
{
|
||||
public class AirPollution
|
||||
{
|
||||
// TODO: Looks like here should be Id 1 also
|
||||
[ParameterId(1)]
|
||||
public Number Index { get; set; }
|
||||
|
||||
[ParameterId(2)]
|
||||
public ImageSet Icon { get; set; }
|
||||
|
|
|
@ -9,9 +9,9 @@ namespace WatchFace.Parser.Models.Elements
|
|||
|
||||
public override void Draw(Graphics drawer, Bitmap[] resources, WatchState state)
|
||||
{
|
||||
if (state.Air == AirCondition.Unknown) return;
|
||||
if (state.AirQuality == AirCondition.Unknown) return;
|
||||
|
||||
var imageIndex = (int) state.Air;
|
||||
var imageIndex = (int) state.AirQuality;
|
||||
Draw(drawer, resources, imageIndex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
using System.Drawing;
|
||||
using WatchFace.Parser.Interfaces;
|
||||
|
||||
namespace WatchFace.Parser.Models.Elements
|
||||
{
|
||||
public class AirQualityIndexNumberElement : NumberElement, IDrawable
|
||||
{
|
||||
public AirQualityIndexNumberElement(Parameter parameter, Element parent = null, string name = null) :
|
||||
base(parameter, parent, name) { }
|
||||
|
||||
public void Draw(Graphics drawer, Bitmap[] resources, WatchState state)
|
||||
{
|
||||
if (state.AirQualityIndex != null)
|
||||
Draw(drawer, resources, state.AirQualityIndex.Value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,12 +5,16 @@
|
|||
public AirPollutionElement(Parameter parameter, Element parent = null, string name = null) :
|
||||
base(parameter, parent, name) { }
|
||||
|
||||
public AirQualityIndexNumberElement Index { get; set; }
|
||||
public AirPollutionImageElement Current { get; set; }
|
||||
|
||||
protected override Element CreateChildForParameter(Parameter parameter)
|
||||
{
|
||||
switch (parameter.Id)
|
||||
{
|
||||
case 1:
|
||||
Index = new AirQualityIndexNumberElement(parameter, this);
|
||||
return Index;
|
||||
case 2:
|
||||
Current = new AirPollutionImageElement(parameter, this);
|
||||
return Current;
|
||||
|
|
|
@ -19,11 +19,14 @@ namespace WatchFace.Parser.Models.Elements
|
|||
var useAltCoordinates = CurrentAlt != null && state.CurrentTemperature == null;
|
||||
var iconCoordinates = useAltCoordinates ? CurrentAlt : Current;
|
||||
|
||||
if (state.CurrentWeather > WeatherCondition.VeryHeavyDownpour ||
|
||||
state.CurrentWeather < WeatherCondition.Unknown) return;
|
||||
|
||||
if (iconCoordinates != null)
|
||||
drawer.DrawImage(LoadWeatherImage(state.CurrentWeather), iconCoordinates.X, iconCoordinates.Y);
|
||||
|
||||
if (CustomIcon != null)
|
||||
drawer.DrawImage(resources[CustomIcon.ImageIndex + 1], CustomIcon.X, CustomIcon.Y);
|
||||
drawer.DrawImage(resources[CustomIcon.ImageIndex + (int)state.CurrentWeather], CustomIcon.X, CustomIcon.Y);
|
||||
}
|
||||
|
||||
private static Bitmap LoadWeatherImage(WeatherCondition weather)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace WatchFace.Parser.Models
|
||||
{
|
||||
|
@ -12,13 +14,19 @@ namespace WatchFace.Parser.Models
|
|||
public int Distance { get; set; } = 2367;
|
||||
public int? Pulse { get; set; } = 62;
|
||||
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public WeatherCondition CurrentWeather { get; set; } = WeatherCondition.PartlyCloudy;
|
||||
public int? CurrentTemperature { get; set; } = -10;
|
||||
public int? DayTemperature { get; set; } = -15;
|
||||
public int? NightTemperature { get; set; } = -24;
|
||||
public int? TomorrowDayTemperature { get; set; }
|
||||
public int? TomorrowNightTemperature { get; set; }
|
||||
public WeatherCondition CurrentWeather { get; set; } = WeatherCondition.Cloudy;
|
||||
public AirCondition Air { get; set; } = AirCondition.Excellent;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Air_quality_index#Mainland_China
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public AirCondition AirQuality { get; set; } = AirCondition.Excellent;
|
||||
public int? AirQualityIndex { get; set; } = 15;
|
||||
|
||||
public int BatteryLevel { get; set; } = 67;
|
||||
public bool Bluetooth { get; set; } = true;
|
||||
|
|
|
@ -2,7 +2,31 @@
|
|||
{
|
||||
public enum WeatherCondition
|
||||
{
|
||||
Unknown = 279,
|
||||
Cloudy = 247
|
||||
Unknown,
|
||||
PartlyCloudy,
|
||||
CloudyAndRain,
|
||||
CloudyAndSnow,
|
||||
Sunny,
|
||||
Cloudy,
|
||||
LightRain,
|
||||
LightSnow,
|
||||
Rain,
|
||||
Snow,
|
||||
HeavySnow,
|
||||
HeavyRain,
|
||||
SandStorm,
|
||||
SnowAndRain,
|
||||
Fog,
|
||||
Haze,
|
||||
Storm,
|
||||
VeryHeavySnow,
|
||||
FloatingDust,
|
||||
Downpour,
|
||||
Hail,
|
||||
HailStorm,
|
||||
HeavyDownpour,
|
||||
BlowingDust,
|
||||
Tornado,
|
||||
VeryHeavyDownpour
|
||||
}
|
||||
}
|
|
@ -1,8 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using BumpKit;
|
||||
using WatchFace.Parser.Interfaces;
|
||||
using WatchFace.Parser.Models;
|
||||
|
||||
|
@ -10,52 +7,23 @@ namespace WatchFace.Parser
|
|||
{
|
||||
public class PreviewGenerator
|
||||
{
|
||||
public static void CreateGif(List<Parameter> descriptor, Bitmap[] images, Stream outputStream)
|
||||
public static IEnumerable<Image> CreateAnimation(List<Parameter> descriptor, Bitmap[] images,
|
||||
IEnumerable<WatchState> states)
|
||||
{
|
||||
var previewWatchFace = new Models.Elements.WatchFace(descriptor);
|
||||
var watchState = new WatchState();
|
||||
var time = watchState.Time;
|
||||
|
||||
using (var encoder = new GifEncoder(outputStream))
|
||||
foreach (var watchState in states)
|
||||
{
|
||||
for (var i = 0; i < 10; i++)
|
||||
using (var image = CreateFrame(previewWatchFace, images, watchState))
|
||||
{
|
||||
var num = i + 1;
|
||||
watchState.BatteryLevel = num * 10;
|
||||
|
||||
watchState.Pulse = 60 + num * 2;
|
||||
watchState.Steps = num * 1000;
|
||||
watchState.Calories = num * 75;
|
||||
watchState.Distance = num * 700;
|
||||
|
||||
watchState.Bluetooth = num > 1 && num < 6;
|
||||
watchState.Unlocked = num > 2 && num < 7;
|
||||
watchState.Alarm = num > 3 && num < 8;
|
||||
watchState.DoNotDisturb = num > 4 && num < 9;
|
||||
|
||||
watchState.DayTemperature += 2;
|
||||
watchState.NightTemperature += 4;
|
||||
|
||||
if (num < 3)
|
||||
watchState.CurrentTemperature = null;
|
||||
else if (num == 3)
|
||||
watchState.CurrentTemperature = -10;
|
||||
else
|
||||
watchState.CurrentTemperature += 6;
|
||||
|
||||
watchState.Time = new DateTime(time.Year, num, num * 2 + 5, i * 2, i * 6, i);
|
||||
using (var image = CreateFrame(previewWatchFace, images, watchState))
|
||||
{
|
||||
encoder.AddFrame(image, frameDelay: TimeSpan.FromSeconds(1));
|
||||
}
|
||||
yield return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Image CreateImage(IEnumerable<Parameter> descriptor, Bitmap[] resources)
|
||||
public static Image CreateImage(IEnumerable<Parameter> descriptor, Bitmap[] images, WatchState state)
|
||||
{
|
||||
var previewWatchFace = new Models.Elements.WatchFace(descriptor);
|
||||
return CreateFrame(previewWatchFace, resources, new WatchState());
|
||||
return CreateFrame(previewWatchFace, images, state);
|
||||
}
|
||||
|
||||
private static Image CreateFrame(IDrawable watchFace, Bitmap[] resources, WatchState state)
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using Resources.Models;
|
||||
using WatchFace.Parser.Models;
|
||||
using Header = WatchFace.Parser.Models.Header;
|
||||
using Image = Resources.Models.Image;
|
||||
|
||||
namespace WatchFace.Parser
|
||||
{
|
||||
|
@ -18,7 +22,8 @@ namespace WatchFace.Parser
|
|||
}
|
||||
|
||||
public List<Parameter> Parameters { get; private set; }
|
||||
public List<Bitmap> Images { get; private set; }
|
||||
public List<IResource> Resources { get; private set; }
|
||||
public Bitmap[] Images => Resources.OfType<Image>().Select(i => i.Bitmap).ToArray();
|
||||
|
||||
public void Read()
|
||||
{
|
||||
|
@ -46,7 +51,7 @@ namespace WatchFace.Parser
|
|||
Logger.Trace("Watch face parameters locations were read:");
|
||||
|
||||
Parameters = ReadParameters(parametrsTableLength, parametersLocations);
|
||||
Images = new Resources.Reader(_stream).Read((uint) imagesCount);
|
||||
Resources = new Resources.Reader(_stream).Read((uint) imagesCount);
|
||||
}
|
||||
|
||||
private List<Parameter> ReadParameters(long coordinatesTableSize, ICollection<Parameter> parametersDescriptors)
|
||||
|
|
|
@ -15,8 +15,6 @@ namespace WatchFace.Parser.Utils
|
|||
var result = new List<Parameter>();
|
||||
var currentType = typeof(T);
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
Logger.Trace("{0} '{1}'", path, currentType.Name);
|
||||
foreach (var kv in ElementsHelper.SortedProperties<T>())
|
||||
{
|
||||
var id = kv.Key;
|
||||
|
@ -52,11 +50,21 @@ namespace WatchFace.Parser.Utils
|
|||
else if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>))
|
||||
{
|
||||
foreach (var item in propertyValue)
|
||||
{
|
||||
Logger.Trace("{0} '{1}'", currentPath, propertyInfo.Name);
|
||||
result.Add(new Parameter(id, Build(item, currentPath)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(new Parameter(id, Build(propertyValue, currentPath)));
|
||||
var innerParameters = Build(propertyValue, currentPath);
|
||||
if (innerParameters.Count > 0)
|
||||
{
|
||||
Logger.Trace("{0} '{1}'", currentPath, propertyInfo.Name);
|
||||
result.Add(new Parameter(id, innerParameters));
|
||||
}
|
||||
else
|
||||
Logger.Trace("{0} '{1}': Skipped because of empty", currentPath, propertyInfo.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,8 +79,6 @@ namespace WatchFace.Parser.Utils
|
|||
|
||||
var thisMethod = typeof(ParametersConverter).GetMethod(nameof(Parse));
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
Logger.Trace("{0} '{1}'", path, currentType.Name);
|
||||
foreach (var parameter in descriptor)
|
||||
{
|
||||
var currentPath = string.IsNullOrEmpty(path)
|
||||
|
@ -107,6 +113,7 @@ namespace WatchFace.Parser.Utils
|
|||
}
|
||||
else if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>))
|
||||
{
|
||||
Logger.Trace("{0} '{1}'", currentPath, propertyInfo.Name);
|
||||
dynamic propertyValue = propertyInfo.GetValue(result, null);
|
||||
if (propertyValue == null)
|
||||
{
|
||||
|
@ -128,6 +135,7 @@ namespace WatchFace.Parser.Utils
|
|||
}
|
||||
else
|
||||
{
|
||||
Logger.Trace("{0} '{1}'", currentPath, propertyInfo.Name);
|
||||
dynamic propertyValue = propertyInfo.GetValue(result, null);
|
||||
if (propertyValue != null)
|
||||
throw new ArgumentException($"Parameter {parameter.Id} is already set for {currentType.Name}");
|
||||
|
|
|
@ -1,31 +1,35 @@
|
|||
using System;
|
||||
using NLog;
|
||||
using Resources;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using NLog;
|
||||
using Resources;
|
||||
using System.Linq;
|
||||
using Resources.Models;
|
||||
using WatchFace.Parser.Attributes;
|
||||
using Image = Resources.Models.Image;
|
||||
|
||||
namespace WatchFace.Parser.Utils
|
||||
{
|
||||
public class ImagesLoader
|
||||
public class ResourcesLoader
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
private readonly string _imagesDirectory;
|
||||
|
||||
private readonly Dictionary<long, long> _mapping;
|
||||
|
||||
public ImagesLoader(string imagesDirectory)
|
||||
public ResourcesLoader(string imagesDirectory)
|
||||
{
|
||||
Images = new List<Bitmap>();
|
||||
Resources = new List<IResource>();
|
||||
_mapping = new Dictionary<long, long>();
|
||||
_imagesDirectory = imagesDirectory;
|
||||
}
|
||||
|
||||
public List<Bitmap> Images { get; }
|
||||
public List<IResource> Resources { get; }
|
||||
public Bitmap[] Images => Resources.OfType<Image>().Select(i => i.Bitmap).ToArray();
|
||||
|
||||
public void Process<T>(T serializable, string path = "")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(path)) Logger.Trace("Loading images for {0} '{1}'", path, typeof(T).Name);
|
||||
if (!string.IsNullOrEmpty(path)) Logger.Trace("Loading resources for {0} '{1}'", path, typeof(T).Name);
|
||||
|
||||
long? lastImageIndexValue = null;
|
||||
|
||||
|
@ -67,7 +71,7 @@ namespace WatchFace.Parser.Utils
|
|||
{
|
||||
if (lastImageIndexValue == null)
|
||||
throw new ArgumentException(
|
||||
$"Property {propertyInfo.Name} can't be processed becuase ImageIndex isn't present or it is zero"
|
||||
$"Property {propertyInfo.Name} can't be processed because ImageIndex isn't present or it is zero"
|
||||
);
|
||||
|
||||
var imagesCount = propertyType.IsGenericType
|
||||
|
@ -102,9 +106,10 @@ namespace WatchFace.Parser.Utils
|
|||
if (_mapping.ContainsKey(index))
|
||||
return _mapping[index];
|
||||
|
||||
var newImageIndex = Images.Count;
|
||||
var newImageIndex = Resources.Count;
|
||||
Logger.Trace("Loading image {0}...", newImageIndex);
|
||||
Images.Add(ImageLoader.LoadImageForNumber(_imagesDirectory, index));
|
||||
var resource = ImageLoader.LoadResourceForNumber(_imagesDirectory, index);
|
||||
Resources.Add(resource);
|
||||
_mapping[index] = newImageIndex;
|
||||
return newImageIndex;
|
||||
}
|
|
@ -31,19 +31,19 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BumpKit, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Bumpkit.1.0.2\lib\BumpKit.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.12\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.4.5.6\lib\net40-client\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
|
@ -59,16 +59,20 @@
|
|||
<Compile Include="Elements\BasicElements\Coordinates.cs" />
|
||||
<Compile Include="Elements\BasicElements\Image.cs" />
|
||||
<Compile Include="Elements\BasicElements\ImageSet.cs" />
|
||||
<Compile Include="Elements\BasicElements\UnknownType14d6.cs" />
|
||||
<Compile Include="Elements\BasicElements\UnknownType.cs" />
|
||||
<Compile Include="Elements\BasicElements\Number.cs" />
|
||||
<Compile Include="Elements\BasicElements\Scale.cs" />
|
||||
<Compile Include="Elements\Battery.cs" />
|
||||
<Compile Include="Elements\Date.cs" />
|
||||
<Compile Include="Elements\DateElements\DateUnknown3.cs" />
|
||||
<Compile Include="Elements\DateElements\MonthAndDay.cs" />
|
||||
<Compile Include="Elements\DateElements\OneLineMonthAndDay.cs" />
|
||||
<Compile Include="Elements\DateElements\SeparateMonthAndDay.cs" />
|
||||
<Compile Include="Elements\StepsProgress.cs" />
|
||||
<Compile Include="Elements\Status.cs" />
|
||||
<Compile Include="Elements\StatusElements\Switch.cs" />
|
||||
<Compile Include="Elements\UnknownType14.cs" />
|
||||
<Compile Include="Elements\Time.cs" />
|
||||
<Compile Include="Elements\TimeElements\AmPm.cs" />
|
||||
<Compile Include="Elements\TimeElements\TwoDigits.cs" />
|
||||
|
@ -120,6 +124,7 @@
|
|||
<Compile Include="Models\Elements\TimeElement.cs" />
|
||||
<Compile Include="Models\Elements\Common\TwoDigitsElement.cs" />
|
||||
<Compile Include="Models\Elements\WatchFace.cs" />
|
||||
<Compile Include="Models\Elements\Weather\AirPollution\AirQualityIndexNumberElement.cs" />
|
||||
<Compile Include="Models\Elements\Weather\Temperature\Today\OnelineTemperatureElement.cs" />
|
||||
<Compile Include="Models\Elements\Weather\Temperature\CurrentTemperatureElement.cs" />
|
||||
<Compile Include="Models\Elements\Weather\AirPollution\AirPollutionImageElement.cs" />
|
||||
|
@ -155,7 +160,7 @@
|
|||
<Compile Include="Attributes\ParameterImagesCountAttribute.cs" />
|
||||
<Compile Include="Utils\DrawingOrderIterator.cs" />
|
||||
<Compile Include="Utils\ElementsHelper.cs" />
|
||||
<Compile Include="Utils\ImagesLoader.cs" />
|
||||
<Compile Include="Utils\ResourcesLoader.cs" />
|
||||
<Compile Include="Utils\ParametersConverter.cs" />
|
||||
<Compile Include="Attributes\ParameterImageIndexAttribute.cs" />
|
||||
<Compile Include="Attributes\ParameterIdAttribute.cs" />
|
||||
|
@ -172,9 +177,34 @@
|
|||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="WeatherIcons\247.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\279.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\1.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\0.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="WeatherIcons\10.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\11.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\12.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\13.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\14.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\15.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\16.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\17.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\18.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\19.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\2.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\20.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\21.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\22.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\23.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\24.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\25.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\3.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\4.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\5.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\6.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\7.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\8.png" />
|
||||
<EmbeddedResource Include="WeatherIcons\9.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -31,5 +31,8 @@ namespace WatchFace.Parser
|
|||
|
||||
[ParameterId(10)]
|
||||
public AnalogDialFace AnalogDialFace { get; set; }
|
||||
|
||||
[ParameterId(14)]
|
||||
public UnknownType14 Unknown14 { get; set; }
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 332 B After Width: | Height: | Size: 332 B |
Before Width: | Height: | Size: 352 B After Width: | Height: | Size: 352 B |
After Width: | Height: | Size: 334 B |
After Width: | Height: | Size: 325 B |
After Width: | Height: | Size: 288 B |
After Width: | Height: | Size: 334 B |
After Width: | Height: | Size: 236 B |
After Width: | Height: | Size: 302 B |
After Width: | Height: | Size: 365 B |
After Width: | Height: | Size: 340 B |
After Width: | Height: | Size: 229 B |
After Width: | Height: | Size: 319 B |
After Width: | Height: | Size: 372 B |
After Width: | Height: | Size: 335 B |
After Width: | Height: | Size: 367 B |
After Width: | Height: | Size: 316 B |
After Width: | Height: | Size: 270 B |
After Width: | Height: | Size: 278 B |
After Width: | Height: | Size: 305 B |
After Width: | Height: | Size: 374 B |
After Width: | Height: | Size: 326 B |
After Width: | Height: | Size: 297 B |
After Width: | Height: | Size: 314 B |
After Width: | Height: | Size: 316 B |
After Width: | Height: | Size: 324 B |
After Width: | Height: | Size: 319 B |
|
@ -2,18 +2,20 @@
|
|||
using System.Drawing;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using Resources.Models;
|
||||
using WatchFace.Parser.Models;
|
||||
using Header = WatchFace.Parser.Models.Header;
|
||||
|
||||
namespace WatchFace.Parser
|
||||
{
|
||||
public class Writer
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
private readonly List<Bitmap> _images;
|
||||
private readonly List<IResource> _images;
|
||||
|
||||
private readonly Stream _stream;
|
||||
|
||||
public Writer(Stream stream, List<Bitmap> images)
|
||||
public Writer(Stream stream, List<IResource> images)
|
||||
{
|
||||
_stream = stream;
|
||||
_images = images;
|
||||
|
@ -25,6 +27,7 @@ namespace WatchFace.Parser
|
|||
var encodedParameters = new Dictionary<byte, MemoryStream>(descriptor.Count);
|
||||
foreach (var parameter in descriptor)
|
||||
{
|
||||
Logger.Trace("Parameter: {0}", parameter.Id);
|
||||
var memoryStream = new MemoryStream();
|
||||
foreach (var child in parameter.Children)
|
||||
child.Write(memoryStream);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Bumpkit" version="1.0.2" targetFramework="net40-client" />
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net40-client" />
|
||||
<package id="NLog" version="4.4.12" targetFramework="net40-client" />
|
||||
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net40-client" />
|
||||
<package id="NLog" version="4.5.6" targetFramework="net40-client" />
|
||||
</packages>
|
|
@ -3,6 +3,9 @@ using System.Collections.Generic;
|
|||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using BumpKit;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
|
@ -10,7 +13,9 @@ using NLog.Targets;
|
|||
using Resources;
|
||||
using Resources.Models;
|
||||
using WatchFace.Parser;
|
||||
using WatchFace.Parser.Models;
|
||||
using WatchFace.Parser.Utils;
|
||||
using Image = System.Drawing.Image;
|
||||
using Reader = WatchFace.Parser.Reader;
|
||||
using Writer = WatchFace.Parser.Writer;
|
||||
|
||||
|
@ -20,6 +25,7 @@ namespace WatchFace
|
|||
{
|
||||
private const string AppName = "WatchFace";
|
||||
|
||||
private static readonly bool IsRunningOnMono = Type.GetType("Mono.Runtime") != null;
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private static void Main(string[] args)
|
||||
|
@ -107,7 +113,7 @@ namespace WatchFace
|
|||
var imagesDirectory = Path.GetDirectoryName(inputFileName);
|
||||
try
|
||||
{
|
||||
WriteWatchFace(outputFileName, imagesDirectory, watchFace);
|
||||
WriteWatchFace(outputDirectory, outputFileName, imagesDirectory, watchFace);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
@ -128,16 +134,10 @@ namespace WatchFace
|
|||
var watchFace = ParseResources(reader);
|
||||
if (watchFace == null) return;
|
||||
|
||||
Logger.Debug("Generating previews...");
|
||||
var preview = PreviewGenerator.CreateImage(reader.Parameters, reader.Images.ToArray());
|
||||
preview.Save(Path.Combine(outputDirectory, $"{baseName}_preview.png"), ImageFormat.Png);
|
||||
using (var gifOutput = File.OpenWrite(Path.Combine(outputDirectory, $"{baseName}_preview.gif")))
|
||||
{
|
||||
PreviewGenerator.CreateGif(reader.Parameters, reader.Images.ToArray(), gifOutput);
|
||||
}
|
||||
GeneratePreviews(reader.Parameters, reader.Images, outputDirectory, baseName);
|
||||
|
||||
Logger.Debug("Exporting resources to '{0}'", outputDirectory);
|
||||
var reDescriptor = new FileDescriptor {Images = reader.Images};
|
||||
var reDescriptor = new FileDescriptor {Resources = reader.Resources};
|
||||
new Extractor(reDescriptor).Extract(outputDirectory);
|
||||
ExportWatchFaceConfig(watchFace, Path.Combine(outputDirectory, $"{baseName}.json"));
|
||||
}
|
||||
|
@ -174,13 +174,13 @@ namespace WatchFace
|
|||
}
|
||||
|
||||
var i = 0;
|
||||
var images = new List<Bitmap>();
|
||||
var images = new List<IResource>();
|
||||
while (resDescriptor.ResourcesCount == null || i < resDescriptor.ResourcesCount.Value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var image = ImageLoader.LoadImageForNumber(inputDirectory, i);
|
||||
images.Add(image);
|
||||
var resource = ImageLoader.LoadResourceForNumber(inputDirectory, i);
|
||||
images.Add(resource);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
|
@ -192,9 +192,10 @@ namespace WatchFace
|
|||
}
|
||||
|
||||
if (resDescriptor.ResourcesCount != null && resDescriptor.ResourcesCount.Value != images.Count)
|
||||
throw new ArgumentException($"The .res-file should contain {resDescriptor.ResourcesCount.Value} images but was loaded {images.Count} images.");
|
||||
throw new ArgumentException(
|
||||
$"The .res-file should contain {resDescriptor.ResourcesCount.Value} images but was loaded {images.Count} images.");
|
||||
|
||||
resDescriptor.Images = images;
|
||||
resDescriptor.Resources = images;
|
||||
|
||||
using (var stream = File.OpenWrite(outputFileName))
|
||||
{
|
||||
|
@ -218,29 +219,24 @@ namespace WatchFace
|
|||
new Extractor(resDescriptor).Extract(outputDirectory);
|
||||
}
|
||||
|
||||
private static void WriteWatchFace(string outputFileName, string imagesDirectory, Parser.WatchFace watchFace)
|
||||
private static void WriteWatchFace(string outputDirectory, string outputFileName, string imagesDirectory, Parser.WatchFace watchFace)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.Debug("Reading referenced images from '{0}'", imagesDirectory);
|
||||
var imagesReader = new ImagesLoader(imagesDirectory);
|
||||
var imagesReader = new ResourcesLoader(imagesDirectory);
|
||||
imagesReader.Process(watchFace);
|
||||
|
||||
Logger.Trace("Building parameters for watch face...");
|
||||
var descriptor = ParametersConverter.Build(watchFace);
|
||||
|
||||
Logger.Debug("Generating preview...");
|
||||
var preview = PreviewGenerator.CreateImage(descriptor, imagesReader.Images.ToArray());
|
||||
preview.Save(Path.ChangeExtension(outputFileName, ".png"));
|
||||
using (var gifOutput = File.OpenWrite(Path.ChangeExtension(outputFileName, ".gif")))
|
||||
{
|
||||
PreviewGenerator.CreateGif(descriptor, imagesReader.Images.ToArray(), gifOutput);
|
||||
}
|
||||
var baseFilename = Path.GetFileNameWithoutExtension(outputFileName);
|
||||
GeneratePreviews(descriptor, imagesReader.Images, outputDirectory, baseFilename);
|
||||
|
||||
Logger.Debug("Writing watch face to '{0}'", outputFileName);
|
||||
using (var fileStream = File.OpenWrite(outputFileName))
|
||||
{
|
||||
var writer = new Writer(fileStream, imagesReader.Images);
|
||||
var writer = new Writer(fileStream, imagesReader.Resources);
|
||||
writer.Write(descriptor);
|
||||
fileStream.Flush();
|
||||
}
|
||||
|
@ -386,7 +382,10 @@ namespace WatchFace
|
|||
var fileTarget = new FileTarget
|
||||
{
|
||||
FileName = logFileName,
|
||||
Layout = "${level}|${message}"
|
||||
Layout = "${level}|${message}",
|
||||
KeepFileOpen = true,
|
||||
ConcurrentWrites = false,
|
||||
OpenFileCacheTimeout = 30
|
||||
};
|
||||
config.AddTarget("file", fileTarget);
|
||||
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, fileTarget));
|
||||
|
@ -397,5 +396,109 @@ namespace WatchFace
|
|||
|
||||
LogManager.Configuration = config;
|
||||
}
|
||||
|
||||
private static void GeneratePreviews(List<Parameter> parameters, Bitmap[] images, string outputDirectory, string baseName)
|
||||
{
|
||||
Logger.Debug("Generating previews...");
|
||||
|
||||
var states = GetPreviewStates();
|
||||
var staticPreview = PreviewGenerator.CreateImage(parameters, images, new WatchState());
|
||||
staticPreview.Save(Path.Combine(outputDirectory, $"{baseName}_static.png"), ImageFormat.Png);
|
||||
|
||||
var previewImages = PreviewGenerator.CreateAnimation(parameters, images, states);
|
||||
|
||||
if (IsRunningOnMono)
|
||||
{
|
||||
var i = 0;
|
||||
foreach (var previewImage in previewImages)
|
||||
{
|
||||
previewImage.Save(Path.Combine(outputDirectory, $"{baseName}_animated_{i}.png"), ImageFormat.Png);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var gifOutput = File.OpenWrite(Path.Combine(outputDirectory, $"{baseName}_animated.gif")))
|
||||
using (var encoder = new GifEncoder(gifOutput))
|
||||
{
|
||||
foreach (var previewImage in previewImages)
|
||||
encoder.AddFrame(previewImage, frameDelay: TimeSpan.FromSeconds(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<WatchState> GetPreviewStates()
|
||||
{
|
||||
var appPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
var previewStatesPath = Path.Combine(appPath, "PreviewStates.json");
|
||||
|
||||
if (File.Exists(previewStatesPath))
|
||||
using (var stream = File.OpenRead(previewStatesPath))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
var json = reader.ReadToEnd();
|
||||
return JsonConvert.DeserializeObject<List<WatchState>>(json);
|
||||
}
|
||||
|
||||
var previewStates = GenerateSampleStates();
|
||||
using (var stream = File.OpenWrite(previewStatesPath))
|
||||
using (var writer = new StreamWriter(stream))
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(previewStates, Formatting.Indented);
|
||||
writer.Write(json);
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
return previewStates;
|
||||
}
|
||||
|
||||
private static IEnumerable<WatchState> GenerateSampleStates()
|
||||
{
|
||||
var time = DateTime.Now;
|
||||
var states = new List<WatchState>();
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var num = i + 1;
|
||||
var watchState = new WatchState
|
||||
{
|
||||
BatteryLevel = 100 - i * 10,
|
||||
Pulse = 60 + num * 2,
|
||||
Steps = num * 1000,
|
||||
Calories = num * 75,
|
||||
Distance = num * 700,
|
||||
Bluetooth = num > 1 && num < 6,
|
||||
Unlocked = num > 2 && num < 7,
|
||||
Alarm = num > 3 && num < 8,
|
||||
DoNotDisturb = num > 4 && num < 9,
|
||||
|
||||
DayTemperature = -15 + 2 * i,
|
||||
NightTemperature = -24 + i * 4,
|
||||
};
|
||||
|
||||
if (num < 3)
|
||||
{
|
||||
watchState.AirQuality = AirCondition.Unknown;
|
||||
watchState.AirQualityIndex = null;
|
||||
|
||||
watchState.CurrentWeather = WeatherCondition.Unknown;
|
||||
watchState.CurrentTemperature = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = num - 2;
|
||||
watchState.AirQuality = (AirCondition) index;
|
||||
watchState.CurrentWeather = (WeatherCondition) index;
|
||||
|
||||
watchState.AirQualityIndex = index * 50 - 25;
|
||||
watchState.CurrentTemperature = -10 + i * 6;
|
||||
}
|
||||
|
||||
watchState.Time = new DateTime(time.Year, num, num * 2 + 5, i * 2, i * 6, i);
|
||||
states.Add(watchState);
|
||||
}
|
||||
|
||||
return states;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,16 +35,24 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="BumpKit, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Bumpkit.1.0.2\lib\BumpKit.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.12\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.4.5.6\lib\net40-client\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net40-client" />
|
||||
<package id="NLog" version="4.4.12" targetFramework="net40-client" />
|
||||
<package id="Bumpkit" version="1.0.2" targetFramework="net40-client" />
|
||||
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net40-client" />
|
||||
<package id="NLog" version="4.5.6" targetFramework="net40-client" />
|
||||
</packages>
|