/** @func    oyraFilterPlug_ImageOutputPPMWrite
 *  @brief   implement oyCMMFilter_GetNext_f()
 *
 *  @version Oyranos: 0.3.1
 *  @since   2008/10/07 (Oyranos: 0.1.8)
 *  @date    2011/05/12
 */
int      oyraFilterPlug_ImageOutputPPMWrite (
                                       oyFilterPlug_s    * requestor_plug,
                                       oyPixelAccess_s   * ticket )
{
  oyFilterSocket_s * socket;
  oyFilterNode_s * node = 0;
  oyOptions_s * node_opts = 0;
  int result = 0;
  const char * filename = 0;
  FILE * fp = 0;

  socket = oyFilterPlug_GetSocket( requestor_plug );
  node = oyFilterSocket_GetNode( socket );
  node_opts = oyFilterNode_GetOptions( node, 0 );

  /* to reuse the requestor_plug is a exception for the starting request */
  if(node)
    result = oyFilterNode_Run( node, requestor_plug, ticket );
  else
    result = 1;

  if(result <= 0)
    filename = oyOptions_FindString( node_opts, "filename", 0 );

  if(filename)
    fp = fopen( filename, "wb" );

  if(fp)
  {
    oyImage_s *image_output = (oyImage_s*)oyFilterSocket_GetData( socket );
    const char * comment = oyOptions_FindString( node_opts, "comment", NULL );

    fclose (fp); fp = 0;

    result = oyImage_WritePPM( image_output, filename,
                               comment ? comment :
                               oyFilterNode_GetRelatives( node ) );
  }

  return result;
}
oyOptions_s* oyraFilter_ImageOutputPPMValidateOptions
                                     ( oyFilterCore_s    * filter,
                                       oyOptions_s       * validate,
                                       int                 statical OY_UNUSED,
                                       uint32_t          * result )
{
  uint32_t error = !filter;

#if 0
  oyDATATYPE_e data_type = 0;
  int planar, channels;
  oyImage_s * image = 0;

  if(!error)
    filter = node->filter;

  if(!error)
    error = filter->type_ != oyOBJECT_FILTER_S;

  if(!error)
  {
    if(filter->image_ && filter->image_->layout_)
    {
      data_type = oyToDataType_m( filter->image_->layout_[0] );
      if(!(data_type == oyUINT8 ||
           data_type == oyUINT16 ||
           data_type == oyFLOAT ||
           data_type == oyDOUBLE
                                   ))
        error = 1;

      planar = oyToPlanar_m( filter->image_->layout_[0] );
      if(!error && planar)
        error = 1;

      channels = oyToChannels_m( filter->image_->layout_[0] );
      if(!error && channels > 4)
        error = 1;
    }
  }
#endif

  if(!error)
    error = !oyOptions_FindString( validate, "filename", 0 );

  *result = error;

  return 0;
}
int oyDisplayColorServerIsActive( )
{
  int color_server_active = 0; /* A XCM color server expects local white point adjustment and effect. */
  oyOptions_s * result_opts = oyOptions_New(NULL);

  oyOptions_Handle( "//" OY_TYPE_STD "/color_server_active",
                          result_opts,"color_server_active.source_data",
                          &result_opts );
  color_server_active = oyOptions_FindString( result_opts, "color_server_active", "1" ) != NULL;
  oyOptions_Release( &result_opts );

  if(oy_debug && color_server_active)
    oyMessageFunc_p( oyMSG_DBG, NULL, OY_DBG_FORMAT_
                        "color_server_active=%d",
                        OY_DBG_ARGS_, color_server_active );

  return color_server_active;
}
/** Function Configs_Modify
 *  @brief   oyCMMapi8_s SANE scanner manipulation
 *
 *  @version Oyranos: 0.1.10
 *  @since   2009/01/19 (Oyranos: 0.1.10)
 *  @date    2009/08/21
 *
 *  \todo { Test }
 */
