Skip to content

Commit

Permalink
fix image writing
Browse files Browse the repository at this point in the history
  • Loading branch information
brettfo committed Dec 5, 2022
1 parent c4d4045 commit 71c9ca2
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 54 deletions.
Binary file added src/Examples/Images/arrow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 55 additions & 22 deletions src/Examples/TestExamples.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using System;
using System.IO;
using System.Runtime.CompilerServices;
using IxMilia.Dwg;
using IxMilia.Dwg.Objects;
using Xunit;
Expand Down Expand Up @@ -72,28 +75,58 @@ public void WriteCustomLineType()
}

[Fact]
public void WriteBlock()
{
var drawing = new DwgDrawing();
drawing.CurrentEntityLineType = drawing.ByLayerLineType;
drawing.FileHeader.Version = DwgVersionId.R14;

// create a block with a line from (0,0) to (1,1)
var line = new DwgLine(new DwgPoint(0.0, 0.0, 0.0), new DwgPoint(1.0, 1.0, 0.0));
line.Layer = drawing.CurrentLayer;

var blockHeader = DwgBlockHeader.CreateBlockRecordWithName("my-block", drawing.CurrentLayer);
blockHeader.Entities.Add(line);
drawing.BlockHeaders.Add(blockHeader);

// insert a copy of the block at location (3,3); the result is a line from (3,3) to (4,4)
var insert = new DwgInsert(blockHeader);
insert.Location = new DwgPoint(3.0, 3.0, 0.0);
insert.Layer = drawing.CurrentLayer;

drawing.ModelSpaceBlockRecord.Entities.Add(insert);

drawing.SaveExample();
public void WriteBlock()
{
var drawing = new DwgDrawing();
drawing.CurrentEntityLineType = drawing.ByLayerLineType;
drawing.FileHeader.Version = DwgVersionId.R14;

// create a block with a line from (0,0) to (1,1)
var line = new DwgLine(new DwgPoint(0.0, 0.0, 0.0), new DwgPoint(1.0, 1.0, 0.0));
line.Layer = drawing.CurrentLayer;

var blockHeader = DwgBlockHeader.CreateBlockRecordWithName("my-block", drawing.CurrentLayer);
blockHeader.Entities.Add(line);
drawing.BlockHeaders.Add(blockHeader);

// insert a copy of the block at location (3,3); the result is a line from (3,3) to (4,4)
var insert = new DwgInsert(blockHeader);
insert.Location = new DwgPoint(3.0, 3.0, 0.0);
insert.Layer = drawing.CurrentLayer;

drawing.ModelSpaceBlockRecord.Entities.Add(insert);

drawing.SaveExample();
}

[Fact]
public void WriteImage()
{
var drawing = new DwgDrawing();
drawing.FileHeader.Version = DwgVersionId.R14;

// create an image object
var fourtyFiveDegrees = Math.PI / 4.0;
var image = new DwgImage(
filePath: GetSampleImagePath(),
insertionPoint: new DwgPoint(2.0, 2.0, 0.0), // where the bottom left corner of the original image will be
widthInPixels: 16, // should be pulled directly from the image
heightInPixels: 16,
displayWidth: 1.0, // in drawing units
displayHeight: 1.0,
rotationAngleInRadians: fourtyFiveDegrees); // counter-clockwise rotation
image.Layer = drawing.CurrentLayer;
drawing.ModelSpaceBlockRecord.Entities.Add(image);

drawing.SaveExample();
}

private static string GetSampleImagePath([CallerFilePath] string testFilePath = null)
{
var thisDirectory = Path.GetDirectoryName(testFilePath);
var sampleImagesDirectory = Path.Combine(thisDirectory, "Images");
var sampleImagePath = Path.Combine(sampleImagesDirectory, "arrow.png");
return sampleImagePath;
}
}
}
11 changes: 8 additions & 3 deletions src/IxMilia.Dwg.Generator/Spec/Objects.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1282,7 +1282,7 @@
<Property Name="UVector" Type="DwgVector" BinaryType="3BD" DefaultValue="DwgVector.XAxis" ReadConverter="Converters.TripleVector({0})" WriteConverter="Converters.TripleVector({0})" />
<Property Name="VVector" Type="DwgVector" BinaryType="3BD" DefaultValue="DwgVector.YAxis" ReadConverter="Converters.TripleVector({0})" WriteConverter="Converters.TripleVector({0})" />
<Property Name="ImageSize" Type="DwgVector" BinaryType="2RD" DefaultValue="new DwgVector(1.0, 1.0, 0.0)" ReadConverter="Converters.DoubleVector({0})" WriteConverter="Converters.DoubleVector({0})" />
<Property Name="DisplayPropertyFlags" Type="int" BinaryType="BS" DefaultValue="0" WriteConverter="(short){0}">
<Property Name="DisplayPropertyFlags" Type="int" BinaryType="BS" DefaultValue="3" WriteConverter="(short){0}">
<Flag Name="ShowImage" Mask="1" />
<Flag Name="ShowImageWhenNotAlignedToScreen" Mask="2" />
<Flag Name="UseClippingBoundary" Mask="4" />
Expand Down Expand Up @@ -1314,14 +1314,19 @@
<Property Name="PixelWidth" Type="double" BinaryType="RD" DefaultValue="0.0" />
<Property Name="PixelHeight" Type="double" BinaryType="RD" DefaultValue="0.0" />
<ObjectSizeEnd />

