Author Topic: NET and COM with AcCmColor, almost one is wrong...  (Read 4139 times)

0 Members and 1 Guest are viewing this topic.

gile

  • Gator
  • Posts: 2520
  • Marseille, France
NET and COM with AcCmColor, almost one is wrong...
« on: October 09, 2011, 04:18:32 PM »
Hi

I noticed a strange thing while converting an index (ACI) color to RGB: using NET or COM objects do not return the same result.
The NET object seems to return the right RGB result.
Doing the reverse process (from RGB to ACI) both objects return the same output from the same input, but, using the NET RGB result do not return the same ACI.

This little piece of code returns the following result:

Code: [Select]
using System.Reflection;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace ColorUtils
{
    public class TestCommand
    {
        [CommandMethod("test")]
        public void Test()
        {
            Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;

            // using .NET
            Color color = Color.FromColorIndex(ColorMethod.ByAci, 123);
            ed.WriteMessage("\nNET: RGB from 123 color index: Red = {0}, Green = {1}, Blue = {2}",
                color.ColorValue.R,
                color.ColorValue.G,
                color.ColorValue.B);

            // using COM
            object acadAp = AcAp.AcadApplication;
            object objColor = LateBinding.Invoke(acadAp, "GetInterfaceObject", "AutoCAD.AcCmColor.18");
            LateBinding.Set(objColor, "ColorIndex", 123);
            ed.WriteMessage("\nCOM: RGB from 123 color index: Red = {0}, Green = {1}, Blue = {2}",
                LateBinding.Get(objColor, "Red"),
                LateBinding.Get(objColor, "Green"),
                LateBinding.Get(objColor, "Blue"));

            // using .NET
            color = Color.FromRgb(82, 165, 145);
            ed.WriteMessage("\nNET: ACI from NET RGB result = {0};", color.ColorIndex);

            // using COM
            LateBinding.Invoke(objColor, "SetRGB", 82, 165, 145);
            ed.WriteMessage("\nCOM: ACI from NET RGB result = {0}", LateBinding.Get(objColor, "ColorIndex"));

            // using .NET
            color = Color.FromRgb(102, 204, 178);
            ed.WriteMessage("\nNET: ACI from COM RGB result = {0};", color.ColorIndex);

            // using COM
            LateBinding.Invoke(objColor, "SetRGB", 102, 204, 178);
            ed.WriteMessage("\nCOM: ACI from COM RGB result = {0}", LateBinding.Get(objColor, "ColorIndex"));
        }
    }

    public static class LateBinding
    {
        public static object Get(object obj, string propName, params object[] parameter)
        {
            return obj.GetType().InvokeMember(propName, BindingFlags.GetProperty, null, obj, parameter);
        }

        public static void Set(object obj, string propName, params object[] parameter)
        {
            obj.GetType().InvokeMember(propName, BindingFlags.SetProperty, null, obj, parameter);
        }

        public static object Invoke(object obj, string methName, params object[] parameter)
        {
            return obj.GetType().InvokeMember(methName, BindingFlags.InvokeMethod, null, obj, parameter);
        }
    }
}

Quote
NET: RGB from 123 color index: Red = 82, Green = 165, Blue = 145
COM: RGB from 123 color index: Red = 102, Green = 204, Blue = 178
NET: ACI from NET RGB result = 135;
COM: ACI from NET RGB result = 135
NET: ACI from COM RGB result = 123;
COM: ACI from COM RGB result = 123

Speaking English as a French Frog

LE3

  • Guest
Re: NET and COM with AcCmColor, almost one is wrong...
« Reply #1 on: October 09, 2011, 04:50:41 PM »
Hi Gile,

Have not played with autocad stuff for a while now, but recall using in one of my c# routines this:
Code: [Select]
extern "C" __declspec(dllexport)
void GetRGB (long aciColor, long *Red, long *Green, long *Blue)
{
unsigned long rgb = acedGetRGB(aciColor);
*Red   = GetRValue(rgb);
*Green = GetGValue(rgb);
*Blue  = GetBValue(rgb);
}
Code: [Select]
        // ARX signature:
        //void GetRGB (long aciColor, long *Red, long *Green, long *Blue);
        [DllImport(GBPOLY_ARX, CharSet = CharSet.Unicode, EntryPoint = "GetRGB")]
        public static extern void getRGB ( int aciColor, out int red, out int green, out int blue );
Code: [Select]
                        // color is by index - we need RGB conversion
                        if (colorHatch.IsByAci)
                        {
                            int red = new int();
                            int green = new int();
                            int blue = new int();
                            PInvoke.getRGB((int)colorHatch.ColorIndex, out red, out green, out blue);

                            Autodesk.AutoCAD.Colors.Color _colorHatch = new Autodesk.AutoCAD.Colors.Color();
                            _colorHatch = Autodesk.AutoCAD.Colors.Color.FromRgb(Convert.ToByte(red), Convert.ToByte(green), Convert.ToByte(blue));

                            colorHatch = _colorHatch;
                        }

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: NET and COM with AcCmColor, almost one is wrong...
« Reply #2 on: October 09, 2011, 08:29:29 PM »

Can't make  time to play gile, but was reminded of this : (ColorLab )
Code and style is a little dated   :)

http://www.theswamp.org/index.php?topic=14977.msg181469#msg181469

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Re: NET and COM with AcCmColor, almost one is wrong...
« Reply #3 on: October 10, 2011, 02:05:20 AM »
Thank you both.

So, using EntityColor returns the same result as the COM route.
But why is this result different from value returned by the Color.ColorValue wich seems to be more accurate (as shown in the picture) ?
Speaking English as a French Frog