int Configs_Modify(oyConfigs_s * devices, oyOptions_s * options)
{
   oyOption_s *version_opt = NULL;
   oyOption_s *version_opt_dev = NULL;
   oyConfig_s *device = NULL;
   int num_devices, g_error = 0;
   int call_sane_exit = 0;
   const char *command_list = NULL,
              *command_properties = NULL;

   oyAlloc_f allocateFunc = malloc;

   printf(PRFX "Entering %s(). Options:\n%s", __func__, oyOptions_GetText(options, oyNAME_NICK));

   /* "error handling" section */
   if (!devices || !oyConfigs_Count(devices)) {
      SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n "
              "No devices given! Options:\n%s", _DBG_ARGS_,
              oyOptions_GetText(options, oyNAME_NICK) );
      return 1;
   }

   /* "help" call section */
   if (oyOptions_FindString(options, "command", "help") || !options || !oyOptions_Count(options)) {
    /** oyMSG_WARN should make shure our message is visible. */
      ConfigsFromPatternUsage((oyStruct_s *) options);
      return 0;
   }

   num_devices = oyConfigs_Count(devices);
   command_list = oyOptions_FindString(options, "command", "list");
   command_properties = oyOptions_FindString(options, "command", "properties");

   /* Now we get some options [IN], and we already have some devices with
    * possibly already assigned options. Those provided through the input
    * oyOptions_s should take presedence over ::data & ::backend_core ones.
    * OTOH, all device_* options have a 1-1 relationship meaning if
    * one changes, probably all other should. So the simplest [naive] approach
    * would be to ignore all device_* options [IN] that are already in device.
    * Except from driver_version which has a special meaning.
    */

   /* Handle "driver_version" option [IN] */
   /* Check the first device to see if a positive driver_version is provided. */
   /* If not, consult the input options */
   device = oyConfigs_Get(devices, 0);
   version_opt_dev = oyConfig_Find(device, "driver_version");
   if (version_opt_dev && oyOption_GetValueInt(version_opt_dev, 0) > 0)
      call_sane_exit = 0;
   else
      check_driver_version(options, &version_opt, &call_sane_exit);
   oyConfig_Release(&device);
   oyOption_Release(&version_opt_dev);

   if (command_list) {
      /* "list" call section */
      int i;

      for (i = 0; i < num_devices; ++i) {
         const SANE_Device *device_context = NULL;
         SANE_Status status = SANE_STATUS_INVAL;
         oyOption_s *name_opt_dev = NULL,
                    *handle_opt_dev = NULL,
                    *context_opt_dev = NULL;
         const char *sane_name = NULL,
                    *sane_model = NULL;
         int error = 0;

         device = oyConfigs_Get(devices, i);

         if(oyOptions_Count(*oyConfig_GetOptions(device,"backend_core")))
           printf(PRFX "Backend core:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"backend_core"), oyNAME_NICK));
         if(oyOptions_Count(*oyConfig_GetOptions(device,"data")))
           printf(PRFX "Data:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"data"), oyNAME_NICK));

         /*Ignore device without a device_name*/
         if (!oyOptions_FindString(*oyConfig_GetOptions(device,"backend_core"), "device_name", NULL)) {
            SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n",
                    _DBG_ARGS_, "The \"device_name\" is missing from config object!");
            oyConfig_Release(&device);
            g_error++;
            continue;
         }

         /*Handle "driver_version" option [OUT] */
         version_opt_dev = oyConfig_Find(device, "driver_version");
         if (!version_opt_dev && version_opt)
            oyOptions_MoveIn(*oyConfig_GetOptions(device,"backend_core"), &version_opt, -1);
         oyOption_Release(&version_opt_dev);

         /*Handle "device_context" option */
         /*This is always provided by Configs_FromPattern()
          * [or should be alternatively by the user].
          * Configs_Modify() will not scan for SANE devices
          * because it takes too long*/
         context_opt_dev = oyConfig_Find(device, "device_context");
         if (!context_opt_dev) {
            SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n",
                    _DBG_ARGS_, "The \"device_context\" option is missing!");
            error = g_error = 1;
         }
         if (!error) {
            device_context = (SANE_Device*)oyOption_GetData(context_opt_dev, NULL, allocateFunc);
            sane_name  = device_context->name;
            sane_model = device_context->model;
         }

         /*Handle "oyNAME_NAME" option */
         name_opt_dev = oyConfig_Find(device, "oyNAME_NAME");
         if (!error && !name_opt_dev && oyOptions_Find(options, "oyNAME_NAME", oyNAME_PATTERN))
            oyOptions_SetFromString(oyConfig_GetOptions(device,"backend_core"),
                                  CMM_BASE_REG OY_SLASH "oyNAME_NAME",
                                  sane_model,
                                  OY_CREATE_NEW);

         /*Handle "device_handle" option */
         handle_opt_dev = oyConfig_Find(device, "device_handle");
         if (!error && !handle_opt_dev) {
            oyPointer_s *handle_ptr = NULL;
            SANE_Handle h;
            status = sane_open(sane_name, &h);
            if (status == SANE_STATUS_GOOD) {
               handle_ptr = oyPointer_New(0);
               oyPointer_Set(handle_ptr,
                            "SANE",
                            "handle",
                            (oyPointer)h,
                            "sane_release_handle",
                            sane_release_handle);
               oyOptions_MoveInStruct(oyConfig_GetOptions(device,"data"),
                                      CMM_BASE_REG OY_SLASH "device_handle",
                                      (oyStruct_s **) &handle_ptr, OY_CREATE_NEW);
            } else
               printf(PRFX "Unable to open sane device \"%s\": %s\n", sane_name, sane_strstatus(status));
         }

         /*Create static rank_map, if not already there*/
         if (!oyConfig_GetRankMap( device))
           oyConfig_SetRankMap( device, _api8.rank_map );

         /*Cleanup*/
         oyConfig_Release(&device);
         oyOption_Release(&context_opt_dev);
         oyOption_Release(&name_opt_dev);
         oyOption_Release(&handle_opt_dev);
      }
   } else if (command_properties) {
      /* "properties" call section */
      int i;

      /*Return a full list of scanner H/W &
       * SANE driver S/W color options
       * with the according rank map */

      for (i = 0; i < num_devices; ++i) {
         SANE_Device *device_context = NULL;
         SANE_Status status = SANE_STATUS_INVAL;
         SANE_Handle device_handle;
         oyOption_s *name_opt_dev = NULL,
                    *handle_opt_dev = NULL,
                    *context_opt_dev = NULL;
         oyConfig_s *device_new = NULL;
         char *device_name = NULL;

         /* All previous device properties are considered obsolete
          * and a new device is created. Basic options are moved from
          * the old to new device */
         device = oyConfigs_Get(devices, i);
         device_new = oyConfig_FromRegistration(CMM_BASE_REG, 0);

         printf(PRFX "Backend core:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"backend_core"), oyNAME_NICK));
         printf(PRFX "Data:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"data"), oyNAME_NICK));

         /*Ignore device without a device_name*/
         if (!oyOptions_FindString(*oyConfig_GetOptions(device,"backend_core"), "device_name", NULL)) {
            SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n",
                    _DBG_ARGS_, "The \"device_name\" is NULL, or missing from config object!");
            oyConfig_Release(&device);
            oyConfig_Release(&device_new);
            g_error++;
            continue;
         }

         /*Handle "driver_version" option [OUT] */
         if (version_opt) {
            oyOption_s *tmp = oyOption_Copy(version_opt, 0);
            oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"backend_core"), &tmp, -1);
         }

         /* 1. Get the "device_name" from old device */
         name_opt_dev = oyConfig_Find(device, "device_name");
         device_name = oyOption_GetValueText(name_opt_dev, allocateFunc);
         oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"backend_core"), &name_opt_dev, -1);

         /* 2. Get the "device_context" from old device */
         /* It should be there, see "list" call above */
         context_opt_dev = oyConfig_Find(device, "device_context");
         if (context_opt_dev) {
            device_context = (SANE_Device*)oyOption_GetData(context_opt_dev, NULL, allocateFunc);
            if (device_context) {
               oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"data"), &context_opt_dev, -1);
            } else {
               SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n",
                       _DBG_ARGS_, "The \"device_context\" is NULL!");
               oyOption_Release(&context_opt_dev);
               g_error++;
            }
         } else {
            SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n",
                    _DBG_ARGS_, "The \"device_context\" option is missing!");
            g_error++;
         }

         /* 3. Get the scanner H/W properties from old device */
         /* FIXME: we only recompute them, just in case they are not in old device */
         if (device_context) {
            DeviceInfoFromContext_(device_context, oyConfig_GetOptions(device_new,"backend_core"));
         }

         /* 4. Get the "device_handle" from old device */
         /* If not there, get one from SANE */
         handle_opt_dev = oyConfig_Find(device, "device_handle");
         if (handle_opt_dev) {
           oyPointer_s * oy_struct = (oyPointer_s*)oyOption_GetStruct(
                                           handle_opt_dev, oyOBJECT_POINTER_S );
           device_handle = (SANE_Handle)oyPointer_GetPointer(oy_struct);
           oyPointer_Release( &oy_struct );
            oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"data"), &handle_opt_dev, -1);
         } else {
            printf(PRFX "Opening sane device \"%s\"..", device_name); fflush(NULL);
            status = sane_open( device_name, &device_handle );
            if (status != SANE_STATUS_GOOD)
               printf("[FAIL: %s]\n", sane_strstatus(status));
            else
               printf("[OK]\n");
         }

         if (handle_opt_dev || status == SANE_STATUS_GOOD) {
            /* Use the device_handle to get the device color options */
            ColorInfoFromHandle(device_handle, oyConfig_GetOptions(device_new,"backend_core"));

            /*5. Set the rank map*/
            oyConfig_SetRankMap( device_new, _api8.rank_map );
         }

         /*Cleanup*/
         /* Remove old, add new device */
         oyConfig_Release(&device);
         oyConfigs_ReleaseAt(devices, i);
         oyConfigs_MoveIn(devices, &device_new, -1);

         /*If we had to open a SANE device, we'll have to close it*/
         if (status == SANE_STATUS_GOOD) {
            printf(PRFX "sane_close(%s)\n", device_name);
            sane_close(device_handle);
         }

         free(device_context);
         free(device_name);
      }
   } else {
      /*unsupported, wrong or no command */
      SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n "
              "No supported commands in options:\n%s", _DBG_ARGS_,
              oyOptions_GetText(options, oyNAME_NICK) );
      ConfigsFromPatternUsage((oyStruct_s *) options);
      g_error = 1;
   }

   /*Cleanup*/
   if (call_sane_exit) {
      printf(PRFX "sane_exit()\n");
      sane_exit();
   }

   oyOption_Release(&version_opt);

   printf(PRFX "Leaving %s\n", __func__);
   return g_error;
}
/** Function Configs_FromPattern
 *  @brief   CMM_NICK oyCMMapi8_s scanner devices
 *
 *  @param[in] 	registration	a string to compare ??????
 *  @param[in]		options			read what to do from the options object
 *  @param[out]	s					Return a configuration for each device found
 *
 *  @version Oyranos: 0.1.10
 *  @since   2009/01/19 (Oyranos: 0.1.10)
 *  @date    2009/02/09
 */