<!-- handles -->
<Property Name="_parentHandleReference" Type="DwgHandleReference" BinaryType="H" DefaultValue="new DwgHandleReference(4, 0)" Accessibility="internal" />
<Property Name="_reactorHandleReferences" Type="DwgHandleReference" BinaryType="H" DefaultValue="new List&lt;DwgHandleReference&gt;()" SkipCreation="true" ReadCount="_reactorCount" />
<Property Name="_xDictionaryObjectHandleReference" Type="DwgHandleReference" BinaryType="H" DefaultValue="new DwgHandleReference(3, 0)" SkipCreation="true" />
</Object>
<!--
Image definition reactor
-->
<Object Name="ImageDefinitionReactor" Value="505" IsEntity="false" ClassName="IMAGEDEFREACTOR" CppClassName="AcDbRasterImageDefReactor">
<Property Name="ClassVersion" Type="int" BinaryType="BL" DefaultValue="0" />
<Object Name="ImageDefinitionReactor" Value="505" IsEntity="false" ClassName="IMAGEDEF_REACTOR" CppClassName="AcDbRasterImageDefReactor">
<Property Name="ClassVersion" Type="int" BinaryType="BL" DefaultValue="2" />
<ObjectSizeEnd />
</Object>
<!--
Expand Down
3 changes: 2 additions & 1 deletion src/IxMilia.Dwg.Test/RawObjectReadTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ private static DwgClassDefinition[] CommonClasses()
new DwgClassDefinition(0, 0, "", "", "RASTERVARIABLES", false, false),
null,
new DwgClassDefinition(0, 0, "", "", "IMAGEDEF", false, false),
new DwgClassDefinition(0, 0, "", "", "IMAGEDEFREACTOR", false, false),
new DwgClassDefinition(0, 0, "", "", "IMAGEDEF_REACTOR", false, false),
new DwgClassDefinition(0, 0, "", "", "IMAGE", false, false),
new DwgClassDefinition(0, 0, "", "", "IDBUFFER", false, false),
new DwgClassDefinition(0, 0, "", "", "LWPOLYLINE", false, false),
Expand Down Expand Up @@ -2250,6 +2250,7 @@ public void ReadRawImageDefinitionReactor()
0xA1, 0x13 // crc
);
Assert.Equal(new DwgHandle(0x6C), i.Handle);
Assert.Equal(2, i.ClassVersion);
}

[Fact]
Expand Down
44 changes: 27 additions & 17 deletions src/IxMilia.Dwg/DwgDrawing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -356,12 +356,12 @@ private void AssignHandles(DwgObjectMap objectMap)
objectMap.SetNextAvailableHandle(Variables);
}

private void AssignOwnershipHandles()
{
foreach (var lt in LineTypes.Values)
{
lt.LineTypeControlHandleReference = LineTypes.Handle.MakeHandleReference(DwgHandleReferenceCode.HardPointer);
}
private void AssignOwnershipHandles()
{
foreach (var lt in LineTypes.Values)
{
lt.LineTypeControlHandleReference = LineTypes.Handle.MakeHandleReference(DwgHandleReferenceCode.HardPointer);
}
}

private void EnsureObjectMemberships()
Expand Down Expand Up @@ -390,22 +390,32 @@ private void EnsureClasses()
var classNames = new HashSet<string>(Classes.Select(c => c.DxfClassName));
foreach (var entity in ModelSpaceBlockRecord.Entities)
{
var expectedClassName = DwgObjectTypeExtensions.ClassNameFromTypeCode(entity.Type);
if (expectedClassName is not null)
EnsureClassesFromObject(entity, classNames);
}
}

private void EnsureClassesFromObject(DwgObject obj, HashSet<string> seenClasses)
{
var expectedClassName = DwgObjectTypeExtensions.ClassNameFromTypeCode(obj.Type);
if (expectedClassName is not null)
{
if (!seenClasses.Contains(expectedClassName))
{
if (!classNames.Contains(expectedClassName))
var classDefinition = DwgObjectTypeExtensions.GetClassDefinitionForObjectType(obj.Type);
if (classDefinition is null)
{
var classDefinition = DwgObjectTypeExtensions.GetClassDefinitionForObjectType(entity.Type);
if (classDefinition is null)
{
throw new InvalidOperationException($"Unable to create class definition for object type {entity.Type}.");
}

Classes.Add(classDefinition);
classNames.Add(expectedClassName);
throw new InvalidOperationException($"Unable to create class definition for object type {obj.Type}.");
}

Classes.Add(classDefinition);
seenClasses.Add(expectedClassName);
}
}

foreach (var child in obj.ChildItems)
{
EnsureClassesFromObject(child, seenClasses);
}
}

