/** @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; }
oyConversion_s * oyConversion_FromImageForDisplay_ ( oyImage_s * image_in, oyImage_s * image_out, oyFilterNode_s ** cc_node, uint32_t flags, oyDATATYPE_e data_type, oyOptions_s * cc_options, oyObject_s obj ) { oyFilterNode_s * in = 0, * out = 0, * icc = 0; int error = 0; oyConversion_s * conversion = 0; oyOptions_s * options = 0; oyOption_s * option = 0; const char * sv = 0; double scale = 0; if(!image_in || !image_out) return NULL; /* start with an empty conversion object */ conversion = oyConversion_New( obj ); /* create a filter node */ in = oyFilterNode_NewWith( "//" OY_TYPE_STD "/root", 0, obj ); /* set the above filter node as the input */ oyConversion_Set( conversion, in, 0 ); /* set the image buffer */ oyFilterNode_SetData( in, (oyStruct_s*)image_in, 0, 0 ); /* add a scale node */ out = oyFilterNode_NewWith( "//" OY_TYPE_STD "/scale", 0, obj ); options = oyFilterNode_GetOptions( out, OY_SELECT_FILTER ); /* scale factor from DB */ option = oyOption_FromRegistration( OY_INTERNAL "/scale/scale", 0 ); error = oyOption_SetFromText( option, 0, 0 ); error = oyOption_SetValueFromDB( option ); scale = 1.0; if(!error) { sv = oyOption_GetValueString( option, 0 ); if(sv) scale = strtod( sv, 0 ); } oyOption_Release( &option ); error = oyOptions_SetFromDouble( &options, OY_INTERNAL "/scale/scale", scale, 0, OY_CREATE_NEW ); oyOptions_Release( &options ); /* append the node */ error = oyFilterNode_Connect( in, "//" OY_TYPE_STD "/data", out, "//" OY_TYPE_STD "/data", 0 ); if(error > 0) fprintf( stderr, "could not add filter: %s\n", "//" OY_TYPE_STD "/scale" ); in = out; /* add a expose node */ out = oyFilterNode_NewWith( "//" OY_TYPE_STD "/expose", 0, obj ); options = oyFilterNode_GetOptions( out, OY_SELECT_FILTER ); /* expose factor */ error = oyOptions_SetFromDouble( &options, "//" OY_TYPE_STD "/expose/expose", 1.0, 0, OY_CREATE_NEW ); oyOptions_Release( &options ); /* append the node */ error = oyFilterNode_Connect( in, "//" OY_TYPE_STD "/data", out, "//" OY_TYPE_STD "/data", 0 ); if(error > 0) fprintf( stderr, "could not add filter: %s\n", "//" OY_TYPE_STD "/expose" ); in = out; /* add a channel node */ out = oyFilterNode_NewWith( "//" OY_TYPE_STD "/channel", 0, obj ); options = oyFilterNode_GetOptions( out, OY_SELECT_FILTER ); /* channel option*/ error = oyOptions_SetFromText( &options, "//" OY_TYPE_STD "/channel/channel", "", OY_CREATE_NEW ); oyOptions_Release( &options ); /* append the node */ error = oyFilterNode_Connect( in, "//" OY_TYPE_STD "/data", out, "//" OY_TYPE_STD "/data", 0 ); if(error > 0) fprintf( stderr, "could not add filter: %s\n", "//" OY_TYPE_STD "/channel" ); in = out; /* create a new filter node */ { icc = out = oyFilterNode_FromOptions( OY_CMM_STD, "//" OY_TYPE_STD "/icc_color", cc_options, NULL ); /* append the new to the previous one */ error = oyFilterNode_Connect( in, "//" OY_TYPE_STD "/data", out, "//" OY_TYPE_STD "/data", 0 ); if(error > 0) fprintf( stderr, "could not add filter: %s\n", OY_CMM_STD ); /* Set the image to the first/only socket of the filter node. * oyFilterNode_Connect() has now no chance to copy it it the other nodes. * We rely on resolving the image later. */ error = oyFilterNode_SetData( out, (oyStruct_s*)image_out, 0, 0 ); if(error != 0) fprintf( stderr, "could not add data\n" ); } /* swap in and out */ if(out) in = out; /* create a node for preparing the image for displaying */ { out = oyFilterNode_NewWith( "//" OY_TYPE_STD "/display", 0, obj ); options = oyFilterNode_GetOptions( out, OY_SELECT_FILTER ); /* data type for display */ error = oyOptions_SetFromInt( &options, "//" OY_TYPE_STD "/display/datatype", data_type, 0, OY_CREATE_NEW ); /* alpha might be support once by FLTK? */ error = oyOptions_SetFromInt( &options, "//" OY_TYPE_STD "/display/preserve_alpha", 1, 0, OY_CREATE_NEW ); oyOptions_Release( &options ); /* append the node */ error = oyFilterNode_Connect( in, "//" OY_TYPE_STD "/data", out, "//" OY_TYPE_STD "/data", 0 ); if(error > 0) fprintf( stderr, "could not add filter: %s\n", "//" OY_TYPE_STD "/display" ); oyFilterNode_SetData( out, (oyStruct_s*)image_out, 0, 0 ); in = out; } /* add a closing node */ out = oyFilterNode_NewWith( "//" OY_TYPE_STD "/output", 0, obj ); error = oyFilterNode_Connect( in, "//" OY_TYPE_STD "/data", out, "//" OY_TYPE_STD "/data", 0 ); if(error > 0) fprintf( stderr, "could not add filter: %s\n", "//" OY_TYPE_STD "/output" ); /* set the output node of the conversion */ oyConversion_Set( conversion, 0, out ); /* apply policies */ /*error = oyOptions_SetFromText( &options, "//" OY_TYPE_STD "//verbose", "true", OY_CREATE_NEW );*/ oyConversion_Correct( conversion, "//" OY_TYPE_STD "/icc_color", flags, options ); oyOptions_Release( &options ); if(cc_node) *cc_node = icc; return conversion; }
/** @brief implement oyCMMFilter_GetNext_f() * * @version Oyranos: 0.9.6 * @date 2016/04/04 * @since 2013/06/10 (Oyranos: 0.9.5) */ int oyraFilter_ImageExposeRun ( oyFilterPlug_s * requestor_plug, oyPixelAccess_s * ticket ) { int result = 0, error = 0; oyFilterSocket_s * socket = 0; oyFilterNode_s * input_node = 0, * node = 0; oyFilterPlug_s * plug = 0; oyImage_s * image = 0; int dirty = 0; socket = oyFilterPlug_GetSocket( requestor_plug ); node = oyFilterSocket_GetNode( socket ); image = (oyImage_s*)oyFilterSocket_GetData( socket ); if(!image) { result = 1; goto clean_expose1; } if(oy_debug) oyra_msg( oyMSG_WARN, (oyStruct_s*)ticket, OY_DBG_FORMAT_ "image [%d](%d)\n",OY_DBG_ARGS_,oyStruct_GetId((oyStruct_s*)image),oyImage_GetWidth(image) ); { oyRectangle_s * ticket_roi = oyPixelAccess_GetArrayROI( ticket ); double expose = 1.0; oyOptions_s * node_opts = oyFilterNode_GetOptions( node, 0 ); if(!node_opts) dirty = 1; if(dirty) { result = dirty; goto clean_expose2; } plug = oyFilterNode_GetPlug( node, 0 ); /* select node */ input_node = oyFilterNode_GetPlugNode( node, 0 ); /* find filters own expose factor */ error = oyOptions_FindDouble( node_opts, "//" OY_TYPE_STD "/expose/expose", 0, &expose ); if(error) WARNc2_S("%s %d", _("found issues"),error); if(oy_debug > 2) oyra_msg( oyMSG_WARN, (oyStruct_s*)ticket, OY_DBG_FORMAT_ "%s expose: %f",OY_DBG_ARGS_, oyPixelAccess_Show(ticket), expose); if(expose != 1.0) { oyImage_s * output_image = oyPixelAccess_GetOutputImage( ticket ); oyArray2d_s * array_out = oyPixelAccess_GetArray( ticket ); oyProfile_s * p = oyImage_GetProfile( output_image ); icColorSpaceSignature sig = oyProfile_GetSignature( p, oySIGNATURE_COLOR_SPACE ); int layout_dst = oyImage_GetPixelLayout( output_image, oyLAYOUT ); int channels_dst = oyToChannels_m( layout_dst ); int byte_swap = oyToByteswap_m( layout_dst ); int ticket_array_pix_width; /* avoid division by zero */ if(!channels_dst) channels_dst = 1; ticket_array_pix_width = oyArray2d_GetWidth( array_out ) / channels_dst; { int w,h,x,y, i, start_x,start_y; unsigned int max = 1; oyRectangle_s * ticket_roi = oyPixelAccess_GetArrayROI( ticket ); oyRectangle_s_ roi_= {oyOBJECT_RECTANGLE_S,0,0,0, 0,0,0,0}; oyRectangle_s * roi = (oyRectangle_s*)&roi_; uint8_t ** array_out_data; /* get pixel layout infos for copying */ oyDATATYPE_e data_type_out = oyToDataType_m( layout_dst ); int bps_out = oyDataTypeGetSize( data_type_out ); /* get the source pixels */ result = oyFilterNode_Run( input_node, plug, ticket ); /* get the channel buffers */ array_out_data = oyArray2d_GetData( array_out ); w = oyArray2d_GetWidth( array_out ) / channels_dst; h = oyArray2d_GetHeight( array_out ); oyRectangle_SetByRectangle( roi, ticket_roi ); oyRectangle_Scale( roi, ticket_array_pix_width ); start_x = OY_ROUND(roi_.x); start_y = OY_ROUND(roi_.y); switch(data_type_out) { case oyUINT8: max = 255; break; case oyUINT16: max = 65535; break; case oyUINT32: max = UINT32_MAX; break; default: break; } /* expose the samples */ #if defined(USE_OPENMP) #pragma omp parallel for private(x,y,i) #endif for(y = start_y; y < h; ++y) { for(x = start_x; x < w; ++x) { if( (sig == icSigRgbData || sig == icSigXYZData || sig == icSigLabData || sig == icSigYCbCrData) && channels_dst >= 3) { double rgb[3], v; for(i = 0; i < 3; ++i) { switch(data_type_out) { case oyUINT8: rgb[i] = array_out_data[y][x*channels_dst*bps_out + i*bps_out]; break; case oyUINT16: { uint16_t v = *((uint16_t*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]); if(byte_swap) v = oyByteSwapUInt16(v); rgb[i] = v; } break; case oyUINT32: { uint32_t v = *((uint32_t*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]); if(byte_swap) v = oyByteSwapUInt32(v); rgb[i] = v; } break; case oyHALF: v = *((uint16_t*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]); rgb[i] = v; break; case oyFLOAT: v = *((float*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]); rgb[i] = v; break; case oyDOUBLE: v = *((double*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]); rgb[i] = v; break; } } oySensibleClip ( rgb, sig, max, expose ); for(i = 0; i < 3; ++i) { v = rgb[i]; switch(data_type_out) { case oyUINT8: array_out_data[y][x*channels_dst*bps_out + i*bps_out] = v; break; case oyUINT16: { uint16_t u16 = v; *((uint16_t*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]) = byte_swap ? oyByteSwapUInt16(u16) : u16; } break; case oyUINT32: { uint32_t u32 = v; *((uint32_t*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]) = byte_swap ? oyByteSwapUInt16(u32) : u32; } break; case oyHALF: *((uint16_t*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]) = v; break; case oyFLOAT: *((float*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]) = v; break; case oyDOUBLE: *((double*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]) = v; break; } } } else for(i = 0; i < channels_dst; ++i) { int v; switch(data_type_out) { case oyUINT8: v = array_out_data[y][x*channels_dst*bps_out + i*bps_out] * expose; if(v > 255) v = 255; array_out_data[y][x*channels_dst*bps_out + i*bps_out] = v; break; case oyUINT16: v = *((uint16_t*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]); if(byte_swap) v = oyByteSwapUInt16(v); v *= expose; if(v > 65535) v = 65535; *((uint16_t*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]) = byte_swap ? oyByteSwapUInt16(v) : v; break; case oyUINT32: *((uint32_t*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]) *= expose; break; case oyHALF: *((uint16_t*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]) *= expose; break; case oyFLOAT: *((float*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]) *= expose; break; case oyDOUBLE: *((double*)&array_out_data[y][x*channels_dst*bps_out + i*bps_out]) *= expose; break; } } } } } oyArray2d_Release( &array_out ); oyImage_Release( &output_image ); oyProfile_Release( &p ); } else /* expose == 1.0 */ { result = oyFilterNode_Run( input_node, plug, ticket ); } clean_expose2: oyOptions_Release( &node_opts ); oyFilterPlug_Release( &plug ); oyRectangle_Release( &ticket_roi ); oyFilterNode_Release( &input_node ); } clean_expose1: oyImage_Release( &image ); oyFilterSocket_Release( &socket ); oyFilterNode_Release( &node ); return result; }