Skip to content

Commit

Permalink
Merge pull request #635 from sn4k3/anet-n7
Browse files Browse the repository at this point in the history
Add support for Anet N7 and future Anet printers in same format
  • Loading branch information
sn4k3 authored Jan 1, 2023
2 parents fd87a9a + ad0cfd7 commit acbc4cd
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 120 deletions.
42 changes: 42 additions & 0 deletions PrusaSlicer/printer/Anet N7.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# generated by PrusaSlicer 2.5.0+win64 on 2023-01-01 at 18:22:58 UTC
absolute_correction = 0
area_fill = 50
bed_custom_model =
bed_custom_texture =
bed_shape = 0x0,192x0,192x120,0x120
default_sla_material_profile = Prusa Orange Tough 0.05
default_sla_print_profile = 0.05 Normal
display_height = 120
display_mirror_x = 1
display_mirror_y = 0
display_orientation = landscape
display_pixels_x = 2560
display_pixels_y = 1600
display_width = 192
elefant_foot_compensation = 0.2
elefant_foot_min_width = 0.2
fast_tilt_time = 5
gamma_correction = 0
high_viscosity_tilt_time = 10
host_type = octoprint
inherits = Original Prusa SL1
max_exposure_time = 120
max_initial_exposure_time = 300
max_print_height = 300
min_exposure_time = 1
min_initial_exposure_time = 1
print_host =
printer_model = SL1
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_ANET\nPRINTER_MODEL_N7\nFILEFORMAT_N7\n\nSTART_CUSTOM_VALUES\nLiftHeight_6\nLiftSpeed_60\nEND_CUSTOM_VALUES
printer_settings_id =
printer_technology = SLA
printer_variant = default
printer_vendor =
printhost_apikey =
printhost_cafile =
relative_correction = 1,1
relative_correction_x = 1
relative_correction_y = 1
relative_correction_z = 1
slow_tilt_time = 8
thumbnails = 260x140
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ But also, I need victims for test subject. Proceed at your own risk!
- LGS4K (Longer Orange 4K & mono)
- Flashforge SVGX
- Anet N4
- Anet N7
- ZIP (Generic / Phrozen Zip)
- VDA.ZIP (Voxeldance Additive)
- VDT (Voxeldance Tango)
Expand Down
4 changes: 2 additions & 2 deletions UVtools.Core/Extensions/SizeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static string SizeSuffix(long value, byte decimalPlaces = 2)
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
public static bool HaveZero(this Size size) => size.Width <= 0 && size.Height <= 0;
public static bool HaveZero(this Size size) => size.Width <= 0 || size.Height <= 0;

/// <summary>
/// Exchange width with height
Expand All @@ -96,7 +96,7 @@ public static string SizeSuffix(long value, byte decimalPlaces = 2)
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
public static bool HaveZero(this SizeF size) => size.Width <= 0 && size.Height <= 0;
public static bool HaveZero(this SizeF size) => size.Width <= 0 || size.Height <= 0;

public static float Area(this SizeF size, int round = -1) => round >= 0 ? (float)Math.Round(size.Width * size.Height, round) : size.Width * size.Height;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using UVtools.Core.Converters;
using UVtools.Core.Extensions;
using UVtools.Core.Layers;
using UVtools.Core.Operations;
using UVtools.Core.Printer;

namespace UVtools.Core.FileFormats;