private static void EnsureCollectionContains<TKey, TValue>(IDictionary<TKey, TValue> collection, string collectionName, params Tuple<TValue, string>[] items)
Expand Down
2 changes: 1 addition & 1 deletion src/IxMilia.Dwg/Objects/DwgBlockHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ internal override void OnBeforeObjectWrite(DwgVersionId version)
}
else
{
var flatList = DwgEntityHelpers.FlattenAndAssignPointersForWrite(Entities);
var flatList = DwgEntityHelpers.FlattenAndAssignPointersForWrite(Entities).OfType<DwgEntity>().ToArray();
foreach (var entity in Entities)
{
AssignEntityMode(entity);
Expand Down
20 changes: 10 additions & 10 deletions src/IxMilia.Dwg/Objects/DwgEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ internal override void ReadCommonDataEnd(BitReader reader)
LineTypeHandleReference = reader.Read_H();
}

if (_noLinks)
{
PreviousEntityHandle = new DwgHandleReference(DwgHandleReferenceCode.HandleMinus1, 0);
NextEntityHandle = new DwgHandleReference(DwgHandleReferenceCode.HandlePlus1, 0);
if (_noLinks)
{
PreviousEntityHandle = new DwgHandleReference(DwgHandleReferenceCode.HandleMinus1, 0);
NextEntityHandle = new DwgHandleReference(DwgHandleReferenceCode.HandlePlus1, 0);
}
else
{
Expand Down Expand Up @@ -193,12 +193,12 @@ internal override void OnAfterObjectRead(BitReader reader, DwgObjectCache object
OnAfterEntityRead(reader, objectCache, version);
}

internal void AssignSubentityReference(DwgHandle ownerHandle)
{
if (_entityMode == 0)
{
_subentityRef = ownerHandle.MakeHandleReference(DwgHandleReferenceCode.HardPointer);
}
internal void AssignSubentityReference(DwgHandle ownerHandle)
{
if (_entityMode == 0)
{
_subentityRef = ownerHandle.MakeHandleReference(DwgHandleReferenceCode.HardPointer);
}
}
}
}
36 changes: 36 additions & 0 deletions src/IxMilia.Dwg/Objects/DwgImage.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using System;
using System.Collections.Generic;

namespace IxMilia.Dwg.Objects
{
public partial class DwgImage
Expand All @@ -9,6 +12,36 @@ public partial class DwgImage

public DwgImageDefinitionReactor ImageDefinitionReactor { get; set; } = new DwgImageDefinitionReactor();

public DwgImage(string filePath, DwgPoint insertionPoint, int widthInPixels, int heightInPixels, double displayWidth, double displayHeight, double rotationAngleInRadians = 0.0)
: this()
{
ImageDefinition.FilePath = filePath;
ImageDefinition.ImageWidth = widthInPixels;
ImageDefinition.ImageHeight = heightInPixels;
ImageDefinition.PixelWidth = widthInPixels;
ImageDefinition.PixelHeight = heightInPixels;
ImageSize = new DwgVector(widthInPixels, heightInPixels, 0.0);
InsertionPoint = insertionPoint;

var uVectorLength = widthInPixels / displayWidth;
var vVectorLength = heightInPixels / displayHeight;

var sin = Math.Sin(rotationAngleInRadians);
var cos = Math.Cos(rotationAngleInRadians);

UVector = new DwgVector(cos / uVectorLength, sin / uVectorLength, 0.0);
VVector = new DwgVector(-sin / vVectorLength, cos / vVectorLength, 0.0);
}

internal override IEnumerable<DwgObject> ChildItems
{
get
{
yield return ImageDefinition;
yield return ImageDefinitionReactor;
}
}

internal override void ReadPostData(BitReader reader, DwgVersionId version)
{
_imageDefHandleReference = reader.Read_H();
Expand All @@ -34,6 +67,9 @@ internal override void OnBeforeEntityWrite(DwgVersionId version)
{
_imageDefHandleReference = ImageDefinition.MakeHandleReference(DwgHandleReferenceCode.SoftOwner);
_imageDefReactorHandleReference = ImageDefinitionReactor.MakeHandleReference(DwgHandleReferenceCode.SoftPointer);

ImageDefinition._reactorHandleReferences.Clear();
ImageDefinition._reactorHandleReferences.Add(ImageDefinitionReactor.MakeHandleReference(DwgHandleReferenceCode.HardPointer));
}

internal override void WritePostData(BitWriter writer, DwgVersionId version)
Expand Down

0 comments on commit 71c9ca2

Please sign in to comment.