Ejemplo n.º 1
0
static PyObject *
cms_get_display_profile_win32(PyObject* self, PyObject* args)
{
    char filename[MAX_PATH];
    DWORD filename_size;
    BOOL ok;

    int handle = 0;
    int is_dc = 0;
    if (!PyArg_ParseTuple(args, "|ii:get_display_profile", &handle, &is_dc))
        return NULL;

    filename_size = sizeof(filename);

    if (is_dc) {
        ok = GetICMProfile((HDC) handle, &filename_size, filename);
    } else {
        HDC dc = GetDC((HWND) handle);
        ok = GetICMProfile(dc, &filename_size, filename);
        ReleaseDC((HWND) handle, dc);
    }

    if (ok)
        return PyString_FromStringAndSize(filename, filename_size-1);

    Py_INCREF(Py_None);
    return Py_None;
}
Ejemplo n.º 2
0
 // retrieve monitor profile from Windows
 // TODO: support for multi-monitor setups
 void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
 {
     // look up monitor profile in system
     HDC hdc = GetDC(NULL);
     if (hdc)
     {
         wxChar filename[MAX_PATH];
         DWORD len;
         if (GetICMProfile(hdc, &len, filename))
         {
             profileName = filename;
             profile = cmsOpenProfileFromFile(profileName.c_str(), "r");
         };
         ReleaseDC(NULL, hdc);
     };
 };