int Configs_FromPattern(const char *registration, oyOptions_s * options, oyConfigs_s ** s)
{
   oyConfig_s *device = NULL;
   oyConfigs_s *devices = NULL;
   oyOption_s *context_opt = NULL,
              *handle_opt = NULL,
              *version_opt = NULL,
              *name_opt = NULL;
   int i, num_devices, g_error = 0, status, call_sane_exit = 0;
   const char *device_name = 0, *command_list = 0, *command_properties = 0;
   const SANE_Device **device_list = NULL;
   int rank;
   oyAlloc_f allocateFunc = malloc;

   printf(PRFX "Entering %s(). Options:\n%s", __func__, oyOptions_GetText(options, oyNAME_NICK));

   rank = oyFilterRegistrationMatch(_api8.registration, registration,
                                        oyOBJECT_CMM_API8_S);
   command_list = oyOptions_FindString(options, "command", "list");
   command_properties = oyOptions_FindString(options, "command", "properties");
   device_name = oyOptions_FindString(options, "device_name", 0);

   /* "error handling" section */
   if (rank == 0) {
      SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n "
              "Registration match Failed. Options:\n%s", _DBG_ARGS_,
              oyOptions_GetText(options, oyNAME_NICK));
      return 1;
   }
   if (s == NULL) {
      SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n "
              "oyConfigs_s is NULL! Options:\n%s", _DBG_ARGS_,
              oyOptions_GetText(options, oyNAME_NICK));
      return 1;
   }
   if (*s != NULL) {
      SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n "
              "Devices struct already present! Options:\n%s", _DBG_ARGS_,
              oyOptions_GetText(options, oyNAME_NICK));
      return 1;
   }

   if (!device_name && command_properties) {
      SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n "
              "Device_name is mandatory for properties command:\n%s",
              _DBG_ARGS_, oyOptions_GetText(options, oyNAME_NICK));
      return 1;
   }

   /* "help" call section */
   if (oyOptions_FindString(options, "command", "help") || !options || !oyOptions_Count(options)) {
    /** oyMSG_WARN should make shure our message is visible. */
      ConfigsFromPatternUsage((oyStruct_s *) options);
      return 0;
   }

   context_opt = oyOptions_Find(options, "device_context", oyNAME_PATTERN);
   handle_opt = oyOptions_Find(options, "device_handle", oyNAME_PATTERN);
   name_opt = oyOptions_Find(options, "oyNAME_NAME", oyNAME_PATTERN);

   /*Handle "driver_version" option [IN] */
   check_driver_version(options, &version_opt, &call_sane_exit);

   devices = oyConfigs_New(0);
   if (command_list) {
      /* "list" call section */

      if (device_name &&   /*If a user provides a device_name option,*/
          !context_opt &&  /*and does not need the device_context data,*/
          !name_opt        /*or the oyNAME_NAME description*/
         )
         num_devices = 1;  /*then we can get away without calling GetDevices()*/
      else if (GetDevices(&device_list, &num_devices) != 0) {
         num_devices = 0; /*So that for loop will not run*/
         ++g_error;
      }

      for (i = 0; i < num_devices; ++i) {
         int error = 0;
         const char *sane_name = NULL,
                    *sane_model = NULL;

         if (device_list) {
            sane_name = device_list[i]->name;
            sane_model = device_list[i]->model;
         } else {
            sane_name = device_name;
         }

         /*Handle "device_name" option [IN] */
         if (device_name &&                        /*device_name is provided*/
             sane_name &&                          /*and sane_name has been retrieved*/
             strcmp(device_name, sane_name) != 0)  /*and they don't match,*/
            continue;                              /*then try the next*/

         device = oyConfig_FromRegistration(CMM_BASE_REG, 0);

         /*Handle "driver_version" option [OUT] */
         if (version_opt) {
            oyOption_s * tmp = oyOption_Copy(version_opt, 0);
            oyOptions_MoveIn(*oyConfig_GetOptions(device,"backend_core"), &tmp, -1);
         }

         /*Handle "device_name" option [OUT] */
         oyOptions_SetFromString(oyConfig_GetOptions(device,"backend_core"),
                               CMM_BASE_REG OY_SLASH "device_name",
                               sane_name,
                               OY_CREATE_NEW);

         /*Handle "oyNAME_NAME" option */
         if (name_opt)
            oyOptions_SetFromString(oyConfig_GetOptions(device,"backend_core"),
                                  CMM_BASE_REG OY_SLASH "oyNAME_NAME",
                                  sane_model,
                                  OY_CREATE_NEW);

         /*Handle "device_context" option */
         /* SANE Backend protocol states that device_context is *always* returned
          * This is a slight variation: Only when GetDevices() is called will it be returned,
          * unless we call sane_exit*/
         if (device_list && !call_sane_exit) {
            oyBlob_s *context_blob = oyBlob_New(NULL);
            oyOption_s *context_opt = oyOption_FromRegistration(
                                     CMM_BASE_REG OY_SLASH "device_context", 0);

            oyBlob_SetFromData(context_blob, (oyPointer) device_list[i], sizeof(SANE_Device), "sane");
            oyOption_MoveInStruct(context_opt, (oyStruct_s **) & context_blob);
            oyOptions_MoveIn(*oyConfig_GetOptions(device,"data"), &context_opt, -1);
         }

         /*Handle "device_handle" option */
         if (handle_opt && !call_sane_exit) {
            oyPointer_s *handle_ptr = NULL;
            SANE_Handle h;
            status = sane_open(sane_name, &h);
            if (status == SANE_STATUS_GOOD) {
               handle_ptr = oyPointer_New(0);
               oyPointer_Set(handle_ptr,
                            "SANE",
                            "handle",
                            (oyPointer)h,
                            "sane_release_handle",
                            sane_release_handle);
               oyOptions_MoveInStruct(oyConfig_GetOptions(device,"data"),
                                      CMM_BASE_REG OY_SLASH "device_handle",
                                      (oyStruct_s **) &handle_ptr, OY_CREATE_NEW);
            } else
               printf(PRFX "Unable to open sane device \"%s\": %s\n", sane_name, sane_strstatus(status));
         }

         oyConfig_SetRankMap( device, _api8.rank_map );

         error = oyConfigs_MoveIn(devices, &device, -1);

         /*Cleanup*/
         if (error) {
            oyConfig_Release(&device);
            ++g_error;
         }
      }

      *s = devices;
   } else if (command_properties) {
      /* "properties" call section */
      const SANE_Device *device_context = NULL;
      SANE_Device *aux_context = NULL;
      SANE_Handle device_handle = NULL;

      /*Return a full list of scanner H/W &
       * SANE driver S/W color options
       * with the according rank map */

      device = oyConfig_FromRegistration(CMM_BASE_REG, 0);

      /*Handle "driver_version" option [OUT] */
      if (version_opt) {
         oyOption_s *tmp = oyOption_Copy(version_opt, 0);
         oyOptions_MoveIn(*oyConfig_GetOptions(device,"backend_core"), &tmp, -1);
      }

      /*1a. Get the "device_context"*/
      if (!context_opt) { /*we'll have to get it ourselves*/
         if (GetDevices(&device_list, &num_devices) == 0) {
            device_context = *device_list;
            while (device_context) {
               if(device_name && device_context->name &&
                  strcmp(device_name,device_context->name) == 0)
                  break;
               device_context++;
            }
            if (!device_context) {
               printf(PRFX "device_name does not match any installed device.\n");
               g_error++;
            }
         } else {
            g_error++;
         }
      } else {
         aux_context = (SANE_Device*)oyOption_GetData(context_opt, NULL, allocateFunc);
         device_context = aux_context;
      }

      /*1b. Use the "device_context"*/
      if (device_context)
         DeviceInfoFromContext_(device_context, oyConfig_GetOptions(device,"backend_core"));

      /*2a. Get the "device_handle"*/
      if (!handle_opt) {
         status = sane_open( device_name, &device_handle );
         if (status != SANE_STATUS_GOOD) {
            printf(PRFX "Unable to open sane device \"%s\": %s\n", device_name, sane_strstatus(status));
            g_error++;
         }
      } else {
        oyPointer_s * oy_struct = (oyPointer_s*) oyOption_GetStruct( handle_opt,
                                                           oyOBJECT_POINTER_S );
        device_handle = (SANE_Handle)oyPointer_GetPointer(oy_struct);
        oyPointer_Release( &oy_struct );
      }

      if (device_handle) {
         /*2b. Use the "device_handle"*/
         ColorInfoFromHandle(device_handle, oyConfig_GetOptions(device,"backend_core"));

         /*3. Set the rank map*/
         oyConfig_SetRankMap( device, _api8.rank_map );
      }
      oyConfigs_MoveIn(devices, &device, -1);

      /*Cleanup*/
      free(aux_context);

      *s = devices;
   } else {
      /*unsupported, wrong or no command */
      SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n "
              "No supported commands in options:\n%s", _DBG_ARGS_,
              oyOptions_GetText(options, oyNAME_NICK) );
      ConfigsFromPatternUsage((oyStruct_s *) options);
      g_error = 1;
   }

   /*Global Cleanup*/
   if (call_sane_exit) {
      printf(PRFX "sane_exit()\n");
      sane_exit();
   }

   oyOption_Release(&context_opt);
   oyOption_Release(&handle_opt);
   oyOption_Release(&version_opt);
   oyOption_Release(&name_opt );

   printf(PRFX "Leaving %s\n", __func__);
   return g_error;
}
Exemple #6
0
int updateOutputConfiguration( Display * display )
{
  int error = 0,
      i, n, update = 0;
  oyOptions_s * options = 0;
  oyConfigs_s * devices = 0;
  oyConfig_s * device = 0, * old_device = 0;

  /* allow Oyranos to see modifications made to the compiz Xlib context */
  XFlush( display );

  /* obtain device informations, including geometry and ICC profiles
     from the according Oyranos module */
  error = oyOptions_SetFromText( &options, "//" OY_TYPE_STD "/config/command",
                                 "list", OY_CREATE_NEW );
  if(error) WARNc2_S("%s %d", _("found issues"),error);
  error = oyOptions_SetFromText( &options, "//" OY_TYPE_STD "/config/device_rectangle",
                                 "true", OY_CREATE_NEW );
  if(error) WARNc2_S("%s %d", _("found issues"),error);
  error = oyOptions_SetFromText( &options, "//" OY_TYPE_STD "/config/edid",
                                 "refresh", OY_CREATE_NEW );
  error = oyDevicesGet( OY_TYPE_STD, "monitor", options, &devices );
  if(error) WARNc2_S("%s %d", _("found issues"),error);
  n = oyOptions_Count( options );
  oyOptions_Release( &options );

  n = oyConfigs_Count( devices );
  /* find out if monitors have changed at all
   * care only about EDID's and enumeration, no dimension */
  if(n != oyConfigs_Count( old_devices ))
    update = 1;
  else
  for(i = 0; i < n; ++i)
  {
    const char * edid, * old_edid;
    device = oyConfigs_Get( devices, i );
    old_device = oyConfigs_Get( old_devices, i );
    edid = oyOptions_FindString( *oyConfig_GetOptions(device,"backend_core"),"EDID",0 );
    old_edid = oyOptions_FindString( *oyConfig_GetOptions(old_device,"backend_core"),"EDID",0 );

    if(edid && old_edid && strcmp(edid,old_edid)==0)
      update = 0;
    else
      update = 1;

    oyConfig_Release( &device );
    oyConfig_Release( &old_device );
    if(update) break;
  }

  if(!update)
    goto clean_update;

  cleanDisplay( display, n );

  for(i = 0; i < n; ++i)
  {
    device = oyConfigs_Get( devices, i );

    error = getDeviceProfile( display, device, i );
    if(error) WARNc2_S("%s %d", _("found issues"),error);

    oyConfig_Release( &device );
  }

  clean_update:
  oyConfigs_Release( &old_devices );
  old_devices = devices;

  return 0;
}
Exemple #7
0
/** Function  oyConfigs_FromDeviceClass
 *  @memberof oyConfigs_s
 *  @brief    Ask a module for device informations or other direct calls
 *
 *  @param[in]     device_type     the device type ::oyFILTER_REG_TYPE,
 *                                     defaults to OY_TYPE_STD (optional)
 *  @param[in]     device_class    the device class, e.g. "monitor",
 *                                     ::oyFILTER_REG_APPLICATION
 *  @param[in]     options             options to pass to the module, for zero
 *                                     the usage instructions are requested,
 *                                     a option "device_name" can be used 
 *                                     as filter
 *  @param[out]    devices         the devices
 *  @param[in]     object              the optional object
 *  @return                            0 - good, >= 1 - error
 *
 *  @verbatim
    // pass empty options to the module to get a usage message
    oyOptions_s * options = 0;
    int error = oyConfigs_FromDeviceClass( OY_TYPE_STD, "monitor",
                                              options, 0, 0 );
    @endverbatim
 *
 *  @version Oyranos: 0.1.10
 *  @since   2009/01/28 (Oyranos: 0.1.10)
 *  @date    2009/01/30
 */
