Fixed invalid colors on unpacking 16bit images, added support for new WF elements

amazfit_cor
Valeriy Mironov 2018-03-16 02:27:29 +02:00
parent 237308699a
commit d48bc3d81c
14 changed files with 174 additions and 31 deletions

View File

@ -118,11 +118,11 @@ namespace Resources.Image
var bitReader = new BitReader(rowBytes);
for (var x = 0; x < _width; x++)
{
var firstByte = bitReader.ReadByte();
var secondByte = bitReader.ReadByte();
var b = ((secondByte >> 3) & 0x1f) << 3;
var g = ((secondByte & (0x07 << 2)) | (firstByte & (0x40 >> 5))) << 3;
var r = (firstByte & 0x1f) << 3;
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);
}

View File

@ -19,6 +19,9 @@ namespace WatchFace.Parser.Elements
public CompositeNumber Pulse { get; set; }
[ParameterId(5)]
public FormattedNumber Distance { get; set; }
public DistanceNumber Distance { get; set; }
[ParameterId(6)]
public StepsWithGoalNumber StepsWithGoal { get; set; }
}
}

View File

@ -3,7 +3,7 @@ using WatchFace.Parser.Elements.BasicElements;
namespace WatchFace.Parser.Elements.ActivityElements
{
public class FormattedNumber
public class DistanceNumber
{
[ParameterId(1)]
public Number Number { get; set; }

View File

@ -0,0 +1,15 @@
using WatchFace.Parser.Attributes;
using WatchFace.Parser.Elements.BasicElements;
namespace WatchFace.Parser.Elements.ActivityElements
{
public class StepsWithGoalNumber
{
[ParameterId(1)]
public Number Number { get; set; }
[ParameterId(2)]
[ParameterImageIndex]
public long? DelimiterImageIndex { get; set; }
}
}

View File

@ -1,12 +1,13 @@
using WatchFace.Parser.Attributes;
using WatchFace.Parser.Elements.BasicElements;
using WatchFace.Parser.Elements.BatteryElements;
namespace WatchFace.Parser.Elements
{
public class Battery
{
[ParameterId(1)]
public CompositeNumber Text { get; set; }
public BatteryNumber Text { get; set; }
[ParameterId(2)]
public ImageSet Icon { get; set; }

View File

@ -0,0 +1,23 @@
using WatchFace.Parser.Attributes;
using WatchFace.Parser.Elements.BasicElements;
namespace WatchFace.Parser.Elements.BatteryElements
{
public class BatteryNumber
{
[ParameterId(1)]
public Number Number { get; set; }
[ParameterId(2)]
[ParameterImageIndex]
public CircleScale CircleScale { get; set; }
[ParameterId(3)]
[ParameterImageIndex]
public long? PrefixImageIndex { get; set; }
[ParameterId(4)]
[ParameterImageIndex]
public long? SuffixImageIndex { get; set; }
}
}

View File

@ -0,0 +1,40 @@
using System.Collections.Generic;
using System.Drawing;
using WatchFace.Parser.Helpers;
using WatchFace.Parser.Interfaces;
namespace WatchFace.Parser.Models.Elements.Activity
{
public class StepsWithGoalElement : CompositeElement, IDrawable
{
public StepsWithGoalElement(Parameter parameter, Element parent, string name = null) :
base(parameter, parent, name) { }
public NumberElement Number { get; set; }
public long DelimiterImageIndex { get; set; }
public void Draw(Graphics drawer, Bitmap[] resources, WatchState state)
{
var images = new List<Bitmap>();
images.AddRange(Number.GetImagesForNumber(resources, state.Steps));
images.Add(resources[DelimiterImageIndex]);
images.AddRange(Number.GetImagesForNumber(resources, state.Goal));
DrawerHelper.DrawImages(drawer, images, (int)Number.Spacing, Number.Alignment, Number.GetBox());
}
protected override Element CreateChildForParameter(Parameter parameter)
{
switch (parameter.Id)
{
case 1:
Number = new NumberElement(parameter, this, nameof(Number));
return Number;
case 2:
DelimiterImageIndex = parameter.Value;
return new ValueElement(parameter, this, nameof(DelimiterImageIndex));
default:
return base.CreateChildForParameter(parameter);
}
}
}
}

View File

@ -1,4 +1,6 @@
namespace WatchFace.Parser.Models.Elements
using WatchFace.Parser.Models.Elements.Activity;
namespace WatchFace.Parser.Models.Elements
{
public class ActivityElement : ContainerElement
{
@ -10,6 +12,7 @@
public CaloriesElement Calories { get; set; }
public PulseElement Pulse { get; set; }
public DistanceElement Distance { get; set; }
public StepsWithGoalElement StepsWithGoal { get; set; }
protected override Element CreateChildForParameter(Parameter parameter)
{
@ -30,6 +33,9 @@
case 5:
Distance = new DistanceElement(parameter, this);
return Distance;
case 6:
StepsWithGoal = new StepsWithGoalElement(parameter, this);
return StepsWithGoal;
default:
return base.CreateChildForParameter(parameter);
}

View File

@ -1,6 +1,4 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing;
using BumpKit;
using WatchFace.Parser.Interfaces;
@ -32,22 +30,23 @@ namespace WatchFace.Parser.Models.Elements
{
var angle = DegreeFromValues(state.Time.Minute, 60);
var hoursImage = RotateImage(
resources[Minutes.ImageIndex], new Point((int)Minutes.X, (int)Minutes.Y), angle
resources[Minutes.ImageIndex], new Point((int) Minutes.X, (int) Minutes.Y), angle
);
drawer.DrawImage(hoursImage, new Point((int)RedrawArea.X, (int)RedrawArea.Y));
drawer.DrawImage(hoursImage, new Point((int) RedrawArea.X, (int) RedrawArea.Y));
}
if (Seconds != null)
{
var angle = DegreeFromValues(state.Time.Second, 60);
var hoursImage = RotateImage(
resources[Seconds.ImageIndex], new Point((int)Seconds.X, (int)Seconds.Y), angle
resources[Seconds.ImageIndex], new Point((int) Seconds.X, (int) Seconds.Y), angle
);
drawer.DrawImage(hoursImage, new Point((int)RedrawArea.X, (int)RedrawArea.Y));
drawer.DrawImage(hoursImage, new Point((int) RedrawArea.X, (int) RedrawArea.Y));
}
if (CenterImage != null)
drawer.DrawImage(resources[CenterImage.ImageIndex], new Point((int)CenterImage.X, (int)CenterImage.Y));
drawer.DrawImage(resources[CenterImage.ImageIndex],
new Point((int) CenterImage.X, (int) CenterImage.Y));
}
private static double DegreeFromValues(double value, double total)
@ -55,24 +54,19 @@ namespace WatchFace.Parser.Models.Elements
return value * 360 / total - 90;
}
private Bitmap RotateImage(Image image, Point ImageCoords, double degrees)
private Bitmap RotateImage(Image image, Point imageCoords, double degrees)
{
var radians = degrees / 180 * Math.PI;
var sin = Math.Sin(radians);
var cos = Math.Cos(radians);
var drawBox = RedrawArea.GetBox();
var newImage = new Bitmap(drawBox.Width, drawBox.Height);
using (var graphics = Graphics.FromImage(newImage))
{
graphics.DrawImage(image, new Point(ImageCoords.X - drawBox.X, ImageCoords.Y - drawBox.Y));
graphics.DrawImage(image, new Point(imageCoords.X - drawBox.X, imageCoords.Y - drawBox.Y));
}
while (degrees < 0) degrees += 360;
while (degrees > 360) degrees -= 360;
var rotated = newImage.Rotate(degrees);
rotated.Save("tmp.png");
return rotated as Bitmap;
return rotated as Bitmap;
}
protected override Element CreateChildForParameter(Parameter parameter)

View File

@ -1,16 +1,55 @@
using System.Drawing;
using System.Collections.Generic;
using System.Drawing;
using WatchFace.Parser.Helpers;
using WatchFace.Parser.Interfaces;
using WatchFace.Parser.Models.Elements.Common;
namespace WatchFace.Parser.Models.Elements.Battery
{
public class BatteryNumberElement : CompositeNumberElement, IDrawable
public class BatteryNumberElement : CompositeElement, IDrawable
{
public BatteryNumberElement(Parameter parameter, Element parent, string name = null) :
base(parameter, parent, name) { }
public NumberElement Number { get; set; }
public CircularProgressElement CircularProgress { get; set; }
public long? PrefixImageIndex { get; set; }
public long? SuffixImageIndex { get; set; }
public void Draw(Graphics drawer, Bitmap[] resources, WatchState state)
{
Draw(drawer, resources, state.BatteryLevel);
var images = new List<Bitmap>();
if (PrefixImageIndex != null)
images.Add(resources[PrefixImageIndex.Value]);
images.AddRange(Number.GetImagesForNumber(resources, state.BatteryLevel));
if (SuffixImageIndex != null)
images.Add(resources[SuffixImageIndex.Value]);
DrawerHelper.DrawImages(drawer, images, (int)Number.Spacing, Number.Alignment, Number.GetBox());
CircularProgress?.Draw(drawer, resources, state);
}
protected override Element CreateChildForParameter(Parameter parameter)
{
switch (parameter.Id)
{
case 1:
Number = new NumberElement(parameter, this, nameof(Number));
return Number;
case 2:
CircularProgress = new CircularBatteryProgressElement(parameter, this);
return CircularProgress;
case 3:
PrefixImageIndex = parameter.Value;
return new ValueElement(parameter, this, nameof(PrefixImageIndex));
case 4:
SuffixImageIndex = parameter.Value;
return new ValueElement(parameter, this, nameof(SuffixImageIndex));
default:
return base.CreateChildForParameter(parameter);
}
}
}
}

View File

@ -0,0 +1,16 @@
using System.Drawing;
using WatchFace.Parser.Models.Elements.Common;
namespace WatchFace.Parser.Models.Elements.Battery
{
public class CircularBatteryProgressElement : CircularProgressElement
{
public CircularBatteryProgressElement(Parameter parameter, Element parent, string name = null) :
base(parameter, parent, name) { }
public override void Draw(Graphics drawer, Bitmap[] resources, WatchState state)
{
Draw(drawer, resources, state.BatteryLevel, 100);
}
}
}

View File

@ -1,7 +1,7 @@
using System.Drawing;
using WatchFace.Parser.Interfaces;
namespace WatchFace.Parser.Models.Elements.GoalProgress
namespace WatchFace.Parser.Models.Elements.Common
{
public abstract class CircularProgressElement : CoordinatesElement, IDrawable
{
@ -19,7 +19,8 @@ namespace WatchFace.Parser.Models.Elements.GoalProgress
public void Draw(Graphics drawer, Bitmap[] resources, int value, int total)
{
var sectorAngle = (EndAngle - StartAngle) * value / total;
var part = value >= total ? 1.0f : (float) value / total;
var sectorAngle = (EndAngle - StartAngle) * part;
var pen = new Pen(Color, Width);
var rect = new Rectangle((int) (X - RadiusX), (int) (Y - RadiusY),
(int) (RadiusX * 2), (int) (RadiusY * 2));

View File

@ -1,4 +1,5 @@
using System.Drawing;
using WatchFace.Parser.Models.Elements.Common;
namespace WatchFace.Parser.Models.Elements.GoalProgress
{

View File

@ -51,8 +51,9 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Elements\Activity.cs" />
<Compile Include="Elements\ActivityElements\StepsWithGoalNumber.cs" />
<Compile Include="Elements\BasicElements\CompositeNumber.cs" />
<Compile Include="Elements\ActivityElements\FormattedNumber.cs" />
<Compile Include="Elements\ActivityElements\DistanceNumber.cs" />
<Compile Include="Elements\AnalogDialVector.cs" />
<Compile Include="Elements\Background.cs" />
<Compile Include="Elements\BasicElements\CircleScale.cs" />
@ -64,6 +65,7 @@
<Compile Include="Elements\BasicElements\Number.cs" />
<Compile Include="Elements\BasicElements\Scale.cs" />
<Compile Include="Elements\Battery.cs" />
<Compile Include="Elements\BatteryElements\BatteryNumber.cs" />
<Compile Include="Elements\Date.cs" />
<Compile Include="Elements\DateElements\MonthAndDay.cs" />
<Compile Include="Elements\DateElements\OneLineMonthAndDay.cs" />
@ -91,6 +93,7 @@
<Compile Include="JsonConverters\ColorJsonConverter.cs" />
<Compile Include="Models\DrawingOrderPosition.cs" />
<Compile Include="Models\Elements\Activity\CaloriesElement.cs" />
<Compile Include="Models\Elements\Activity\StepsWithGoalElement.cs" />
<Compile Include="Models\Elements\Activity\StepsElement.cs" />
<Compile Include="Models\Elements\Activity\StepsGoalElement.cs" />
<Compile Include="Models\Elements\Activity\PulseElement.cs" />
@ -101,6 +104,7 @@
<Compile Include="Models\Elements\Basic\ContainerElement.cs" />
<Compile Include="Models\Elements\Battery\BatteryLenearProgressElement.cs" />
<Compile Include="Models\Elements\Battery\BatteryNumberElement.cs" />
<Compile Include="Models\Elements\Battery\CircularBatteryProgressElement.cs" />
<Compile Include="Models\Elements\Common\CompositeNumberElement.cs" />
<Compile Include="Models\Elements\Common\ImageSetElement.cs" />
<Compile Include="Models\Elements\Common\CircularProgressElement.cs" />