Ejemplo n.º 3
0
int main(int argc, char** argv) {
#if defined(SK_BUILD_FOR_MAC)
    CGColorSpaceRef cs = CGDisplayCopyColorSpace(CGMainDisplayID());
    CFDataRef dataRef = CGColorSpaceCopyICCProfile(cs);
    const uint8_t* data = CFDataGetBytePtr(dataRef);
    size_t size = CFDataGetLength(dataRef);
    
    SkFILEWStream file("monitor_0.icc");
    file.write(data, size);
    
    CFRelease(cs);
    CFRelease(dataRef);
    return 0;
#elif defined(SK_BUILD_FOR_WIN)
    DISPLAY_DEVICE dd = { sizeof(DISPLAY_DEVICE) };
    SkString outputFilename;

    // Chrome's code for this currently just gets the primary monitor's profile. This code iterates
    // over all attached monitors, so it's "better" in that sense. Making intelligent use of this
    // information (via things like MonitorFromWindow or MonitorFromRect to pick the correct
    // profile for a particular window or region of a window), is an exercise left to the reader.
    for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) {
        if (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {
            // There are other helpful things in dd at this point:
            // dd.DeviceString has a longer name for the adapter
            // dd.StateFlags indicates primary display, mirroring, etc...
            HDC dc = CreateDC(NULL, dd.DeviceName, NULL, NULL);
            if (dc) {
                char icmPath[MAX_PATH + 1];
                DWORD pathLength = MAX_PATH;
                if (GetICMProfile(dc, &pathLength, icmPath)) {
                    // GetICMProfile just returns the path to the installed profile (not the data)
                    outputFilename = SkStringPrintf("monitor_%d.icc", i);
                    CopyFile(icmPath, outputFilename.c_str(), FALSE);
                }
                DeleteDC(dc);
            }
        }
    }

    return 0;
#else
    SkDebugf("ERROR: Unsupported platform\n");
    return 1;
#endif
}
Ejemplo n.º 4
0
GimpColorProfile *
gimp_widget_get_color_profile (GtkWidget *widget)
{
    GimpColorProfile *profile = NULL;
    GdkScreen        *screen;
    gint              monitor;

    g_return_val_if_fail (widget == NULL || GTK_IS_WIDGET (widget), NULL);

    if (widget)
    {
        screen  = gtk_widget_get_screen (widget);
        monitor = gimp_widget_get_monitor (widget);
    }
    else
    {
        screen  = gdk_screen_get_default ();
        monitor = 0;
    }

#if defined GDK_WINDOWING_X11
    {
        GdkAtom  type    = GDK_NONE;
        gint     format  = 0;
        gint     nitems  = 0;
        gchar   *atom_name;
        guchar  *data    = NULL;

        if (monitor > 0)
            atom_name = g_strdup_printf ("_ICC_PROFILE_%d", monitor);
        else
            atom_name = g_strdup ("_ICC_PROFILE");

        if (gdk_property_get (gdk_screen_get_root_window (screen),
                              gdk_atom_intern (atom_name, FALSE),
                              GDK_NONE,
                              0, 64 * 1024 * 1024, FALSE,
                              &type, &format, &nitems, &data) && nitems > 0)
        {
            profile = gimp_color_profile_new_from_icc_profile (data, nitems,
                      NULL);
            g_free (data);
        }

        g_free (atom_name);
    }
#elif defined GDK_WINDOWING_QUARTZ
    {
        CMProfileRef prof = NULL;

        CMGetProfileByAVID (monitor, &prof);

        if (prof)
        {
            CFDataRef data;

            data = CMProfileCopyICCData (NULL, prof);
            CMCloseProfile (prof);

            if (data)
            {
                UInt8 *buffer = g_malloc (CFDataGetLength (data));

                /* We cannot use CFDataGetBytesPtr(), because that returns
                 * a const pointer where cmsOpenProfileFromMem wants a
                 * non-const pointer.
                 */
                CFDataGetBytes (data, CFRangeMake (0, CFDataGetLength (data)),
                                buffer);

                profile = gimp_color_profile_new_from_icc_profile (data,
                          CFDataGetLength (data),
                          NULL);

                g_free (buffer);
                CFRelease (data);
            }
        }
    }
#elif defined G_OS_WIN32
    {
        HDC hdc = GetDC (NULL);

        if (hdc)
        {
            gchar  *path;
            gint32  len = 0;

            GetICMProfile (hdc, &len, NULL);
            path = g_new (gchar, len);

            if (GetICMProfile (hdc, &len, path))
            {
                GFile *file = g_file_new_for_path (path);

                profile = gimp_color_profile_new_from_file (file, NULL);
                g_object_unref (file);
            }

            g_free (path);
            ReleaseDC (NULL, hdc);
        }
    }
#endif

    return profile;
}
Ejemplo n.º 5
0
// Get the display ICC profile of the monitor associated with the widget.
// For X display, uses the ICC profile specifications version 0.2 from
// http://burtonini.com/blog/computers/xicc
// Based on code from Gimp's modules/cdisplay_lcms.c
void dt_ctl_set_display_profile()
{
  if(!dt_control_running()) return;
  // make sure that no one gets a broken profile
  // FIXME: benchmark if the try is really needed when moving/resizing the window. Maybe we can just lock it and block
  if(pthread_rwlock_trywrlock(&darktable.control->xprofile_lock))
    return; // we are already updating the profile. Or someone is reading right now. Too bad we can't distinguish that. Whatever ...

  GtkWidget *widget = dt_ui_center(darktable.gui->ui);
  guint8 *buffer = NULL;
  gint buffer_size = 0;
  gchar *profile_source = NULL;

#if defined GDK_WINDOWING_X11

  // we will use the xatom no matter what configured when compiled without colord
  gboolean use_xatom = TRUE;
#if defined USE_COLORDGTK
  gboolean use_colord = TRUE;
  gchar *display_profile_source = dt_conf_get_string("ui_last/display_profile_source");
  if(display_profile_source)
  {
    if(!strcmp(display_profile_source, "xatom"))
      use_colord = FALSE;
    else if(!strcmp(display_profile_source, "colord"))
      use_xatom = FALSE;
    g_free(display_profile_source);
  }
#endif

  /* let's have a look at the xatom, just in case ... */
  if(use_xatom)
  {
    GdkScreen *screen = gtk_widget_get_screen(widget);
    if ( screen==NULL )
      screen = gdk_screen_get_default();
    int monitor = gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window(widget));
    char *atom_name;
    if (monitor > 0)
      atom_name = g_strdup_printf("_ICC_PROFILE_%d", monitor);
    else
      atom_name = g_strdup("_ICC_PROFILE");

    profile_source = g_strdup_printf("xatom %s", atom_name);

    GdkAtom type = GDK_NONE;
    gint format = 0;
    gdk_property_get(gdk_screen_get_root_window(screen),
                    gdk_atom_intern(atom_name, FALSE), GDK_NONE,
                    0, 64 * 1024 * 1024, FALSE,
                    &type, &format, &buffer_size, &buffer);
    g_free(atom_name);
  }

