amazfitbiptools/WatchFace.Parser/Reader.cs

95 lines
3.8 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using NLog;
using SixLabors.ImageSharp;
using WatchFace.Models;
namespace WatchFace
{
public class Reader
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly FileStream _fileStream;
public Reader(FileStream streamReader)
{
_fileStream = streamReader;
}
public List<Parameter> Resources { get; private set; }
public List<Image<Rgba32>> Images { get; private set; }
public void Read()
{
Logger.Trace("Reading header...");
var header = Header.ReadFrom(_fileStream);
Logger.Trace("Header was read:");
Logger.Trace("Signature: {0}, Unknown: {1}, ParametersSize: {2}, IsValid: {3}", header.Signature,
header.Unknown,
header.ParametersSize, header.IsValid);
if (!header.IsValid) return;
Logger.Trace("Reading parameter offsets...");
var parametersStream = StreamBlock(_fileStream, (int) header.ParametersSize);
Logger.Trace("Parameter offsets were read from file");
Logger.Trace("Reading parameters descriptor...");
var mainParam = Parameter.ReadFrom(parametersStream);
Logger.Trace("Parameters descriptor was read:");
var coordinatesTableSize = mainParam.Children[0].Value;
var imagesTableLength = mainParam.Children[1].Value;
Logger.Trace($"CoordinatesTableSize: {coordinatesTableSize}, ImagesTableLength: {imagesTableLength}");
Logger.Trace("Reading face parameters...");
var parameters = Parameter.ReadList(parametersStream);
Logger.Trace("Watch face parameters were read:");
ParseResources(coordinatesTableSize, parameters);
ParseImages(imagesTableLength);
}
private void ParseResources(long coordinatesTableSize, IReadOnlyCollection<Parameter> parameters)
{
var coordsStream = StreamBlock(_fileStream, (int) coordinatesTableSize);
Resources = new List<Parameter>(parameters.Count);
foreach (var parameter in parameters)
{
Logger.Trace("Reading descriptor for parameter {0}", parameter.Id);
var descriptorOffset = parameter.Children[0].Value;
var descriptorLength = parameter.Children[1].Value;
Logger.Trace("Descriptor offset: {0}, Descriptor length: {1}", descriptorOffset, descriptorLength);
coordsStream.Seek(descriptorOffset, SeekOrigin.Begin);
var descriptorStream = StreamBlock(coordsStream, (int) descriptorLength);
Logger.Trace("Parsing descriptor for parameter {0}...", parameter.Id);
Resources.Add(new Parameter(parameter.Id, Parameter.ReadList(descriptorStream)));
}
}
private void ParseImages(long imagesTableLength)
{
var imagesOffsets = new byte[imagesTableLength * 4];
_fileStream.Read(imagesOffsets, 0, imagesOffsets.Length);
var imagesOffset = _fileStream.Position;
Images = new List<Image<Rgba32>>((int) imagesTableLength);
for (var i = 0; i < (int) imagesTableLength; i++)
{
var imageOffset = BitConverter.ToUInt32(imagesOffsets, i * 4) + imagesOffset;
_fileStream.Seek(imageOffset, SeekOrigin.Begin);
var image = new ImageReader(_fileStream).Read();
Images.Add(image);
}
}
private static Stream StreamBlock(Stream stream, int size)
{
var buffer = new byte[size];
stream.Read(buffer, 0, buffer.Length);
return new MemoryStream(buffer);
}
}
}