OYAPI int  OYEXPORT
             oyConfigs_FromDeviceClass (
                                       const char        * device_type,
                                       const char        * device_class,
                                       oyOptions_s       * options,
                                       oyConfigs_s      ** devices,
                                       oyObject_s          object )
{
  int error = !device_class || !device_class[0];
  oyConfig_s * device = 0;
  oyConfigs_s * configs = 0;
  int i, j, j_n;
  uint32_t count = 0,
         * rank_list = 0;
  char ** texts = 0,
        * device_class_registration = 0;
  const char * tmp = 0,
             * device_name = 0;

  if(error > 0)
  {
    WARNc_S( "\n  No device_class argument provided. Give up" );
    return 0;
  }

  /** 1. obtain detailed and expensive device informations */
  if(options)
  {
    options = oyOptions_Copy( options, 0 );
    device_name = oyOptions_FindString( options, "device_name", 0 );
  }

  /** 1.2.1 build a device class registration string */
  if(error <= 0)
  {
    device_class_registration = oyDeviceRegistrationCreate_(
                                          device_type, device_class,
                                          device_name,
                                          device_class_registration );
    error = !device_class_registration;
  }

  /** 1.2.2 get all device class module names */
  if(error <= 0)
    error = oyConfigDomainList  ( device_class_registration, &texts, &count,
                                  &rank_list, 0 );

  if(devices && !*devices)
    *devices = oyConfigs_New( object );

  /** 1.3 ask each module */
  for( i = 0; i < count; ++i )
  {
    const char * registration_domain = texts[i];

    /** 1.3.1 call into module */
    error = oyConfigs_FromDomain( registration_domain, options, &configs,
                                  object);

    if(devices && *devices)
      j_n = oyConfigs_Count( configs );
    else
      j_n = 0;
    for( j = 0; j < j_n; ++j )
    {
      device = oyConfigs_Get( configs, j );

      if(device_name)
      {
        /** 1.3.1.1 Compare the device_name with the device_name option
         *          and collect the matching devices. */
        tmp = oyConfig_FindString( device, "device_name", 0 );
        if(tmp && oyStrcmp_( tmp, device_name ) == 0)
          oyConfigs_MoveIn( *devices, &device, -1 );
      } else
        /** 1.3.1.2 ... or collect all device configurations */
        oyConfigs_MoveIn( *devices, &device, -1 );

      oyConfig_Release( &device );
    }

    oyConfigs_Release( &configs );
  }

  if(devices)
    j_n = oyConfigs_Count( *devices );
  else
    j_n = 0;

  for( j = 0; j < j_n; ++j )
  {
    device = oyConfigs_Get( *devices, j );

    /** The basic call on how to obtain the configuration is added here as
     *  the objects name. "properties" and "list" are known. */
    if(oyOptions_FindString( options, "command", "properties" ) ||
       oyOptions_FindString( options, "oyNAME_DESCRIPTION", 0 ))
      oyObject_SetName( device->oy_, "properties", oyNAME_NAME );
    else if(oyOptions_FindString( options, "list", 0 ))
      oyObject_SetName( device->oy_, "list", oyNAME_NAME );

    oyConfig_Release( &device );
  }

  oyOptions_Release( &options );

  return error;
}
/** @brief  create_profile.white_point_adjust.bradford
 *
 *  The profile will be generated in many different shades, which will explode
 *  conversion cache.
 */