Expand All @@ -26,16 +28,23 @@ namespace UVtools.Core.FileFormats;
/// and added several new fields (as example, preview image).
/// Some of the format features are not recommended to use (BaseLayersCount and FilledBaseLayersCount).
/// </summary>
public sealed class AnetN4File : FileFormat
public sealed class AnetFile : FileFormat
{
#region Constants

public const ushort RESOLUTION_X = 1440;
public const ushort RESOLUTION_Y = 2560;
public const ushort RESOLUTION_N4_X = 1440;
public const ushort RESOLUTION_N4_Y = 2560;

public const float DISPLAY_WIDTH = 68.04f;
public const float DISPLAY_HEIGHT = 120.96f;
public const float MACHINE_Z = 135f;
public const float DISPLAY_N4_WIDTH = 68.04f;
public const float DISPLAY_N4_HEIGHT = 120.96f;
public const float MACHINE_N4_Z = 135f;

public const ushort RESOLUTION_N7_X = 2560;
public const ushort RESOLUTION_N7_Y = 1600;

public const float DISPLAY_N7_WIDTH = 192f;
public const float DISPLAY_N7_HEIGHT = 120f;
public const float MACHINE_N7_Z = 300f;

/// <summary>
/// Printer uses incorrect BMP header for preview image so we need to use it as-is instead of generating.
Expand All @@ -44,21 +53,21 @@ public sealed class AnetN4File : FileFormat

#endregion

#region Members
#region Enums

private uint _resolutionX = RESOLUTION_X;
private uint _resolutionY = RESOLUTION_Y;

private float _displayWidth = DISPLAY_WIDTH;
private float _displayHeight = DISPLAY_HEIGHT;
public enum AnetPrinter : byte
{
N4,
N7
}

#endregion

#region Sub Classes

#region Header

public class Header
public class AnetHeader
{
[FieldOrder(0)][FieldEndianness(Endianness.Big)] public int VersionLength { get; set; } = 2;
[FieldOrder(1)][FieldEncoding("UTF-16BE")][FieldLength(nameof(VersionLength))] public string Version { get; set; } = "3";
Expand Down Expand Up @@ -155,10 +164,11 @@ void SetBits(List<byte> data, uint pos, uint value, uint count = 1)
}
}

if (mat.Width != RESOLUTION_X || mat.Height != RESOLUTION_Y)
// Format does not have a global resolution field but supports multiple resolutions
/*if (mat.Width != RESOLUTION_X || mat.Height != RESOLUTION_Y)
{
throw new ArgumentException($"Anet N4 support only {RESOLUTION_X}x{RESOLUTION_Y} image, got {mat.Width}x{mat.Height}");
}
}*/

WhitePixelsCount = 0;
uint singleColorLength = 0;
Expand Down Expand Up @@ -205,7 +215,7 @@ void SetBits(List<byte> data, uint pos, uint value, uint count = 1)
return EncodedRle;
}

public Mat Decode(bool consumeRle = true)
public Mat Decode(out uint resolutionX, out uint resolutionY, bool consumeRle = true)
{
uint GetBits(uint pos, uint count = 1)
{
Expand All @@ -231,10 +241,10 @@ uint GetBits(uint pos, uint count = 1)
throw new IndexOutOfRangeException($"Incorrect RLE data size {EncodedRle.Length * 8}, except {BitsCount} bits.");
}

uint rleWidth = GetBits(0, 16);
uint rleHeight = GetBits(16, 16);
resolutionX = GetBits(0, 16);
resolutionY = GetBits(16, 16);

var mat = EmguExtensions.InitMat(new Size((int)rleWidth, (int)rleHeight));
var mat = EmguExtensions.InitMat(new Size((int)resolutionX, (int)resolutionY));
var imageLength = mat.GetLength();

byte brightness = (byte)((GetBits(32) == 1) ? 0xff : 0x0);
Expand All @@ -261,11 +271,15 @@ uint GetBits(uint pos, uint count = 1)

#region Properties

public Header HeaderSettings { get; private set; } = new();
public AnetHeader HeaderSettings { get; private set; } = new();

public override FileFormatType FileType => FileFormatType.Binary;

public override string ConvertMenuGroup => "Anet";

public override FileExtension[] FileExtensions { get; } = {
new(typeof(AnetN4File), "n4", "Anet N4"),
new(typeof(AnetFile), "n4", "Anet N4"),
new(typeof(AnetFile), "n7", "Anet N7"),
};

public override SpeedUnit FormatSpeedUnit => SpeedUnit.MillimetersPerSecond;
Expand All @@ -283,48 +297,6 @@ uint GetBits(uint pos, uint count = 1)

public override Size[]? ThumbnailsOriginalSize { get; } = { new(260, 140) };

public override uint ResolutionX
{
get => _resolutionX;
set
{
if (!RaiseAndSetIfChanged(ref _resolutionX, value)) return;
if(value != RESOLUTION_X) throw new ArgumentException($"Anet N4 support only {RESOLUTION_X}x{RESOLUTION_Y} image, got {ResolutionX}x{ResolutionY}");
HeaderSettings.XYPixelSize = PixelSizeMax;
}
}

public override uint ResolutionY
{
get => _resolutionY;
set
{
if (!RaiseAndSetIfChanged(ref _resolutionY, value)) return;
if (value != RESOLUTION_Y) throw new ArgumentException($"Anet N4 support only {RESOLUTION_X}x{RESOLUTION_Y} image, got {ResolutionX}x{ResolutionY}");
HeaderSettings.XYPixelSize = PixelSizeMax;
}
}

public override float DisplayWidth
{
get => _displayWidth;
set
{
if (!RaiseAndSetIfChanged(ref _displayWidth, value)) return;
HeaderSettings.XYPixelSize = PixelSizeMax;
}
}

public override float DisplayHeight
{
get => _displayHeight;
set
{
if (!RaiseAndSetIfChanged(ref _displayHeight, value)) return;
HeaderSettings.XYPixelSize = PixelSizeMax;
}
}

public override FlipDirection DisplayMirror
{
get => FlipDirection.Horizontally;
Expand Down Expand Up @@ -409,21 +381,53 @@ public override float MaterialMilliliters
}
}