#ifdef USE_COLORDGTK
  /* also try to get the profile from colord. this will set the value asynchronously! */
  if(use_colord)
  {
    CdWindow *window = cd_window_new();
    GtkWidget *center_widget = dt_ui_center(darktable.gui->ui);
    cd_window_get_profile(window, center_widget, NULL, dt_ctl_get_display_profile_colord_callback, NULL);
  }
#endif

#elif defined GDK_WINDOWING_QUARTZ
  GdkScreen *screen = gtk_widget_get_screen(widget);
  if ( screen==NULL )
    screen = gdk_screen_get_default();
  int monitor = gdk_screen_get_monitor_at_window(screen, gtk_widget_get_window(widget));

  CGDirectDisplayID ids[monitor + 1];
  uint32_t total_ids;
  CMProfileRef prof = NULL;
  if(CGGetOnlineDisplayList(monitor + 1, &ids[0], &total_ids) == kCGErrorSuccess && total_ids == monitor + 1)
    CMGetProfileByAVID(ids[monitor], &prof);
  if ( prof!=NULL )
  {
    CFDataRef data;
    data = CMProfileCopyICCData(NULL, prof);
    CMCloseProfile(prof);

    UInt8 *tmp_buffer = (UInt8 *) g_malloc(CFDataGetLength(data));
    CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), tmp_buffer);

    buffer = (guint8 *) tmp_buffer;
    buffer_size = CFDataGetLength(data);

    CFRelease(data);
  }
  profile_source = g_strdup("osx color profile api");
#elif defined G_OS_WIN32
  (void)widget;
  HDC hdc = GetDC (NULL);
  if ( hdc!=NULL )
  {
    DWORD len = 0;
    GetICMProfile (hdc, &len, NULL);
    gchar *path = g_new (gchar, len);

    if (GetICMProfile (hdc, &len, path))
    {
      gsize size;
      g_file_get_contents(path, (gchar**)&buffer, &size, NULL);
      buffer_size = size;
    }
    g_free (path);
    ReleaseDC (NULL, hdc);
  }
  profile_source = g_strdup("windows color profile api");