int      oyProfileAddWhitePointEffect( oyProfile_s       * monitor_profile,
                                       oyOptions_s      ** module_options )
{
  oyProfile_s * wtpt = NULL;
  double        src_XYZ[3] = {0.0, 0.0, 0.0}, dst_XYZ[3] = {0.0, 0.0, 0.0},
                scale = 1.0;
  int error = oyProfile_GetWhitePoint( monitor_profile, src_XYZ );
  int32_t display_white_point = oyGetBehaviour( oyBEHAVIOUR_DISPLAY_WHITE_POINT );
  oyOptions_s * result_opts = NULL, * opts = NULL;
  const char * desc = NULL;

  if(*module_options)
  {
    const char * value = oyOptions_FindString( *module_options, "display_white_point", 0 );
    if(value)
    {
      int c = atoi( value );
      if(c >= 0)
        display_white_point = c;
    }
  }

  if(!display_white_point)
    return 0;

  if(!error)
    error = oyGetDisplayWhitePoint( display_white_point, dst_XYZ );
  if(isnan(dst_XYZ[0]))
    error = 1;
  if(error)
  {
    oyMessageFunc_p( oyMSG_WARN,(oyStruct_s*)monitor_profile, OY_DBG_FORMAT_
                   "automatic display_white_point: not readable", OY_DBG_ARGS_);
    return error;
  }

  desc = oyProfile_GetText( monitor_profile, oyNAME_DESCRIPTION );

  error = oyOptions_SetFromString( &opts, "//" OY_TYPE_STD "/src_name", desc, OY_CREATE_NEW );
  if(error)
    return error;
  DBG_S_( oyPrintTime() );
  {
    int current = -1, choices = 0;
    const char ** choices_string_list = NULL;
    uint32_t flags = 0;
#ifdef HAVE_LOCALE_H
    char * old_loc = strdup(setlocale(LC_ALL,NULL));
    setlocale(LC_ALL,"C");
#endif
    error = oyOptionChoicesGet2( oyWIDGET_DISPLAY_WHITE_POINT, flags,
                                 oyNAME_NAME, &choices,
                                 &choices_string_list, &current );
    if(error > 0)
      oyMessageFunc_p( oyMSG_WARN,(oyStruct_s*)monitor_profile, OY_DBG_FORMAT_
                   "oyOptionChoicesGet2 failed %d", OY_DBG_ARGS_,
                   error);
#ifdef HAVE_LOCALE_H
    setlocale(LC_ALL,old_loc);
    if(old_loc) { free(old_loc); } old_loc = NULL;
#endif
    if(current > 0 && current < choices && choices_string_list)
    {
      if(current == 1) /* automatic */
      {
        double temperature = oyGetTemperature(-1);
        char k[12];
        sprintf(k, "%dK", (int)temperature);
        oyOptions_SetFromString( &opts, "//" OY_TYPE_STD "/illu_name", k, OY_CREATE_NEW );
        if(temperature <= 0.1)
          oyMessageFunc_p( oyMSG_WARN,(oyStruct_s*)monitor_profile, OY_DBG_FORMAT_
                   "automatic display_white_point: [%g %g %g] %s", OY_DBG_ARGS_,
                   dst_XYZ[0], dst_XYZ[1], dst_XYZ[2], k);
      }
      else
        oyOptions_SetFromString( &opts, "//" OY_TYPE_STD "/illu_name", choices_string_list[current], OY_CREATE_NEW );
      if(oy_debug)
        oyMessageFunc_p( oyMSG_DBG,(oyStruct_s*)monitor_profile, OY_DBG_FORMAT_
                   "illu_name: %s", OY_DBG_ARGS_,
                   oyOptions_FindString( opts, "illu_name", 0) );
    }
    oyOptionChoicesFree( oyWIDGET_DISPLAY_WHITE_POINT, &choices_string_list, choices );
  }

  if(oy_debug)
    oyMessageFunc_p( oyMSG_WARN, NULL, OY_DBG_FORMAT_
                   "src_name: %s -> illu_name: %s",
                   OY_DBG_ARGS_, oyOptions_FindString(opts, "src_name", 0), oyOptions_FindString(opts, "illu_name", 0) );
  oyOptions_SetFromDouble( &opts, "//" OY_TYPE_STD "/src_iccXYZ", src_XYZ[0], 0, OY_CREATE_NEW );
  oyOptions_SetFromDouble( &opts, "//" OY_TYPE_STD "/src_iccXYZ", src_XYZ[1], 1, OY_CREATE_NEW );
  oyOptions_SetFromDouble( &opts, "//" OY_TYPE_STD "/src_iccXYZ", src_XYZ[2], 2, OY_CREATE_NEW );
  oyOptions_SetFromDouble( &opts, "//" OY_TYPE_STD "/illu_iccXYZ", dst_XYZ[0], 0, OY_CREATE_NEW );
  oyOptions_SetFromDouble( &opts, "//" OY_TYPE_STD "/illu_iccXYZ", dst_XYZ[1], 1, OY_CREATE_NEW );
  oyOptions_SetFromDouble( &opts, "//" OY_TYPE_STD "/illu_iccXYZ", dst_XYZ[2], 2, OY_CREATE_NEW );
  /* cache the display white point abstract profile */
  error = oyOptions_Handle( "//" OY_TYPE_STD "/create_profile.white_point_adjust.bradford",
                            opts,             "create_profile.white_point_adjust.bradford.file_name",
                            &result_opts );
  DBG_S_( oyPrintTime() );
  if(error > 0)
    oyMessageFunc_p( oyMSG_WARN,(oyStruct_s*)monitor_profile, OY_DBG_FORMAT_
                   "oyOptions_Handle(white_point_adjust.bradford.file_name) failed %d", OY_DBG_ARGS_,
                   error);

  /* write cache profile for slightly better speed and useful for debugging */
  if(error == 0)
  {
    const char * file_name = oyOptions_FindString( result_opts, "file_name", 0 );
    char * cache_path = oyGetInstallPath( oyPATH_CACHE, oySCOPE_USER, oyAllocateFunc_ ), *t;
    if(strstr( cache_path, "device_link") != NULL)
    {
      t = strstr( cache_path, "device_link");
      t[0] = '\000';
      oyStringAddPrintf( &cache_path, 0,0, "white_point_adjust/%s.icc", file_name );
    }

    if(oyIsFile_(cache_path))
    {
      if(oy_debug)
        oyMessageFunc_p( oyMSG_DBG,(oyStruct_s*)monitor_profile, OY_DBG_FORMAT_
                     "found file_name: %s -> %s\n", OY_DBG_ARGS_, file_name, cache_path );
      wtpt = oyProfile_FromFile( cache_path, 0,0 );
      DBG_S_( oyPrintTime() );
    }
  }

  if(!error && wtpt)
  {
    oyOptions_MoveInStruct( module_options,
                          OY_STD "/icc_color/display.icc_profile.abstract.white_point.automatic.oy-monitor",
                          (oyStruct_s**) &wtpt, OY_CREATE_NEW );
    oyOptions_Release( &result_opts );
    oyOptions_Release( &opts );

    return error;
  }

  if(!error && !wtpt)
  {
    /* detect scaling factor
     * - convert monitor device RGB to XYZ,
     * - apply white point adaption matrix,
     * - convert back to monitor device RGB and
     * - again to XYZ to detect clipping and
     * - use that information for scaling inside the white point effect profile */
    oyProfile_s * xyz_profile = oyProfile_FromStd( oyASSUMED_XYZ, 0, 0 );
    float rgb[9] = {1,0,0, 0,1,0, 0,0,1},
          xyz[9] = {0,0,0, 0,0,0, 0,0,0};
    oyDATATYPE_e buf_type = oyFLOAT;
    oyConversion_s * cc_moni2xyz = oyConversion_CreateBasicPixelsFromBuffers(
                              monitor_profile, rgb, oyDataType_m(buf_type),
                              xyz_profile, xyz, oyDataType_m(buf_type),
                              0, 3 );
    oyConversion_s * cc_xyz2moni = oyConversion_CreateBasicPixelsFromBuffers(
                              xyz_profile, xyz, oyDataType_m(buf_type),
                              monitor_profile, rgb, oyDataType_m(buf_type),
                              0, 3 );
    oyMAT3 wtpt_adapt;
    oyCIEXYZ srcWtpt = {src_XYZ[0], src_XYZ[1], src_XYZ[2]},
             dstIllu = {dst_XYZ[0], dst_XYZ[1], dst_XYZ[2]};
    error = !oyAdaptationMatrix( &wtpt_adapt, NULL, &srcWtpt, &dstIllu );
    int i,j;
    for(j = 0; j < 100; ++j)
    {
      oyConversion_RunPixels( cc_moni2xyz, 0 );
      if(oy_debug)
        oyMessageFunc_p( oyMSG_DBG,(oyStruct_s*)cc_moni2xyz, OY_DBG_FORMAT_
                   "rgb->xyz:\nR[%g %g %g] G[%g %g %g] B[%g %g %g]",
                   OY_DBG_ARGS_, xyz[0], xyz[1], xyz[2], xyz[3], xyz[4], xyz[5], xyz[6], xyz[7], xyz[8]);
      oyVEC3 rXYZ, srcXYZ[3] = { {{xyz[0], xyz[1], xyz[2]}}, {{xyz[3], xyz[4], xyz[5]}}, {{xyz[6], xyz[7], xyz[8]}} };
      oyMAT3 wtpt_adapt_scaled,
             scale_mat = {{ {{scale,0,0}}, {{0,scale,0}}, {{0,0,scale}} }};
      oyMAT3per( &wtpt_adapt_scaled, &wtpt_adapt, &scale_mat );
      oyMAT3eval( &rXYZ, &wtpt_adapt_scaled, &srcXYZ[0] ); for(i = 0; i < 3; ++i) xyz[0+i] = rXYZ.n[i];
      oyMAT3eval( &rXYZ, &wtpt_adapt_scaled, &srcXYZ[1] ); for(i = 0; i < 3; ++i) xyz[3+i] = rXYZ.n[i];
      oyMAT3eval( &rXYZ, &wtpt_adapt_scaled, &srcXYZ[2] ); for(i = 0; i < 3; ++i) xyz[6+i] = rXYZ.n[i];
      if(oy_debug)
        oyMessageFunc_p( oyMSG_DBG,(oyStruct_s*)cc_moni2xyz, OY_DBG_FORMAT_
                   "srcWtpt->Illu:\nR[%g %g %g] G[%g %g %g] B[%g %g %g]", OY_DBG_ARGS_,
          xyz[0], xyz[1], xyz[2], xyz[3], xyz[4], xyz[5], xyz[6], xyz[7], xyz[8]);
      oyConversion_RunPixels( cc_xyz2moni, 0 );
      if(oy_debug)
        oyMessageFunc_p( oyMSG_WARN,(oyStruct_s*)cc_moni2xyz, OY_DBG_FORMAT_
                   "xyz->rgb:\nR[%g %g %g] G[%g %g %g] B[%g %g %g] %g",
                   OY_DBG_ARGS_, rgb[0], rgb[1], rgb[2], rgb[3], rgb[4], rgb[5], rgb[6], rgb[7], rgb[8], scale);
      if(rgb[0+0] < 0.99 && rgb[3+1] < 0.99 && rgb[6+2] < 0.99)
      {
        if(scale < 1.00) scale += 0.01;
        break;
      }
      scale -= 0.01;
    }
  }

  oyMessageFunc_p( /*error ?*/ oyMSG_WARN/*:oyMSG_DBG*/,(oyStruct_s*)monitor_profile, OY_DBG_FORMAT_
                   "%s display_white_point: %d [%g %g %g] -> [%g %g %g] * %g %d", OY_DBG_ARGS_,
          desc, display_white_point,
          src_XYZ[0], src_XYZ[1], src_XYZ[2], dst_XYZ[0], dst_XYZ[1], dst_XYZ[2], scale, error);
  if(error > 0)
    return error;

  /* write cache profile for slightly better speed and useful for debugging */
  if(error == 0)
  {
    const char * file_name = oyOptions_FindString( result_opts, "file_name", 0 );
    char * cache_path = oyGetInstallPath( oyPATH_CACHE, oySCOPE_USER, oyAllocateFunc_ ), *t;
    if(strstr( cache_path, "device_link") != NULL)
    {
      t = strstr( cache_path, "device_link");
      t[0] = '\000';
      oyStringAddPrintf( &cache_path, 0,0, "white_point_adjust/%s.icc", file_name );
    }

    {
      error = oyOptions_SetFromDouble( &opts, "//" OY_TYPE_STD "/scale", scale, 0, OY_CREATE_NEW );
      if(oy_debug)
        oyMessageFunc_p( oyMSG_DBG,(oyStruct_s*)monitor_profile, OY_DBG_FORMAT_
                     "creating file_name: %s -> %s\n", OY_DBG_ARGS_, file_name, cache_path );
      error = oyOptions_Handle( "//" OY_TYPE_STD "/create_profile.white_point_adjust.bradford",
                            opts,             "create_profile.white_point_adjust.bradford",
                            &result_opts );
      wtpt = (oyProfile_s*) oyOptions_GetType( result_opts, -1, "icc_profile",
                                           oyOBJECT_PROFILE_S );
      error = !wtpt;
      if(!error)
        oyProfile_ToFile_( (oyProfile_s_*) wtpt, cache_path );
      DBG_S_( oyPrintTime() );
    }
  }

  error = !wtpt;
  if(error == 0)
    oyOptions_MoveInStruct( module_options,
                          OY_STD "/icc_color/display.icc_profile.abstract.white_point.automatic.oy-monitor",
                          (oyStruct_s**) &wtpt, OY_CREATE_NEW );
  oyOptions_Release( &result_opts );
  oyOptions_Release( &opts );

  return error;
}
/** Function oyDrawScreenImage
 *  @brief   generate a Oyranos image from a given context for display
 *
 *  The function asks the 'oydi' node to provide parameters to render a
 *  oyImage_s from a prepared oyConversion_s context.
 *
 *  @param[in]     context             the Oyranos graph
 *  @param[in,out] ticket              rendering context for tracking
 *                                     rectangles
 *  @param[in]     display_rectangle   absolute coordinates of visible image
 *                                     in relation to display
 *  @param[in,out] old_display_rectangle
 *                                     rembering of display_rectangle
 +  @param[in,out] old_roi_rectangle   remembering of ticket's ROI (optional)
 *  @param[in]     system_type         the system dependent type specification
 *                                     - "X11" is well supported
 *                                     - "oy-test" for internal tests
 *  @param[in]     data_type_request   oyUINT8 or oyUINT16
 *  @param[in]     display             the system display with system_type:
 *                                     - "X11": a Display object
 *  @param[in]     window              the system window with system_type:
 *                                     - "X11": a Window ID
 *  @param[in]     dirty               explicite redraw
 *  @param[out]    image               the image from graph to display
 *  @return                            0 - success, -1 - issue, >=  1 - error
 *
 *  @version Oyranos: 0.9.6
 *  @date    2016/09/22
 *  @since   2010/09/05 (Oyranos: 0.1.11)
 */
