ACadSharp icon indicating copy to clipboard operation
ACadSharp copied to clipboard

DXF writer needs methods to write colors

Open mme1950 opened this issue 1 year ago • 5 comments

IDxfStreamWriter has no dedicated methods to write CM and EN colors. The interface should be extended and the implementation should be added.

mme1950 avatar Apr 02 '24 06:04 mme1950

I've been looking at this particular issue and it seems that DXF does not support true colors when these are saved by a different code than 420 like, DimensionStyle.DimensionLineColor which is saved with code 176.

To do this test I've saved the file in color_samples as a DXF and manually checked the values stored:

image

As the image shows the true color has been stored as the closest index color instead of the true color value.

DomCR avatar Apr 05 '24 16:04 DomCR

In the DimensionStyle Object colors are documented with type BS. So this cannot be a true color. An alternative group code for a true color value such as 420 is not specified. But the group-code pair 62/420 seems to be typical for an EN color, dosn't it?

Colors in MultiLeader and MultiLeaderStyle are BLs, thus can store true colors. see Example in #323.

But we have this 0xC000000 value that does not fit into the scheme.

mme1950 avatar Apr 08 '24 09:04 mme1950

Hi @DomCR ,

please look at this DXF fragment. The colors BS 176 and BS 177 from DimensionStyle are overridden by extended data in the Dimension object (Acad_TC, DSTYLE_TC).

So obviously DimensionStyle does not support true colors, but Dimension does via extended data. The data structures seem to be the same in DWG.

  0
DIMENSION
  5
2BC
330
1F
100
AcDbEntity
  8
0
100
AcDbDimension
280
     0
  2
*D1
 10
145.8763549700604
 20
162.4105217066659
 30
0.0
 11
109.3947382726832
 21
132.3438146722331
 31
0.0
 70
    33
 71
     5
 42
94.45399835668737
 73
     0
 74
     0
 75
     0
  3
ISO-25
100
AcDbAlignedDimension
 13
86.53582406359419
 23
87.18638064426068
 33
0.0
 14
156.6480200168462
 24
150.4780687571392
 34
0.0
1001
ACAD
1000
DSTYLE
1002
{
1070
   177
1070
   215
1070
   176
1070
    82
1002
}
1001
Acad_TC
1000
DSTYLE_TC
1002
{
1070
   177
1004
1800000002000000985CA3C2000000000000000000000000
1070
   176
1004
18000000020000001FE028C2000000000000000000000000
1002
}
  0

mme1950 avatar Apr 08 '24 13:04 mme1950

You are right, I need to take an extensive look on how can we link all this data to the data that is stored in the CadDocument.

DomCR avatar Apr 09 '24 08:04 DomCR

I think, in DXF we have these cases (hopefully this is all ??):

  • EN colors, using different group codes for index colors, true colors, and color names
  • CM colors with BS group codes that do not support true colors
  • CM colors with BL group codes that support index colors, true colors,
  • and the strange 0xC0000000 value

I did not find anything about color names and color books for CM colors in the DXF documentation.

Writing extended data is a different story.

mme1950 avatar Apr 09 '24 12:04 mme1950

Hi @DomCR,

what do you think of this approach writing CM-colors in DXF?

		public void WriteCmColor(int code, Color color, DxfClassMap map = null)
		{
			if (GroupCodeValue.TransformValue(code) == GroupCodeValueType.Int16) {
				//BS: Color Index
				this.Write(code, Convert.ToInt16(color.GetApproxIndex()));
			}
			else {
				byte[] arr = new byte[4];

				if (color.IsTrueColor) {
					arr[0] = (byte)color.B;
					arr[1] = (byte)color.G;
					arr[2] = (byte)color.R;
					arr[3] = 0b1100_0010;	//	0xC2
				}
				else {
					arr[3] = 0b1100_0001;
					arr[0] = (byte)color.Index;
				}

				//BL: RGB value
				this.Write(code, LittleEndianConverter.Instance.ToInt32(arr), map);
			}
		}

But I still do not understand what the special value 0xC0000000 means and how it is to be reflected in the Color object.

mme1950 avatar May 02 '24 05:05 mme1950

Hi @mme1950,

It looks good! your implementation will avoid the Exception when writing the wrong types for GroupCodeValueType. For me we can use this one to write the colors in extended data.

About the 0xC0000000 I don't know how it works either, sorry but I didn't had much time lately to look at this, if you implement something that works and it can be verified I'll merge your PR.

DomCR avatar May 03 '24 08:05 DomCR

Hi @DomCR, ... sorry but I didn't had much time lately to look at this ... don't worry - we are also quite busy in another project.

This implementation to write colors in DXF seems to be OK for most of the cases, except 0xC0000000. I suspect this value has a special meaning that should be reflected by some property of the Color object. This means we have to handle this case explicitly when we read the color and when we write it.

More generally: byte 3 can have the values 0xC0, 0xC2, 0xC3. Assuming that the bit 0 distinguishes index color and true color, we do not know the meaning of bit 1 and C.

OK - lets postpone this question. I open a PR.

mme1950 avatar May 03 '24 09:05 mme1950

... For me we can use this one to write the colors in extended data. ...

An object that reads BS color properties (e. g. DimensionStyle) has respective Color properties, that must not receive true-color values. The Dimension entity does not have any Color property. To set a true color, e.g. for the dimension line extended data have to added in any case. The create extended data in the proper format we should use a dedicated infrastructure. But this is a different story.

mme1950 avatar May 03 '24 09:05 mme1950