#endif

  int profile_changed = buffer_size > 0 &&
                        (darktable.control->xprofile_size != buffer_size || memcmp(darktable.control->xprofile_data, buffer, buffer_size) != 0);
  if(profile_changed)
  {
    cmsHPROFILE profile = NULL;
    char name[512];
    // thanks to ufraw for this!
    g_free(darktable.control->xprofile_data);
    darktable.control->xprofile_data = buffer;
    darktable.control->xprofile_size = buffer_size;
    profile = cmsOpenProfileFromMem(buffer, buffer_size);
    if(profile)
    {
      dt_colorspaces_get_profile_name(profile, "en", "US", name, sizeof(name));
      cmsCloseProfile(profile);
    }
    dt_print(DT_DEBUG_CONTROL, "[color profile] we got a new screen profile `%s' from the %s (size: %d)\n", *name?name:"(unknown)", profile_source, buffer_size);
  }
  pthread_rwlock_unlock(&darktable.control->xprofile_lock);
  if(profile_changed)
    dt_control_signal_raise(darktable.signals, DT_SIGNAL_CONTROL_PROFILE_CHANGED);
  g_free(profile_source);
}
Ejemplo n.º 6
0
static cmsHPROFILE
cdisplay_lcms_get_display_profile (CdisplayLcms *lcms)
{
  GimpColorConfig *config;
  cmsHPROFILE      profile = NULL;

  config = gimp_color_display_get_config (GIMP_COLOR_DISPLAY (lcms));

#if defined GDK_WINDOWING_X11
  if (config->display_profile_from_gdk)
    {
      GdkScreen *screen;
      GdkAtom    type    = GDK_NONE;
      gint       format  = 0;
      gint       nitems  = 0;
      gint       monitor = 0;
      gchar     *atom_name;
      guchar    *data    = NULL;

      screen = cdisplay_lcms_get_screen (lcms, &monitor);

      if (monitor > 0)
        atom_name = g_strdup_printf ("_ICC_PROFILE_%d", monitor);
      else
        atom_name = g_strdup ("_ICC_PROFILE");

      if (gdk_property_get (gdk_screen_get_root_window (screen),
                            gdk_atom_intern (atom_name, FALSE),
                            GDK_NONE,
                            0, 64 * 1024 * 1024, FALSE,
                            &type, &format, &nitems, &data) && nitems > 0)
        {
          profile = cmsOpenProfileFromMem (data, nitems);
          g_free (data);
        }

      g_free (atom_name);
    }

#elif defined GDK_WINDOWING_QUARTZ
  if (config->display_profile_from_gdk)
    {
      CMProfileRef  prof    = NULL;
      gint          monitor = 0;

      cdisplay_lcms_get_screen (lcms, &monitor);

      CMGetProfileByAVID (monitor, &prof);

      if (prof)
        {
          CFDataRef data;

          data = CMProfileCopyICCData (NULL, prof);
          CMCloseProfile (prof);

          if (data)
            {
              UInt8 *buffer = g_malloc (CFDataGetLength (data));

              /* We cannot use CFDataGetBytesPtr(), because that returns
               * a const pointer where cmsOpenProfileFromMem wants a
               * non-const pointer.
               */
              CFDataGetBytes (data, CFRangeMake (0, CFDataGetLength (data)),
                              buffer);

              profile = cmsOpenProfileFromMem (buffer, CFDataGetLength (data));

              g_free (buffer);
              CFRelease (data);
            }
        }
    }

#elif defined G_OS_WIN32
  if (config->display_profile_from_gdk)
    {
      HDC hdc = GetDC (NULL);

      if (hdc)
        {
          gchar *path;
          gint32 len = 0;

          GetICMProfile (hdc, &len, NULL);
          path = g_new (gchar, len);

          if (GetICMProfile (hdc, &len, path))
            profile = cmsOpenProfileFromFile (path, "r");

          g_free (path);
          ReleaseDC (NULL, hdc);
        }
    }
#endif

  if (! profile && config->display_profile)
    profile = cmsOpenProfileFromFile (config->display_profile, "r");

  return profile;
}
Ejemplo n.º 7
0
void KDCAttributes::DumpDC(HDC hDC)
{
	POINT pnt;
	SIZE  size;

	m_List.DeleteAll();

	Add(_T("Technology"),  _T("%d"), GetDeviceCaps(hDC, TECHNOLOGY));
	Add(_T("width"),	   _T("%d"), GetDeviceCaps(hDC, HORZRES));
	Add(_T("height"),	   _T("%d"), GetDeviceCaps(hDC, VERTRES));

	GetDCOrgEx(hDC, & pnt); 
	Add(_T("DC Origin"), _T("{ %d, %d }"), pnt.x, pnt.y);

	TCHAR szTitle[MAX_PATH];

	szTitle[0] = 0;

	GetWindowText(WindowFromDC(hDC), szTitle, MAX_PATH);
	Add(_T("Window"),    _T("0x%X \"%s\""), WindowFromDC(hDC), szTitle);

	Add(_T("Bitmap"),        _T("0x%X"), GetCurrentObject(hDC, OBJ_BITMAP));

	Add(_T("Graphics Mode"), _T("%d"), GetGraphicsMode(hDC));
	Add(_T("Mapping Mode"),  _T("%d"), GetMapMode(hDC));

	GetViewportExtEx(hDC, & size);
	Add(_T("Viewport Extent"), _T("{ %d, %d }"), size.cx, size.cy);
	
	GetViewportOrgEx(hDC, & pnt);
	Add(_T("Viewport Origin"), _T("{ %d, %d }"), pnt.x, pnt.y);

	GetWindowExtEx(hDC, & size);
	Add(_T("Window Extent"), _T("{ %d, %d }"), size.cx, size.cy);
	
	GetWindowOrgEx(hDC, & pnt);
	Add(_T("Window Origin"), _T("{ %d, %d }"), pnt.x, pnt.y);

	XFORM xform;
	GetWorldTransform(hDC, & xform);

	Add(_T("World transformation"), _T("{ %f, %f, %f, %f, %f, %f }"),
		xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);

	// transformation

	Add(_T("Background Color"), _T("0x%X"), GetBkColor(hDC));
	Add(_T("Text Color"),       _T("0x%X"), GetTextColor(hDC));
	Add(_T("Palette"),          _T("0x%X"), GetCurrentObject(hDC, OBJ_PAL));

	{
		COLORADJUSTMENT ca;
		GetColorAdjustment(hDC, & ca);
	
		Add(_T("Color Adjustment"), _T("{ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d }"), 
			ca.caSize, ca.caFlags, ca.caIlluminantIndex,
			ca.caRedGamma, ca.caGreenGamma, ca.caBlueGamma, 
			ca.caReferenceBlack, ca.caReferenceWhite,
			ca.caContrast, ca.caBrightness, ca.caColorfulness, ca.caRedGreenTint);
	}

	Add(_T("Color Space"), _T("0x%X"), GetColorSpace(hDC));
	Add(_T("ICM Mode"),    _T("%d"),   SetICMMode(hDC, ICM_QUERY));

	{
		TCHAR szProfile[MAX_PATH];
		DWORD dwSize = MAX_PATH;

		szProfile[0] = 0;
		GetICMProfile(hDC, & dwSize, szProfile);

		Add(_T("ICM Profile"), _T("%s"), szProfile);
	}

	GetCurrentPositionEx(hDC, & pnt);
	Add(_T("Current Position"), _T("{ %d, %d }"), pnt.x, pnt.y);

	Add(_T("ROP2"),				_T("%d"),	GetROP2(hDC));
	Add(_T("Background Mode"),	_T("%d"),	GetBkMode(hDC));
	Add(_T("Logical Pen"),		_T("0x%X"), GetCurrentObject(hDC, OBJ_PEN));
	Add(_T("DC Pen Color"),     _T("0x%X"), GetDCPenColor(hDC));
	Add(_T("Arc Direction"),	_T("%d"),	GetArcDirection(hDC));

	FLOAT miter;
	GetMiterLimit(hDC, & miter);

	Add(_T("Miter Limit"),		_T("%f"),	miter);
	
	Add(_T("Logical Brush"),    _T("0x%X"), GetCurrentObject(hDC, OBJ_BRUSH));
	Add(_T("DC Brush Color"),   _T("0x%X"), GetDCBrushColor(hDC));

	GetBrushOrgEx(hDC, & pnt);
	Add(_T("Brush Origin"),     _T("{ %d, %d }"), pnt.x, pnt.y);

	Add(_T("Polygon Filling Mode"),   _T("%d"), GetPolyFillMode(hDC));
	Add(_T("Bitmap Stretching Mode"), _T("%d"), GetStretchBltMode(hDC));
	Add(_T("Logical Font"),			  _T("0x%X"), GetCurrentObject(hDC, OBJ_FONT));
	Add(_T("Inter-character spacing"), _T("%d"), GetTextCharacterExtra(hDC));

	DWORD flag = SetMapperFlags(hDC, 0);
	SetMapperFlags(hDC, flag);

	Add(_T("Font Mapper Flags"),       _T("0x%X"), flag);

	Add(_T("Text Alignment"),		   _T("0x%X"), GetTextAlign(hDC));

	Add(_T("Text Justification"),      _T("write only"), 0);

	Add(_T("Layout"),                  _T("%d"), GetLayout(hDC));

	Add(_T("Path"),					   _T("%d bytes"), GetPath(hDC, NULL, NULL, 0));

	RECT rect;

	int typ = GetClipBox(hDC, & rect);

	HRGN hRgn = CreateRectRgn(0, 0, 1, 1);
	
	GetClipRgn(hDC, hRgn);

	Add(_T("Clipping"),				   _T("type %d clip box { %d, %d, %d, %d } size %d bytes"), 
		typ, rect.left, rect.top, rect.right, rect.bottom,
		GetRegionData(hRgn, 0, NULL)
		);
	
	GetMetaRgn(hDC, hRgn);

	GetRgnBox(hRgn, & rect);
	Add(_T("Meta Region"), _T("size %d bytes, rgn box { %d, %d, %d, %d }"), 
		GetRegionData(hRgn, 0, NULL), rect.left, rect.top, rect.right, rect.bottom);

	for (int i=1; i<=5; i++)
	{
		int rslt = GetRandomRgn(hDC, hRgn, i);

		if ( rslt==1 )
		{
			GetRgnBox(hRgn, & rect);
			Add(_T("Random Region"), _T("size %d bytes, rgn box { %d, %d, %d, %d }"), 
			GetRegionData(hRgn, 0, NULL), rect.left, rect.top, rect.right, rect.bottom);
		}
		else if ( rslt==0 )
			Add(_T("Random Region"), _T("NULL"), 0);
		else
			Add(_T("Random Region"), _T("FAIL"), 0);
	}
	DeleteObject(hRgn);

	GetBoundsRect(hDC, & rect, 0);

	Add(_T("Bounds Rectangle"),		_T("{ %d, %d, %d, %d }"), 
		rect.left, rect.top, rect.right, rect.bottom);
}
Ejemplo n.º 8
0
/**
 * gimp_monitor_get_color_profile:
 * @monitor: a #GdkMonitor
 *
 * This function returns the #GimpColorProfile of @monitor
 * or %NULL if there is no profile configured.
 *
 * Since: 3.0
 *
 * Return value: the monitor's #GimpColorProfile, or %NULL.
 **/