public override string MachineName => "Anet N4";

public override object[] Configs => new object[] { HeaderSettings };

public AnetPrinter PrinterModel
{
get
{
if (FileEndsWith(".n4"))
{
return AnetPrinter.N4;
}

if (FileEndsWith(".n7"))
{
return AnetPrinter.N7;
}

return AnetPrinter.N4;
}
}

#endregion

#region Constructors
public AnetN4File()
{
MachineZ = MACHINE_Z;
}

public AnetFile() { }
#endregion

#region Methods

protected override void OnBeforeEncode(bool isPartialEncode)
{
switch (PrinterModel)
{
case AnetPrinter.N4:
if (ResolutionX != RESOLUTION_N4_X || ResolutionY != RESOLUTION_N4_Y)
throw new ArgumentException($"Anet N4 support only {RESOLUTION_N4_X}x{RESOLUTION_N4_Y} image, got {ResolutionX}x{ResolutionY}");
break;
case AnetPrinter.N7:
if (ResolutionX != RESOLUTION_N7_X || ResolutionY != RESOLUTION_N7_Y)
throw new ArgumentException($"Anet N7 support only {RESOLUTION_N7_X}x{RESOLUTION_N7_Y} image, got {ResolutionX}x{ResolutionY}");
break;
default:
throw new ArgumentOutOfRangeException(nameof(PrinterModel), FileExtension);
}
HeaderSettings.XYPixelSize = PixelSizeMax;
}

protected override void EncodeInternally(OperationProgress progress)
{
using var outputFile = new FileStream(TemporaryOutputFileFullPath, FileMode.Create, FileAccess.Write);
Expand Down Expand Up @@ -479,7 +483,7 @@ protected override void EncodeInternally(OperationProgress progress)
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(FileFullPath!, FileMode.Open, FileAccess.Read);
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
HeaderSettings = Helpers.Deserialize<AnetHeader>(inputFile);
if (HeaderSettings.Version is not "3")
{
throw new FileLoadException($"Not a valid N4 file: Version doesn't match, got {HeaderSettings.Version} instead of 3)", FileFullPath);
Expand Down Expand Up @@ -524,7 +528,24 @@ protected override void DecodeInternally(OperationProgress progress)
{
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
{
using var mat = layersDefinitions[layerIndex].Decode();
using var mat = layersDefinitions[layerIndex].Decode(out var resolutionX, out var resolutionY);
if (layerIndex == 0) // Set file resolution from first layer RLE. Figure out other properties after that
{
ResolutionX = resolutionX;
ResolutionY = resolutionY;

var machine = Machine.Machines.FirstOrDefault(machine =>
machine.Brand == PrinterBrand.Anet && machine.ResolutionX == resolutionX &&
machine.ResolutionY == resolutionY);

if (machine is not null)
{
DisplayWidth = machine.DisplayWidth;
DisplayHeight = machine.DisplayHeight;
MachineZ = machine.MachineZ;
MachineName = machine.Name;
}
}
_layers[layerIndex] = new Layer((uint)layerIndex, mat, this);
progress.LockAndIncrement();
});
Expand Down
Loading

0 comments on commit acbc4cd

Please sign in to comment.