int  oyDrawScreenImage               ( oyConversion_s    * context,
                                       oyPixelAccess_s   * ticket,
                                       oyRectangle_s     * display_rectangle,
                                       oyRectangle_s     * old_display_rectangle,
                                       oyRectangle_s     * old_roi_rectangle,
                                       const char        * system_type,
                                       oyDATATYPE_e        data_type_request,
                                       void              * display,
                                       void              * window,
                                       int                 dirty,
                                       oyImage_s         * image )
{
  int result = 0;

    if(context)
    {
      double X,Y,W,H;
      int channels = 0;
      oyFilterNode_s * node_out = 0;
      oyRectangle_s * disp_rectangle = 0,
                    * ticket_roi = 0;
      oyOptions_s * image_tags = 0;
      oyDATATYPE_e data_type = oyUINT8;
      oyPixel_t pt = 0;

      oyRectangle_GetGeo( display_rectangle, &X, &Y, &W, &H );

      if(!image)
        return 1;
      if( W <= 0 || H <= 0)
        return -1;

      image_tags = oyImage_GetTags( image );

      if(window && strcmp("X11", system_type) == 0)
      {
#if defined(XCM_HAVE_X11)
        /* add X11 window and display identifiers to output image */
        oyOption_s * o = 0;
        Display *disp = (Display*) display;
        Window  w = (Window) window;
        int count = oyOptions_CountType( image_tags,
                                         "//" OY_TYPE_STD "/display/window_id",
                                         oyOBJECT_BLOB_S );
        if(!count && w)
        {
          oyBlob_s * win_id = oyBlob_New(0),
                   * display_id = oyBlob_New(0);
          if(win_id)
          {
            oyBlob_SetFromStatic( win_id, (oyPointer)w, 0, 0 );
            o = oyOption_FromRegistration( "//" OY_TYPE_STD "/display/window_id",
                                           0 );
            oyOption_MoveInStruct( o, (oyStruct_s**)&win_id );
            oyOptions_MoveIn( image_tags, &o, -1 );

            oyBlob_SetFromStatic( display_id, (oyPointer)disp, 0, 0 );
            o = oyOption_FromRegistration( "//" OY_TYPE_STD "/display/display_id",
                                           0 );
            oyOption_MoveInStruct( o, (oyStruct_s**)&display_id );
            oyOptions_MoveIn( image_tags, &o, -1 );

            oyOptions_SetFromText( &image_tags,
                                   "//" OY_TYPE_STD "/display/display_name",
                                   DisplayString(disp), OY_CREATE_NEW );

          } else
            printf("%s:%d WARNING: no X11 Window obtained or\n"
                   "   no oyBlob_s allocateable\n", __FILE__,__LINE__);

        }
#endif
      } else if(strcmp("oy-test", system_type) == 0)
        oyOptions_SetFromText( &image_tags,
                               "//" OY_TYPE_STD "/display/display_name",
                               system_type, OY_CREATE_NEW );

      /* check if the actual data can be displayed */
      pt = oyImage_GetPixelLayout( image, oyLAYOUT );
      data_type = oyToDataType_m( pt );
      channels = oyToChannels_m( pt );
      if(pt != 0 &&
         ((channels != 4 && channels != 3) || data_type != data_type_request))
      {
        printf( "%s:%d WARNING: wrong image data format: %s\n%s\n"
                "need 4 or 3 channels with %s\n", __FILE__,__LINE__,
                oyOptions_FindString( image_tags, "filename", 0 ),
                image ? oyObject_GetName( image->oy_, oyNAME_NICK ) : "",
                oyDataTypeToText( data_type_request ) );
        return 1;
      }


      /* Inform about the images display coverage.  */
      disp_rectangle = (oyRectangle_s*) oyOptions_GetType( image_tags, -1,
                                    "display_rectangle", oyOBJECT_RECTANGLE_S );
      oyRectangle_SetGeo( disp_rectangle, X,Y,W,H );


      node_out = oyConversion_GetNode( context, OY_OUTPUT );
      ticket_roi = oyPixelAccess_GetArrayROI( ticket );
      /* decide wether to refresh the cached rectangle of our static image */
      if( node_out &&
          /* Did the window area move? */
         ((!oyRectangle_IsEqual( disp_rectangle, old_display_rectangle ) ||
           /* Something explicite to update? */
           (old_roi_rectangle &&
            !oyRectangle_IsEqual( ticket_roi, old_roi_rectangle ))||
           /* Did the image move? */
           oyPixelAccess_GetStart( ticket,0 ) !=
           oyPixelAccess_GetOldStart( ticket,0 ) ||
           oyPixelAccess_GetStart( ticket,1 ) !=
           oyPixelAccess_GetOldStart( ticket,1 )) ||
           dirty > 0))
      {
#ifdef DEBUG_
        printf( "%s:%d new display rectangle: %s +%d+%d\n", __FILE__,__LINE__,
                oyRectangle_Show(disp_rectangle), X, Y ),
#endif

        /* convert the image data */
        oyConversion_RunPixels( context, ticket );

        if(oy_debug && getenv("OY_DEBUG_WRITE"))
        {
          oyImage_s * out = oyConversion_GetImage( context, OY_OUTPUT );
          oyImage_WritePPM( out, "debug_image_out.ppm", "image_display output image");
          oyImage_Release( &out );
        }

        /* remember the old rectangle */
        oyRectangle_SetByRectangle( old_display_rectangle, disp_rectangle );
        oyRectangle_SetByRectangle( old_roi_rectangle, ticket_roi );
        oyPixelAccess_SetOldStart(ticket,0, oyPixelAccess_GetStart(ticket,0));
        oyPixelAccess_SetOldStart(ticket,1, oyPixelAccess_GetStart(ticket,1));
      } else
        result = -1;

      oyFilterNode_Release( &node_out );
      oyOptions_Release( &image_tags );
      oyRectangle_Release( &disp_rectangle );
      oyRectangle_Release( &ticket_roi );
    }

  if(oy_debug >= 4)
    fprintf( stderr, "%s:%d %s() result: %d\n", strrchr(__FILE__,'/'),__LINE__,__func__, result );
  return result;
}