GimpColorProfile *
gimp_monitor_get_color_profile (GdkMonitor *monitor)
{
  GdkDisplay       *display;
  GdkScreen        *screen;
  GimpColorProfile *profile = NULL;

  g_return_val_if_fail (GDK_IS_MONITOR (monitor), NULL);

  display = gdk_monitor_get_display (monitor);

#if defined GDK_WINDOWING_X11
  {
    GdkAtom  type    = GDK_NONE;
    gint     format  = 0;
    gint     nitems  = 0;
    gint     number;
    gchar   *atom_name;
    guchar  *data    = NULL;

    number = monitor_number (monitor);

    if (number > 0)
      atom_name = g_strdup_printf ("_ICC_PROFILE_%d", number);
    else
      atom_name = g_strdup ("_ICC_PROFILE");

    screen = gdk_display_get_default_screen (display);

    if (gdk_property_get (gdk_screen_get_root_window (screen),
                          gdk_atom_intern (atom_name, FALSE),
                          GDK_NONE,
                          0, 64 * 1024 * 1024, FALSE,
                          &type, &format, &nitems, &data) && nitems > 0)
      {
        profile = gimp_color_profile_new_from_icc_profile (data, nitems,
                                                           NULL);
        g_free (data);
      }

    g_free (atom_name);
  }
#elif defined GDK_WINDOWING_QUARTZ
  {
    CGColorSpaceRef space = NULL;

    space = CGDisplayCopyColorSpace (monitor_number (monitor));

    if (space)
      {
        CFDataRef data;

        data = CGColorSpaceCopyICCData (space);

        if (data)
          {
            UInt8 *buffer = g_malloc (CFDataGetLength (data));

            /* We cannot use CFDataGetBytesPtr(), because that returns
             * a const pointer where cmsOpenProfileFromMem wants a
             * non-const pointer.
             */
            CFDataGetBytes (data, CFRangeMake (0, CFDataGetLength (data)),
                            buffer);

            profile = gimp_color_profile_new_from_icc_profile (buffer,
                                                               CFDataGetLength (data),
                                                               NULL);

            g_free (buffer);
            CFRelease (data);
          }

        CFRelease (space);
      }
  }
#elif defined G_OS_WIN32
  {
    HDC hdc = GetDC (NULL);

    if (hdc)
      {
        gchar  *path;
        gint32  len = 0;

        GetICMProfile (hdc, (LPDWORD) &len, NULL);
        path = g_new (gchar, len);

        if (GetICMProfile (hdc, (LPDWORD) &len, path))
          {
            GFile *file = g_file_new_for_path (path);

            profile = gimp_color_profile_new_from_file (file, NULL);
            g_object_unref (file);
          }

        g_free (path);
        ReleaseDC (NULL, hdc);
      }
  }
#endif

  return profile;
}
bool GetMonitorProfile(char *path, int buf_len, const void *hwnd)
{
    std::list<std::string> profile_descriptions;
    std::map<std::string, std::string> profile_paths;

    // path to the monitor's profile
    char monitor_profile_path[256] = { '\0' };
    DWORD path_size = 256;
    BOOL get_icm_result = GetICMProfile(GetDC((HWND)hwnd), &path_size, monitor_profile_path);

    // directory where Windows stores its profiles
    char profile_directory[256] = { '\0' };
    DWORD dir_name_size = 256;
    BOOL get_color_dir_result = GetColorDirectory(NULL, profile_directory, &dir_name_size);

    // Get the profile file names from Windows
    ENUMTYPE enum_type;
    enum_type.dwSize = sizeof(ENUMTYPE);
    enum_type.dwVersion = ENUM_TYPE_VERSION;
    enum_type.dwFields = ET_DEVICECLASS;  // alternately could use ET_CLASS
    enum_type.dwDeviceClass = CLASS_MONITOR;

    BYTE *buf = NULL;
    DWORD buf_size = 0;
    DWORD num_profiles = 0;

    BOOL other_enum_result = EnumColorProfiles(NULL, &enum_type,
                                                buf, &buf_size, &num_profiles);

    if(buf_size > 0 && num_profiles > 0)
    {
        buf = (BYTE *)malloc(buf_size);

        other_enum_result = EnumColorProfiles(NULL, &enum_type,
                                                buf, &buf_size, &num_profiles);

        if(other_enum_result)
        {
            // build a list of the profile descriptions
            // and a map to return the paths
            char *prof_name = (char *)buf;

            for(int i=0; i < num_profiles; i++)
            {
                std::string prof = prof_name;
                std::string prof_path = std::string(profile_directory) + "\\" + prof_name;

                cmsHPROFILE hProfile = cmsOpenProfileFromFile(prof_path.c_str(), "r");

                // Note: Windows will give us profiles that aren't ICC (.cdmp for example).
                // Don't worry, LittleCMS will just return NULL for those.
                if(hProfile)
                {
                    char profile_description[256];

                    cmsUInt32Number got_desc = cmsGetProfileInfoASCII(hProfile,
                                                                    cmsInfoDescription,
                                                                    "en", "US",
                                                                    profile_description,
                                                                    256);

                    if(got_desc)
                    {
                        profile_descriptions.push_back(profile_description);

                        profile_paths[ profile_description ] = prof_path;
                    }

                    cmsCloseProfile(hProfile);
                }

                prof_name += strlen(prof_name) + 1;
            }
        }

        free(buf);
    }


    if(profile_descriptions.size() > 0)
    {
        // set a vector and selected index for building the profile menu
        profile_descriptions.sort();
        profile_descriptions.unique();

        std::vector<std::string> profile_vec;
        int selected = 0;

        for(std::list<std::string>::const_iterator i = profile_descriptions.begin(); i != profile_descriptions.end(); i++)
        {
            profile_vec.push_back( *i );

            if( profile_paths[ *i ] == monitor_profile_path)
            {
                selected = profile_vec.size() - 1;
            }
        }

        // run the dialog
        g_profile_vec = &profile_vec;
        g_selected_item = selected;

        int status = DialogBox(hDllInstance, (LPSTR)"PROFILEDIALOG",
                                (HWND)hwnd, (DLGPROC)DialogProc);


        if(status == -1)
        {
            // dialog didn't open, my bad
            return true;
        }
        else if(g_item_clicked == DLOG_Cancel)
        {
            return false;
        }
        else
        {
            strncpy(path, profile_paths[ profile_vec[ g_selected_item ] ].c_str(), buf_len);

            return true;
        }
    }
    else
        return true;
}