diff options
Diffstat (limited to 'gpr/source/app/gpr_tools')
-rw-r--r-- | gpr/source/app/gpr_tools/CMakeLists.txt | 69 | ||||
-rwxr-xr-x | gpr/source/app/gpr_tools/gpr_parse_utils.cpp | 545 | ||||
-rwxr-xr-x | gpr/source/app/gpr_tools/gpr_parse_utils.h | 34 | ||||
-rwxr-xr-x | gpr/source/app/gpr_tools/gpr_print_utils.cpp | 541 | ||||
-rwxr-xr-x | gpr/source/app/gpr_tools/gpr_print_utils.h | 34 | ||||
-rwxr-xr-x | gpr/source/app/gpr_tools/main.cpp | 203 | ||||
-rwxr-xr-x | gpr/source/app/gpr_tools/main_c.c | 346 | ||||
-rwxr-xr-x | gpr/source/app/gpr_tools/main_c.h | 34 | ||||
-rwxr-xr-x | gpr/source/app/gpr_tools/stdcpp_utils.h | 138 |
9 files changed, 1944 insertions, 0 deletions
diff --git a/gpr/source/app/gpr_tools/CMakeLists.txt b/gpr/source/app/gpr_tools/CMakeLists.txt new file mode 100644 index 0000000..ecf9828 --- /dev/null +++ b/gpr/source/app/gpr_tools/CMakeLists.txt @@ -0,0 +1,69 @@ +# executable +set( EXE_NAME gpr_tools ) + +# get source and include files +file( GLOB GPRTOOLS_SRC_FILES "*.c" "*.cpp" ) +file( GLOB GPRTOOLS_INC_FILES "*.h" "../common/*.h" ) + +# add include files from other folders +include_directories( "../common" ) +include_directories( "../common/cJSON" ) +include_directories( "../common/argument_parser" ) +include_directories( "../common/TinyJPEG" ) +include_directories( "../../lib/common/public" ) +include_directories( "../../lib/vc5_common" ) + +if(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/vc5_decoder") + include_directories( "../../lib/vc5_decoder" ) + add_definitions("-DGPR_READING=1") +else(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/vc5_decoder") + add_definitions("-DGPR_READING=0") +endif(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/vc5_decoder") + +if(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/vc5_encoder") + include_directories( "../../lib/vc5_encoder" ) + add_definitions("-DGPR_WRITING=1") +else(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/vc5_encoder") + add_definitions("-DGPR_WRITING=0") +endif(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/vc5_encoder") + +include_directories( "../../lib/md5_lib" ) +include_directories( "../../lib/dng_sdk" ) +include_directories( "../../lib/gpr_sdk/public" ) + +if(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/tiny_jpeg") + include_directories( "../../lib/tiny_jpeg" ) + add_definitions("-DGPR_JPEG_AVAILABLE=1") +else(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/tiny_jpeg") + add_definitions("-DGPR_JPEG_AVAILABLE=0") +endif(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/tiny_jpeg") + +# add executable +add_executable( ${EXE_NAME} ${GPRTOOLS_SRC_FILES} ${GPRTOOLS_INC_FILES} ) + +# Linked libraries +target_link_libraries( ${EXE_NAME} gpr_sdk ) + +if(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/tiny_jpeg") + target_link_libraries( ${EXE_NAME} tiny_jpeg ) +endif(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/tiny_jpeg") + +target_link_libraries( ${EXE_NAME} dng_sdk xmp_core ) + +if(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/vc5_decoder") + target_link_libraries( ${EXE_NAME} vc5_decoder ) +endif(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/vc5_decoder") + +if(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/vc5_encoder") + target_link_libraries( ${EXE_NAME} vc5_encoder ) +endif(EXISTS "${CMAKE_SOURCE_DIR}/source/lib/vc5_encoder") + +target_link_libraries( ${EXE_NAME} vc5_common common md5_lib expat_lib cJSON argument_parser ) + +# In order to use Carbon API, define qEnableCarbon in gpr_platform.h and uncomment code below +# if (APPLE) +# target_link_libraries( ${EXE_NAME} "-framework Carbon" ) +# endif (APPLE) + +# set the folder where to place the projects +set_target_properties( ${EXE_NAME} PROPERTIES FOLDER app ) diff --git a/gpr/source/app/gpr_tools/gpr_parse_utils.cpp b/gpr/source/app/gpr_tools/gpr_parse_utils.cpp new file mode 100755 index 0000000..c31ca7d --- /dev/null +++ b/gpr/source/app/gpr_tools/gpr_parse_utils.cpp @@ -0,0 +1,545 @@ +/*! @file gpr_parse_utils.cpp + * + * @brief Parsing utilities for gpr_tools + * + * (C) Copyright 2018 GoPro Inc (http://gopro.com/). + * + * Licensed under either: + * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0 + * - MIT license, http://opensource.org/licenses/MIT + * at your option. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gpr_parse_utils.h" +#include "stdcpp_utils.h" + +#include "cJSON.h" + +#include "dng_stream.h" +#include "dng_misc_opcodes.h" +#include "dng_gain_map.h" + +#define MAX_BUF_SIZE 16000 + +void parse_gps_info( cJSON* pGpsInfo, gpr_gps_info& exif_info ) +{ + exif_info.gps_info_valid = false; +} + +void parse_exif_info( cJSON* pExifInfo, gpr_exif_info& exif_info ) +{ + cJSON* pJSON = pExifInfo->child; + + strcpy( exif_info.camera_make, pJSON->valuestring ); + pJSON = pJSON->next; + + strcpy( exif_info.camera_model, pJSON->valuestring ); + pJSON = pJSON->next; + + strcpy( exif_info.camera_serial, pJSON->valuestring ); + pJSON = pJSON->next; + + strcpy( exif_info.software_version, pJSON->valuestring ); + pJSON = pJSON->next; + + strcpy( exif_info.user_comment, pJSON->valuestring ); + pJSON = pJSON->next; + + strcpy( exif_info.image_description, pJSON->valuestring ); + pJSON = pJSON->next; + + exif_info.exposure_time.numerator = pJSON->child->valueint; + exif_info.exposure_time.denominator = pJSON->child->next->valueint; + pJSON = pJSON->next; + + exif_info.f_stop_number.numerator = pJSON->child->valueint; + exif_info.f_stop_number.denominator = pJSON->child->next->valueint; + pJSON = pJSON->next; + + exif_info.aperture.numerator = pJSON->child->valueint; + exif_info.aperture.denominator = pJSON->child->next->valueint; + pJSON = pJSON->next; + + exif_info.exposure_program = (gpr_exposure_program)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.iso_speed_rating = pJSON->valueint; + pJSON = pJSON->next; + +// strcpy( exif_info.date_time_original, pJSON->valuestring ); + pJSON = pJSON->next; + +// strcpy( exif_info.date_time_digitized, pJSON->valuestring ); + pJSON = pJSON->next; + + exif_info.exposure_bias.numerator = pJSON->child->valueint; + exif_info.exposure_bias.denominator = pJSON->child->next->valueint; + pJSON = pJSON->next; + + exif_info.light_source = (gpr_light_source)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.flash = (gpr_flash)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.focal_length.numerator = pJSON->child->valueint; + exif_info.focal_length.denominator = pJSON->child->next->valueint; + pJSON = pJSON->next; + + exif_info.sharpness = (gpr_sharpness)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.saturation = pJSON->valueint; + pJSON = pJSON->next; + + exif_info.gain_control = (gpr_gain_control)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.contrast = (gpr_contrast)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.scene_capture_type = (gpr_scene_capture_type)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.exposure_mode = (gpr_exposure_mode)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.focal_length_in_35mm_film = pJSON->valueint; + pJSON = pJSON->next; + + exif_info.digital_zoom.numerator = pJSON->child->valueint; + exif_info.digital_zoom.denominator = pJSON->child->next->valueint; + pJSON = pJSON->next; + + exif_info.white_balance = (gpr_white_balance)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.scene_type = (gpr_scene_type)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.file_source = (gpr_file_source)pJSON->valueint; + pJSON = pJSON->next; + + exif_info.sensing_method = (gpr_sensing_method)pJSON->valueint; + pJSON = pJSON->next; + + parse_gps_info( pJSON, exif_info.gps_info ); +} + +void parse_profile_info( cJSON* pProfileInfo, gpr_profile_info& profile_info ) +{ + cJSON* pJSON = pProfileInfo->child; + + profile_info.compute_color_matrix = pJSON->valueint > 0 ? true : false; + pJSON = pJSON->next; + + profile_info.matrix_weighting = pJSON->valuedouble; + pJSON = pJSON->next; + + + { + cJSON* child = pJSON->child; + + profile_info.wb1[0] = child->valuedouble; + child = child->next; + + profile_info.wb1[1] = child->valuedouble; + child = child->next; + + profile_info.wb1[2] = child->valuedouble; + + pJSON = pJSON->next; + } + + { + cJSON* child = pJSON->child; + profile_info.wb2[0] = child->valuedouble; + child = child->next; + + profile_info.wb2[1] = child->valuedouble; + child = child->next; + + profile_info.wb2[2] = child->valuedouble; + + pJSON = pJSON->next; + } + + { + cJSON* child = pJSON->child; + profile_info.cam_to_srgb_1[0][0] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_1[0][1] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_1[0][2] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_1[1][0] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_1[1][1] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_1[1][2] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_1[2][0] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_1[2][1] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_1[2][2] = child->valuedouble; + + pJSON = pJSON->next; + } + + { + cJSON* child = pJSON->child; + profile_info.cam_to_srgb_2[0][0] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_2[0][1] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_2[0][2] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_2[1][0] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_2[1][1] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_2[1][2] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_2[2][0] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_2[2][1] = child->valuedouble; + child = child->next; + + profile_info.cam_to_srgb_2[2][2] = child->valuedouble; + + pJSON = pJSON->next; + } + + { + cJSON* child = pJSON->child; + profile_info.color_matrix_1[0][0] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_1[0][1] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_1[0][2] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_1[1][0] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_1[1][1] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_1[1][2] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_1[2][0] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_1[2][1] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_1[2][2] = child->valuedouble; + + pJSON = pJSON->next; + } + + { + cJSON* child = pJSON->child; + profile_info.color_matrix_2[0][0] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_2[0][1] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_2[0][2] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_2[1][0] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_2[1][1] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_2[1][2] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_2[2][0] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_2[2][1] = child->valuedouble; + child = child->next; + + profile_info.color_matrix_2[2][2] = child->valuedouble; + + pJSON = pJSON->next; + } + + profile_info.illuminant1 = pJSON->valueint; + pJSON = pJSON->next; + + profile_info.illuminant2 = pJSON->valueint; +} + +void parse_tuning_info( cJSON* pTuningInfo, gpr_tuning_info& tuning_info ) +{ + cJSON* pJSON = pTuningInfo->child; + + tuning_info.orientation = (GPR_ORIENTATION)pJSON->valueint; + pJSON = pJSON->next; + + { + cJSON* child = pJSON->child; + tuning_info.static_black_level.r_black = child->valueint; + child = child->next; + + tuning_info.static_black_level.g_r_black = child->valueint; + child = child->next; + + tuning_info.static_black_level.g_b_black = child->valueint; + child = child->next; + + tuning_info.static_black_level.b_black = child->valueint; + + pJSON = pJSON->next; + } + + { + cJSON* child = pJSON->child; + tuning_info.dgain_saturation_level.level_red = child->valueint; + child = child->next; + + tuning_info.dgain_saturation_level.level_green_even = child->valueint; + child = child->next; + + tuning_info.dgain_saturation_level.level_green_odd = child->valueint; + child = child->next; + + tuning_info.dgain_saturation_level.level_blue = child->valueint; + + pJSON = pJSON->next; + } + + { + cJSON* child = pJSON->child; + tuning_info.wb_gains.r_gain = (float_t)child->valuedouble; + child = child->next; + + tuning_info.wb_gains.g_gain = (float_t)child->valuedouble; + child = child->next; + + tuning_info.wb_gains.b_gain = (float_t)child->valuedouble; + + pJSON = pJSON->next; + } + + { + cJSON* child = pJSON->child; + tuning_info.ae_info.iso_value = child->valueint; + child = child->next; + + tuning_info.ae_info.shutter_time = child->valueint; + + pJSON = pJSON->next; + } + + tuning_info.noise_scale = pJSON->valuedouble; + pJSON = pJSON->next; + + tuning_info.noise_offset = pJSON->valuedouble; + pJSON = pJSON->next; + + tuning_info.warp_red_coefficient = pJSON->valuedouble; + pJSON = pJSON->next; + + tuning_info.warp_blue_coefficient = pJSON->valuedouble; + pJSON = pJSON->next; + + if( pJSON->child ) + { + cJSON* size = pJSON->child; + int buffer_size = size->valueint; + + tuning_info.gain_map.size = buffer_size; + + cJSON* channel = size->next; + + int channel_index = 0; + while( channel && channel_index < 4 && buffer_size > 0 ) + { + cJSON* child = channel->child; + + int version = child->valueint; + child = child->next; + + int flags = child->valueint; + child = child->next; + + int bytes = child->valueint; + child = child->next; + + char gain_map_buffer[MAX_BUF_SIZE]; + + tuning_info.gain_map.buffers[channel_index] = (char*)malloc( buffer_size ); + + dng_stream gain_map_stream ( gain_map_buffer, buffer_size ); + + gain_map_stream.Put_uint32( version ); + gain_map_stream.Put_uint32( flags ); + gain_map_stream.Put_uint32( bytes ); + + { + cJSON* _child = child->child; + dng_rect rect; + rect.t = _child->valueint; + _child = _child->next; + + rect.l = _child->valueint; + _child = _child->next; + + rect.b = _child->valueint; + _child = _child->next; + + rect.r = _child->valueint; + + dng_area_spec area_spec(rect, 0, 1, 2, 2); + area_spec.PutData (gain_map_stream); + + child = child->next; + } + + + dng_point points; + + { + cJSON* _child = child->child; + + points.h = _child->valueint; + _child = _child->next; + + points.v = _child->valueint; + + child = child->next; + } + + dng_point_real64 spacing; + + { + cJSON* _child = child->child; + + spacing.h = _child->valuedouble; + _child = _child->next; + + spacing.v = _child->valuedouble; + + child = child->next; + } + + dng_point_real64 origin; + + { + cJSON* _child = child->child; + + origin.h = _child->valuedouble; + _child = _child->next; + + origin.v = _child->valuedouble; + + child = child->next; + } + + dng_gain_map gain_map( gDefaultDNGMemoryAllocator, points, spacing, origin, 1 ); + + cJSON* _child = child->child; + for (int row = 0; row < points.v; row++) + { + for (int col = 0; col < points.h; col++) + { + gain_map.Entry (row, col, 0) = (float_t)_child->valuedouble; + _child = _child->next; + } + } + + gain_map.PutStream( gain_map_stream ); + + memcpy( tuning_info.gain_map.buffers[channel_index], gain_map_buffer, buffer_size ); + + channel = channel->next; + + channel_index++; + } + } + + pJSON = pJSON->next; + + tuning_info.pixel_format = (GPR_PIXEL_FORMAT)pJSON->valueint; +} + +int gpr_parameters_parse( gpr_parameters* parameters, const char* input_file_path ) +{ + gpr_buffer buffer; + + if( read_from_file( &buffer, input_file_path, malloc, free) ) + { + return -2; + } + + const char* return_parse_end; + + cJSON* pRoot = cJSON_ParseWithOpts( (const char*)buffer.buffer, &return_parse_end, 0 ); + + if( pRoot == NULL ) + { + printf( "Error parsing %s \n", input_file_path ); + printf( "Error: %s", return_parse_end ); + return -1; + } + + cJSON* pJSON = pRoot->child; + + parameters->input_width = pJSON->valueint; + pJSON = pJSON->next; + + parameters->input_height = pJSON->valueint; + pJSON = pJSON->next; + + parameters->input_pitch = pJSON->valueint; + pJSON = pJSON->next; + + parameters->fast_encoding = pJSON->valueint > 0 ? true : false; + pJSON = pJSON->next; + + parameters->gpmf_payload.size = pJSON->valueint; + pJSON = pJSON->next; + + parse_exif_info( pJSON, parameters->exif_info ); + pJSON = pJSON->next; + + parse_profile_info( pJSON, parameters->profile_info ); + pJSON = pJSON->next; + + parse_tuning_info( pJSON, parameters->tuning_info ); + + free( buffer.buffer ); + + return 0; +} diff --git a/gpr/source/app/gpr_tools/gpr_parse_utils.h b/gpr/source/app/gpr_tools/gpr_parse_utils.h new file mode 100755 index 0000000..b4ebdaa --- /dev/null +++ b/gpr/source/app/gpr_tools/gpr_parse_utils.h @@ -0,0 +1,34 @@ +/*! @file gpr_parse_utils.h + * + * @brief Parsing utilities for gpr_tools + * + * (C) Copyright 2018 GoPro Inc (http://gopro.com/). + * + * Licensed under either: + * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0 + * - MIT license, http://opensource.org/licenses/MIT + * at your option. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GPR_PARSE_UTILS_H +#define GPR_PARSE_UTILS_H + +#include "gpr.h" + +#ifdef __cplusplus +extern "C" { +#endif + + int gpr_parameters_parse( gpr_parameters* parameters, const char* input_file_path ); + +#ifdef __cplusplus +} +#endif + +#endif // GPR_PARSE_UTILS_H diff --git a/gpr/source/app/gpr_tools/gpr_print_utils.cpp b/gpr/source/app/gpr_tools/gpr_print_utils.cpp new file mode 100755 index 0000000..610db75 --- /dev/null +++ b/gpr/source/app/gpr_tools/gpr_print_utils.cpp @@ -0,0 +1,541 @@ +/*! @file gpr_print_utils.cpp + * + * @brief Printing utilities for gpr_tools + * + * (C) Copyright 2018 GoPro Inc (http://gopro.com/). + * + * Licensed under either: + * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0 + * - MIT license, http://opensource.org/licenses/MIT + * at your option. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gpr_print_utils.h" + +#include <iostream> +#include <fstream> +#include <algorithm> + +using namespace std; + +#include "dng_stream.h" +#include "dng_misc_opcodes.h" +#include "dng_gain_map.h" + +uint32 spaces = 0; + +ostream& operator<<(ostream& output, const gpr_signed_rational& x) +{ + output << "[" << x.numerator << "," << x.denominator << "]"; + + return output; +} + +ostream& operator<<(ostream& output, const gpr_unsigned_rational& x) +{ + output << "[" << x.numerator << "," << x.denominator << "]"; + + return output; +} + +ostream& operator<<(ostream& output, const gpr_date_and_time& x) +{ + output << "\"" << x.year << "-" << x.month << "-" << x.day << " " << x.hour << ":" << x.minute << ":" << x.second << "\""; + + return output; +} + +ostream& operator<<(ostream& output, const dng_area_spec& x) +{ + dng_rect area = x.Area(); + + output << "{ \"top\" : " << area.t << ", \"left\" : " << area.l << ", \"bottom\" : " << area.b << ", \"right\" : " << area.r << ", \"row_pitch\" : " << x.RowPitch() << ", \"col_pitch\" : " << x.ColPitch() << " }"; + + return output; +} + +ostream& operator<<(ostream& output, const dng_point& x) +{ + output << "{ \"h\" : " << x.h << ", \"v\" : " << x.v << " }"; + + return output; +} + +ostream& operator<<(ostream& output, const dng_point_real64& x) +{ + output << "{ \"h\" : " << x.h << ", \"v\" : " << x.v << " }"; + + return output; +} + +void start_tag( const string& tag_id, ostream& output ) +{ + output << "{" << endl; + spaces += 2; +} + +void end_tag( const string& tag_id, ostream& output ) +{ + spaces -= 2; + output << string( spaces, ' ' ).c_str() << "}"; +} + +template<class T> +void print_val(ostream& output, string tag, T x, int N = 0, bool last = false) +{ + if( last ) + output << string( spaces, ' ' ).c_str() << "\"" << tag.c_str() << "\": " << x << "" << endl; + else + output << string( spaces, ' ' ).c_str() << "\"" << tag.c_str() << "\": " << x << "," << endl; +} + +template<> +void print_val<const char*>(ostream& output, string tag, const char* x, int N, bool last) +{ + if( last ) + output << string( spaces, ' ' ).c_str() << "\"" << tag.c_str() << "\": " << "\"" << x << "\"" << "" << endl; + else + output << string( spaces, ' ' ).c_str() << "\"" << tag.c_str() << "\": " << "\"" << x << "\"" << "," << endl; +} + +template<> +void print_val<const double*>(ostream& output, string tag, const double* x, int N, bool last) +{ + output << string( spaces, ' ' ).c_str() << "\"" << tag.c_str() << "\": " << "["; + + for (int i = 0; i < N; i++) + { + if( i < N - 1 ) + output << x[i] << ","; + else + output << x[i]; + } + + if( last ) + output << "]" << "" << endl; + else + output << "]" << "," << endl; +} + +template<> +void print_val<const gpr_unsigned_rational*>(ostream& output, string tag, const gpr_unsigned_rational* x, int N, bool last) +{ + output << string( spaces, ' ' ).c_str() << "\"" << tag.c_str() << "\": " << "["; + + for (int i = 0; i < N; i++) + { + if( i < N - 1 ) + output << x[i] << ","; + else + output << x[i]; + } + + if( last ) + output << "]" << "" << endl; + else + output << "]" << "," << endl; +} + +template<class T, int N> +void print_val(ostream& output, string tag, T x[N][N]) +{ + output << string( spaces, ' ' ) << "\"" << tag << "\": " << "["; + output << x[0][0] << ","; + output << x[0][1] << ","; + output << x[0][2] << ","; + output << x[1][0] << ","; + output << x[1][1] << ","; + output << x[1][2] << ","; + output << x[2][0] << ","; + output << x[2][1] << ","; + output << x[2][2]; + output << "]"; + + output << "," << endl; +} + +ostream& operator<<(ostream& output, const gpr_gain_map& x) +{ + start_tag( "gain_map", output ); + + if( x.size > 0 ) + { + print_val( output, "size", x.size ); + + for (int i = 0; i < 4; i++) + { + dng_stream gain_map_stream (x.buffers[i], x.size); + + output << string( spaces, ' ' ).c_str() << "\"" << "channel_" << i << "\": "; + start_tag( "channel", output ); + + print_val( output, "version", gain_map_stream.Get_uint32() ); + + print_val( output, "flags", gain_map_stream.Get_uint32() ); + + print_val( output, "bytes", gain_map_stream.Get_uint32() ); + + dng_area_spec area_spec; + area_spec.GetData (gain_map_stream); + + print_val( output, "area", area_spec ); + + AutoPtr<dng_gain_map> gain_map; + + gain_map.Reset (dng_gain_map::GetStream (gain_map_stream, gDefaultDNGMemoryAllocator)); + + dng_point points = gain_map.Get()->Points(); + dng_point_real64 spacing = gain_map.Get()->Spacing(); + dng_point_real64 origin = gain_map.Get()->Origin(); + + print_val( output, "points", points ); + print_val( output, "spacing", spacing ); + print_val( output, "origin", origin ); + + output << string( spaces, ' ' ).c_str() << "\"" << "values" << "\": ["; + + for (int row = 0; row < points.v; row++) + { + for (int col = 0; col < points.h; col++) + { + output << gain_map->Entry (row, col, 0); + + if( row == points.v - 1 && col == points.h - 1 ) + output << " "; + else + output << ", "; + } + } + output << "] " << endl; + + end_tag( "channel", output ); + + if( i < 3 ) + output << ", " << endl; + } + } + + end_tag( "gain_map", output ); + + return output; +} + +ostream& operator<<(ostream& output, const gpr_gps_info& x) +{ + start_tag( "gps_info", output ); + + if( x.gps_info_valid ) + { + print_val( output, "gps_info_valid", x.gps_info_valid ); + + print_val( output, "version_id", x.version_id ); + + print_val( output, "latitude_ref", x.latitude_ref ); + + print_val( output, "latitude", x.latitude, 3 ); + + print_val( output, "longitude_ref", x.longitude_ref ); + + print_val( output, "longitude", x.longitude, 3 ); + + print_val( output, "altitude_ref", (uint32)x.altitude_ref ); + + print_val( output, "altitude", x.altitude ); + + print_val( output, "time_stamp", x.time_stamp ); + + print_val( output, "satellites", x.satellites ); + + print_val( output, "status", x.status ); + + print_val( output, "dop", x.dop ); + + print_val( output, "speed_ref", x.speed_ref ); + + print_val( output, "speed", x.speed ); + + print_val( output, "track_ref", x.track_ref ); + + print_val( output, "track", x.track ); + + print_val( output, "img_direction_ref", x.img_direction_ref ); + + print_val( output, "img_direction", x.img_direction ); + + print_val( output, "map_datum", x.map_datum ); + + print_val( output, "dest_latitude_ref", x.dest_latitude_ref ); + + print_val( output, "dest_latitude", x.dest_latitude ); + + print_val( output, "dest_longitude_ref", x.dest_longitude_ref ); + + print_val( output, "dest_longitude", x.dest_longitude ); + + print_val( output, "dest_bearing_ref", x.dest_bearing_ref ); + + print_val( output, "dest_bearing", x.dest_bearing ); + + print_val( output, "dest_distance_ref", x.dest_distance_ref ); + + print_val( output, "dest_distance", x.dest_distance ); + + print_val( output, "processing_method", x.processing_method ); + + print_val( output, "area_information", x.area_information ); + + print_val( output, "date_stamp", x.date_stamp ); + + print_val( output, "differential", x.differential, 0, true ); + } + else + { + print_val( output, "gps_info_valid", x.gps_info_valid, 0, true ); + } + + end_tag( "gps_info", output ); + + return output; +} + +ostream& operator<<(ostream& output, const gpr_exif_info& x) +{ + start_tag( "exif_info", output ); + + print_val( output, "camera_make", x.camera_make ); + + print_val( output, "camera_model", x.camera_model ); + + print_val( output, "camera_serial", x.camera_serial ); + + print_val( output, "software_version", x.software_version ); + + print_val( output, "user_comment", x.user_comment ); + + { + string str_image_description = x.image_description; + std::replace( str_image_description.begin(), str_image_description.end(), '\\', '/'); + print_val( output, "image_description", str_image_description.c_str() ); + } + + print_val( output, "exposure_time", x.exposure_time ); + + print_val( output, "f_stop_number", x.f_stop_number ); + + print_val( output, "aperture", x.aperture ); + + print_val( output, "exposure_program", x.exposure_program ); + + print_val( output, "iso_speed_rating", x.iso_speed_rating ); + + print_val( output, "date_time_original", x.date_time_original ); + + print_val( output, "date_time_digitized", x.date_time_digitized ); + + print_val( output, "exposure_bias", x.exposure_bias ); + + print_val( output, "light_source", x.light_source ); + + print_val( output, "flash", x.flash ); + + print_val( output, "focal_length", x.focal_length ); + + print_val( output, "sharpness", x.sharpness ); + + print_val( output, "saturation", x.saturation ); + + print_val( output, "gain_control", x.gain_control ); + + print_val( output, "contrast", x.contrast ); + + print_val( output, "scene_capture_type", x.scene_capture_type ); + + print_val( output, "exposure_mode", x.exposure_mode ); + + print_val( output, "focal_length_in_35mm_film", x.focal_length_in_35mm_film ); + + print_val( output, "digital_zoom", x.digital_zoom ); + + print_val( output, "white_balance", x.white_balance ); + + print_val( output, "scene_type", x.scene_type ); + + print_val( output, "file_source", x.file_source ); + + print_val( output, "sensing_method", x.sensing_method ); + + print_val( output, "gps_info", x.gps_info, 0, true ); + + end_tag( "exif_info", output ); + + return output; +} + +ostream& operator<<(ostream& output, const gpr_profile_info& x) +{ + start_tag( "profile_info", output ); + + print_val( output, "compute_color_matrix", x.compute_color_matrix ); + + print_val( output, "matrix_weighting", x.matrix_weighting ); + + print_val( output, "wb1", x.wb1, 3, false ); + + print_val( output, "wb2", x.wb2, 3, false ); + + print_val( output, "cam_to_srgb_1", (const double*)x.cam_to_srgb_1, 9, false ); + + print_val( output, "cam_to_srgb_2", (const double*)x.cam_to_srgb_2, 9, false ); + + print_val( output, "color_matrix_1", (const double*)x.color_matrix_1, 9, false ); + + print_val( output, "color_matrix_2", (const double*)x.color_matrix_2, 9, false ); + + print_val( output, "illuminant1", x.illuminant1, 0, false ); + + print_val( output, "illuminant2", x.illuminant2, 0, true ); + + end_tag( "profile_info", output ); + + return output; +} + +ostream& operator<<(ostream& output, const gpr_static_black_level& x) +{ + start_tag( "static_black_level", output ); + + print_val( output, "r_black", x.r_black ); + + print_val( output, "g_r_black", x.g_r_black ); + + print_val( output, "g_b_black", x.g_b_black ); + + print_val( output, "b_black", x.b_black, 0, true ); + + end_tag( "static_black_level", output ); + + return output; +} + +ostream& operator<<(ostream& output, const gpr_saturation_level& x) +{ + start_tag( "dgain_saturation_level", output ); + + print_val( output, "level_red", x.level_red ); + + print_val( output, "level_green_even", x.level_green_even ); + + print_val( output, "level_green_odd", x.level_green_odd ); + + print_val( output, "level_blue", x.level_blue, 0, true ); + + end_tag( "dgain_saturation_level", output ); + + return output; +} + +ostream& operator<<(ostream& output, const gpr_white_balance_gains& x) +{ + start_tag( "wb_gains", output ); + + print_val( output, "r_gain", x.r_gain ); + + print_val( output, "g_gain", x.g_gain ); + + print_val( output, "b_gain", x.b_gain, 0, true ); + + end_tag( "wb_gains", output ); + + return output; +} + +ostream& operator<<(ostream& output, const gpr_auto_exposure_info& x) +{ + start_tag( "ae_info", output ); + + print_val( output, "iso_value", x.iso_value ); + + print_val( output, "shutter_time", x.shutter_time, 0, true ); + + end_tag( "ae_info", output ); + + return output; +} + +ostream& operator<<(ostream& output, const gpr_tuning_info& x) +{ + start_tag( "tuning_info", output ); + + print_val( output, "orientation", x.orientation ); + + print_val( output, "static_black_level", x.static_black_level ); + + print_val( output, "dgain_saturation_level", x.dgain_saturation_level ); + + print_val( output, "wb_gains", x.wb_gains ); + + print_val( output, "ae_info", x.ae_info ); + + print_val( output, "noise_scale", x.noise_scale ); + + print_val( output, "noise_offset", x.noise_offset ); + + print_val( output, "warp_red_coefficient", x.warp_red_coefficient ); + + print_val( output, "warp_blue_coefficient", x.warp_blue_coefficient ); + + print_val( output, "gain_map", x.gain_map ); + + print_val( output, "pixel_format", x.pixel_format, 0, true ); + + end_tag( "tuning_info", output ); + + return output; +} + +ostream& operator<<(ostream& output, const gpr_parameters& x) +{ + print_val( output, "input_width", x.input_width ); + + print_val( output, "input_height", x.input_height ); + + print_val( output, "input_pitch", x.input_pitch ); + + print_val( output, "fast_encoding", x.fast_encoding ); + + // print_val( output, "gpmf_payload_buffer", x.gpmf_payload.buffer ); + + print_val( output, "gpmf_payload_size", x.gpmf_payload.size ); + + print_val( output, "exif_info", x.exif_info ); + + print_val( output, "profile_info", x.profile_info ); + + print_val( output, "tuning_info", x.tuning_info, 0, true ); + + return output; +} + +int gpr_parameters_print( const gpr_parameters* parameters, const char* output_file_path ) +{ + ofstream output; + ostream* output_ref = &cout; + + if( output_file_path ) + { + output.open (output_file_path); + output_ref = &output; + } + + start_tag( "", *output_ref ); + *output_ref << *parameters; + end_tag( "", *output_ref ); + + return 0; +} diff --git a/gpr/source/app/gpr_tools/gpr_print_utils.h b/gpr/source/app/gpr_tools/gpr_print_utils.h new file mode 100755 index 0000000..34dc63a --- /dev/null +++ b/gpr/source/app/gpr_tools/gpr_print_utils.h @@ -0,0 +1,34 @@ +/*! @file gpr_print_utils.h + * + * @brief Printing utilities for gpr_tools + * + * (C) Copyright 2018 GoPro Inc (http://gopro.com/). + * + * Licensed under either: + * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0 + * - MIT license, http://opensource.org/licenses/MIT + * at your option. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GPR_PRINT_UTILS_H +#define GPR_PRINT_UTILS_H + +#include "gpr.h" + +#ifdef __cplusplus +extern "C" { +#endif + + int gpr_parameters_print( const gpr_parameters* parameters, const char* output_file_path ); + +#ifdef __cplusplus +} +#endif + +#endif // GPR_PRINT_UTILS_H diff --git a/gpr/source/app/gpr_tools/main.cpp b/gpr/source/app/gpr_tools/main.cpp new file mode 100755 index 0000000..e182028 --- /dev/null +++ b/gpr/source/app/gpr_tools/main.cpp @@ -0,0 +1,203 @@ +/*! @file main.cpp + * + * @brief Main program file for the gpr_tools. + * + * (C) Copyright 2018 GoPro Inc (http://gopro.com/). + * + * Licensed under either: + * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0 + * - MIT license, http://opensource.org/licenses/MIT + * at your option. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <string.h> + +#include "argument_parser.h" + +#include "gpr.h" +#include "gpr_buffer.h" +#include "gpr_print_utils.h" +#include "main_c.h" + +#include "common_app_def.h" + +using namespace std; + +class my_argument_parser : public argument_parser +{ +protected: + + bool help; + + bool verbose; + +public: + + bool dump_gpr_parameters; + + string jpg_preview_file_path; + + int jpg_preview_file_width; + + int jpg_preview_file_height; + + int input_width; + + int input_height; + + int input_pitch; + + int input_skip_rows; + + string input_pixel_format; + + string input_file_path; + + string gpmf_file_path; + + string rgb_file_resolution; + + int rgb_file_bits; + + string output_file_path; + + string apply_gpr_parameters; + +public: + + bool get_verbose() { return verbose; } + + bool get_help() { return help; } + + void set_options() + { + command_options.addOptions() + /* long and short name */ /* variable to update */ /* default value */ /* help text */ + ("help", help, false, "Prints this help text") + + ("verbose", verbose, false, "Verbosity of the output") + + ("JpgPreviewFilePath,P", jpg_preview_file_path, string(""), "Preview jpg file path") + ("JpgPreviewFileWidth,W", jpg_preview_file_width, 0, "Preview jpg file width") + ("JpgPreviewFileHeight,H", jpg_preview_file_height, 0, "Preview jpg file height") + + ("DumpGprParameters,d", dump_gpr_parameters, false, "Dump GPR parameters to standard output") + + ("InputSkipRows,s", input_skip_rows, 0, "Input image rows to skip") + + ("InputFilePath,i", input_file_path, string(""), "Input file path.\n(files types: GPR, DNG, RAW)") + + ("InputWidth,w", input_width, 4000, "Input image width in pixel samples [4000]") + + ("InputHeight,h", input_height, 3000, "Input image height in pixel samples [3000]") + + ("InputPitch,p", input_pitch, 8000, "Input image pitch in bytes [8000]") + + ("InputPixelFormat,x", input_pixel_format, string("rggb14"), "Input pixel format \n(rggb12, rggb12p, [rggb14], gbrg12, gbrg12p)") + + ("ApplyGprParameters,a", apply_gpr_parameters, string(""), "Parameters to use for GPR or DNG file.") + + ("GPMFFilePath,g", gpmf_file_path, string(""), "GPMF file path") + + ("RgbFileResolution,r", rgb_file_resolution, string(""), "Output RGB resolution \n[1:1, 2:1, 4:1, 8:1. 16:1]") + ("RgbFileBits,b", rgb_file_bits, 8, "Output RGB bits [8]") + + ("OutputFilePath,o", output_file_path, string(""), "Output file path.\n(files types: GPR, DNG, PPM, RAW, JPG)"); + ; + } +}; + +int dng_dump(const char* input_file_path) +{ + gpr_allocator allocator; + allocator.Alloc = malloc; + allocator.Free = free; + + gpr_buffer input_buffer = { NULL, 0 }; + + gpr_parameters params; + + gpr_parameters_set_defaults(¶ms); + + if( read_from_file( &input_buffer, input_file_path, allocator.Alloc, allocator.Free ) != 0 ) + { + return -1; + } + + int success = gpr_parse_metadata( &allocator, &input_buffer, ¶ms ); + + if( success ) + { + gpr_parameters_print( ¶ms, NULL ); + } + + return 0; +} + +int main(int argc, char *argv []) +{ + my_argument_parser args; + + + char zerotag[MAX_STDOUT_LINE]; + sprintf(zerotag, "[%5d-ms] ", 0); + + char line[MAX_STDOUT_LINE]; + sprintf( line, "GPR Tools Version %d.%d.%d [%s @ %s] ", GPR_VERSION_MAJOR, GPR_VERSION_MINOR, GPR_VERSION_REVISION, GIT_BRANCH, GIT_COMMIT_HASH ); + + if( args.parse(argc, argv, line, zerotag) ) + { + printf("\n"); + printf("-- Example Commnads (please see data/tests/run_tests.sh for more examples) --\n"); + printf("GPR to DNG: \n"); + printf(" %s -i ./data/samples/Hero6/GOPR0024.GPR -o ./data/samples/Hero6/GOPR0024.DNG \n\n", argv[0] ); + printf("GPR to RGB (PPM format in 1000x750 resolution): \n"); + printf(" %s -i ./data/samples/Hero6/GOPR0024.GPR -o ./data/samples/Hero6/GOPR0024.PPM -r 4:1 \n\n", argv[0] ); + printf("GPR to RGB (JPG format in 500x375 resolution): \n"); + printf(" %s -i ./data/samples/Hero6/GOPR0024.GPR -o ./data/samples/Hero6/GOPR0024.JPG -r 8:1 \n\n", argv[0] ); + printf("Analyze a GPR or DNG file and output metadata parameters to a file: \n"); + printf(" %s -i ./data/samples/Hero6/GOPR0024.GPR -d 1 > ./data/samples/Hero6/GOPR0024.TXT \n\n", argv[0] ); + printf("Read RAW pixel data, along with gpr parameters (from a file) and apply to an output GPR or DNG file: \n"); + printf(" %s -i ./data/samples/Hero6/GOPR0024.RAW -o ./data/samples/Hero6/GOPR0024.DNG -a ./data/samples/Hero6/GOPR0024.TXT \n\n", argv[0] ); + + return -1; + } + + if( args.dump_gpr_parameters ) + { + if( dng_dump(args.input_file_path.c_str()) != 0 ) + return -1; + } + else + { + string ext = strrchr( args.input_file_path.c_str(),'.'); + + if( args.output_file_path == string("") && ( ext == string(".GPR") || ext == string(".gpr") ) ) + { + args.output_file_path = args.input_file_path; + args.output_file_path.erase(args.output_file_path.find_last_of("."), string::npos); + + args.output_file_path = args.output_file_path + string(".DNG"); + } + } + + fprintf( stderr, "%s Input File: %s \n", zerotag, args.input_file_path.c_str() ); + fprintf( stderr, "%s Output File: %s \n", zerotag, args.output_file_path.c_str() ); + + if( args.output_file_path != "" ) + { + return dng_convert_main(args.input_file_path.c_str(), args.input_width, args.input_height, args.input_pitch, args.input_skip_rows, args.input_pixel_format.c_str(), + args.output_file_path.c_str(), args.apply_gpr_parameters.c_str(), args.gpmf_file_path.c_str(), args.rgb_file_resolution.c_str(), args.rgb_file_bits, + args.jpg_preview_file_path.c_str(), args.jpg_preview_file_width, args.jpg_preview_file_height ); + } + + return 0; +} + diff --git a/gpr/source/app/gpr_tools/main_c.c b/gpr/source/app/gpr_tools/main_c.c new file mode 100755 index 0000000..0583b01 --- /dev/null +++ b/gpr/source/app/gpr_tools/main_c.c @@ -0,0 +1,346 @@ +/*! @file main_c.c + * + * @brief Implement C conversion routines used by gpr_tools + * + * (C) Copyright 2018 GoPro Inc (http://gopro.com/). + * + * Licensed under either: + * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0 + * - MIT license, http://opensource.org/licenses/MIT + * at your option. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <string.h> +#include <stdbool.h> + +#include "gpr.h" + +#if defined __GNUC__ +#define stricmp strcasecmp +#else +#endif // if defined __GNUC__ + +#include "main_c.h" +#include "gpr_parse_utils.h" +#include "gpr_print_utils.h" + +#if GPR_JPEG_AVAILABLE +#include "jpeg.h" +#endif + +#define MAX_FILE_PATH 256 + +typedef enum +{ + FILE_TYPE_UNKNOWN = -1, + + FILE_TYPE_RAW, + FILE_TYPE_GPR, + FILE_TYPE_DNG, + FILE_TYPE_PPM, + FILE_TYPE_JPG, + + FILE_TYPE_COUNT, + +} FILE_TYPE; + +static FILE_TYPE GetFileType( const char* file_path ) +{ + const char *extension = NULL; + + if (file_path == NULL) { + return FILE_TYPE_UNKNOWN; + } + + // Get the pathname extension + extension = strrchr(file_path, '.'); + if (extension == NULL) + { + return FILE_TYPE_UNKNOWN; + } + + if (stricmp(extension, ".raw") == 0 || stricmp(extension, ".RAW") == 0) + { + return FILE_TYPE_RAW; + } + + if (stricmp(extension, ".gpr") == 0 || stricmp(extension, ".GPR") == 0) + { + return FILE_TYPE_GPR; + } + + if (stricmp(extension, ".dng") == 0 || stricmp(extension, ".DNG") == 0 ) + { + return FILE_TYPE_DNG; + } + + if (stricmp(extension, ".ppm") == 0 || stricmp(extension, ".PPM") == 0) + { + return FILE_TYPE_PPM; + } + + if (stricmp(extension, ".jpg") == 0 || stricmp(extension, ".JPG") == 0) + { + return FILE_TYPE_JPG; + } + + return FILE_TYPE_UNKNOWN; +} + +int dng_convert_main(const char* input_file_path, unsigned int input_width, unsigned int input_height, size_t input_pitch, size_t input_skip_rows, const char* input_pixel_format, + const char* output_file_path, const char* metadata_file_path, const char* gpmf_file_path, const char* rgb_file_resolution, int rgb_file_bits, + const char* jpg_preview_file_path, int jpg_preview_file_width, int jpg_preview_file_height ) +{ + bool success; + bool write_buffer_to_file = true; + + FILE_TYPE input_file_type = GetFileType( input_file_path ); + FILE_TYPE output_file_type = GetFileType( output_file_path ); + + if( input_file_type == FILE_TYPE_UNKNOWN ) + { + printf( "Unsupported input file type" ); + return -1; + } + + if( output_file_type == FILE_TYPE_UNKNOWN ) + { + printf( "Unsupported output file type" ); + return -1; + } + + gpr_allocator allocator; + allocator.Alloc = malloc; + allocator.Free = free; + + gpr_parameters params; + gpr_parameters_set_defaults(¶ms); + + gpr_buffer input_buffer = { NULL, 0 }; + + if( read_from_file( &input_buffer, input_file_path, allocator.Alloc, allocator.Free ) != 0 ) + { + return -1; + } + + if( metadata_file_path && strcmp(metadata_file_path, "") ) + { + if( gpr_parameters_parse( ¶ms, metadata_file_path ) != 0 ) + return -1; + } + else if( input_file_type == FILE_TYPE_GPR || input_file_type == FILE_TYPE_DNG ) + { + gpr_parse_metadata( &allocator, &input_buffer, ¶ms ); + } + else + { + params.input_width = input_width; + params.input_height = input_height; + params.input_pitch = input_pitch; + + int32_t saturation_level = params.tuning_info.dgain_saturation_level.level_red; + + if( output_file_type == FILE_TYPE_GPR ) + saturation_level = (1 << 14) - 1; + else if( output_file_type == FILE_TYPE_DNG ) + saturation_level = (1 << 12) - 1; + + if( strcmp(input_pixel_format, "rggb12") == 0 ) + { + params.tuning_info.pixel_format = PIXEL_FORMAT_RGGB_12; + + if( input_pitch == -1 ) + input_pitch = input_width * 2; + } + if( strcmp(input_pixel_format, "rggb12p") == 0 ) + { + params.tuning_info.pixel_format = PIXEL_FORMAT_RGGB_12P; + + if( input_pitch == -1 ) + input_pitch = (input_width * 3 / 4) * 2; + } + else if( strcmp(input_pixel_format, "rggb14") == 0 ) + { + params.tuning_info.pixel_format = PIXEL_FORMAT_RGGB_14; + + saturation_level = (1 << 14) - 1; + + if( input_pitch == -1 ) + input_pitch = input_width * 2; + } + else if( strcmp(input_pixel_format, "gbrg12") == 0 ) + { + params.tuning_info.pixel_format = PIXEL_FORMAT_GBRG_12; + + if( input_pitch == -1 ) + input_pitch = input_width * 2; + } + else if( strcmp(input_pixel_format, "gbrg12p") == 0 ) + { + params.tuning_info.pixel_format = PIXEL_FORMAT_GBRG_12P; + + if( input_pitch == -1 ) + input_pitch = (input_width * 3 / 4) * 2; + } + + params.tuning_info.dgain_saturation_level.level_red = saturation_level; + params.tuning_info.dgain_saturation_level.level_green_even = saturation_level; + params.tuning_info.dgain_saturation_level.level_green_odd = saturation_level; + params.tuning_info.dgain_saturation_level.level_blue = saturation_level; + } + + if( gpmf_file_path != NULL && strcmp(gpmf_file_path, "") ) + { + read_from_file( ¶ms.gpmf_payload, gpmf_file_path, allocator.Alloc, allocator.Free ); + } + + gpr_buffer output_buffer = { NULL, 0 }; + + if( input_skip_rows > 0 ) + { + input_buffer.buffer = (unsigned char*)(input_buffer.buffer) + (input_skip_rows * input_pitch); + } + + gpr_buffer preview = { NULL, 0 }; + + if( strcmp(jpg_preview_file_path, "") != 0 ) + { + if( read_from_file( &preview, jpg_preview_file_path, allocator.Alloc, allocator.Free) == 0 ) + { + params.preview_image.jpg_preview = preview; + params.preview_image.preview_width = jpg_preview_file_width; + params.preview_image.preview_height = jpg_preview_file_height; + } + } + + if( input_file_type == FILE_TYPE_RAW && output_file_type == FILE_TYPE_DNG ) + { + success = gpr_convert_raw_to_dng( &allocator, ¶ms, &input_buffer, &output_buffer ); + } + else if( input_file_type == FILE_TYPE_DNG && output_file_type == FILE_TYPE_RAW ) + { + success = gpr_convert_dng_to_raw( &allocator, &input_buffer, &output_buffer ); + } + else if( input_file_type == FILE_TYPE_DNG && output_file_type == FILE_TYPE_DNG ) + { + success = gpr_convert_dng_to_dng( &allocator, ¶ms, &input_buffer, &output_buffer ); + } +#if GPR_WRITING + else if( input_file_type == FILE_TYPE_DNG && output_file_type == FILE_TYPE_GPR ) + { + success = gpr_convert_dng_to_gpr( &allocator, ¶ms, &input_buffer, &output_buffer ); + } + else if( input_file_type == FILE_TYPE_RAW && output_file_type == FILE_TYPE_GPR ) + { + success = gpr_convert_raw_to_gpr( &allocator, ¶ms, &input_buffer, &output_buffer ); + } +#endif +#if GPR_READING + else if( input_file_type == FILE_TYPE_GPR && ( output_file_type == FILE_TYPE_PPM || output_file_type == FILE_TYPE_JPG ) ) + { + gpr_rgb_buffer rgb_buffer = { NULL, 0, 0, 0 }; + + GPR_RGB_RESOLUTION rgb_resolution = GPR_RGB_RESOLUTION_DEFAULT; + + if( strcmp(rgb_file_resolution, "1:1") == 0 ) + rgb_resolution = GPR_RGB_RESOLUTION_FULL; + else if( strcmp(rgb_file_resolution, "2:1") == 0 ) + rgb_resolution = GPR_RGB_RESOLUTION_HALF; + else if( strcmp(rgb_file_resolution, "4:1") == 0 ) + rgb_resolution = GPR_RGB_RESOLUTION_QUARTER; + else if( strcmp(rgb_file_resolution, "8:1") == 0 ) + rgb_resolution = GPR_RGB_RESOLUTION_EIGHTH; + else if( strcmp(rgb_file_resolution, "16:1") == 0 ) + rgb_resolution = GPR_RGB_RESOLUTION_SIXTEENTH; + + if( output_file_type == FILE_TYPE_JPG && rgb_file_bits == 16 ) + { + printf( "Asked to output 16-bits RGB, but that is only possible in PPM format.\n"); + rgb_file_bits = 8; + } + + success = gpr_convert_gpr_to_rgb( &allocator, rgb_resolution, rgb_file_bits, &input_buffer, &rgb_buffer ); + + if( output_file_type == FILE_TYPE_PPM ) + { +#define PPM_HEADER_SIZE 100 + char header_text[PPM_HEADER_SIZE]; + + if( rgb_file_bits == 8 ) + { + // 8 bits + sprintf( header_text, "P6\n%ld %ld\n255\n", rgb_buffer.width, rgb_buffer.height ); + } + else + { + // 16 bits + sprintf( header_text, "P6\n%ld %ld\n65535\n", rgb_buffer.width, rgb_buffer.height ); + } + + output_buffer.size = rgb_buffer.size + strlen( header_text ); + output_buffer.buffer = allocator.Alloc( output_buffer.size ); + char* buffer_c = (char*)output_buffer.buffer; + + memcpy( buffer_c, header_text, strlen( header_text ) ); + memcpy( buffer_c + strlen( header_text ), rgb_buffer.buffer, rgb_buffer.size ); +#undef PPM_HEADER_SIZE + } + else if( output_file_type == FILE_TYPE_JPG ) + { + write_buffer_to_file = false; +#if GPR_JPEG_AVAILABLE + tje_encode_to_file( output_file_path, rgb_buffer.width, rgb_buffer.height, 3, rgb_buffer.buffer ); +#else + printf("JPG writing capability is disabled. You could still write to a PPM file"); +#endif + } + + allocator.Free( rgb_buffer.buffer ); + } + else if( input_file_type == FILE_TYPE_GPR && output_file_type == FILE_TYPE_DNG ) + { + success = gpr_convert_gpr_to_dng( &allocator, ¶ms, &input_buffer, &output_buffer ); + } + else if( input_file_type == FILE_TYPE_GPR && output_file_type == FILE_TYPE_RAW ) + { + success = gpr_convert_gpr_to_raw( &allocator, &input_buffer, &output_buffer ); + } +#endif + else + { + printf( "Unsupported conversion from %s to %s \n", input_file_path, output_file_path ); + return -1; + } + + if( success == 0 ) + { + printf("Conversion failed \n"); + return -1; + } + else if( write_buffer_to_file ) + { + write_to_file( &output_buffer, output_file_path ); + } + + if( input_skip_rows > 0 ) + { + input_buffer.buffer = (unsigned char*)(input_buffer.buffer) - (input_skip_rows * input_pitch); + } + + if( preview.buffer ) + { + allocator.Free( preview.buffer ); + } + + gpr_parameters_destroy(¶ms, allocator.Free); + + return 0; +} + diff --git a/gpr/source/app/gpr_tools/main_c.h b/gpr/source/app/gpr_tools/main_c.h new file mode 100755 index 0000000..a8bd308 --- /dev/null +++ b/gpr/source/app/gpr_tools/main_c.h @@ -0,0 +1,34 @@ +/*! @file main_c.h + * + * @brief Definition of C conversion routines used by gpr_tools + * + * (C) Copyright 2018 GoPro Inc (http://gopro.com/). + * + * Licensed under either: + * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0 + * - MIT license, http://opensource.org/licenses/MIT + * at your option. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MAIN_C_H +#define MAIN_C_H + +#ifdef __cplusplus +extern "C" { +#endif + + int dng_convert_main(const char* input_file_path, unsigned int input_width, unsigned int input_height, size_t input_pitch, size_t input_skip_rows, const char* input_pixel_format, + const char* output_file_path, const char* exiftool_file_path, const char* gpmf_file_path, const char* rgb_file_resolution, int rgb_file_bits, + const char* jpg_preview_file_path, int jpg_preview_file_width, int jpg_preview_file_height ); + +#ifdef __cplusplus +} +#endif + +#endif // MAIN_C_H diff --git a/gpr/source/app/gpr_tools/stdcpp_utils.h b/gpr/source/app/gpr_tools/stdcpp_utils.h new file mode 100755 index 0000000..eb7191d --- /dev/null +++ b/gpr/source/app/gpr_tools/stdcpp_utils.h @@ -0,0 +1,138 @@ +/*! @file stdcpp_utils.h + * + * @brief Implement some standard C++ routines using templates + * + * (C) Copyright 2018 GoPro Inc (http://gopro.com/). + * + * Licensed under either: + * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0 + * - MIT license, http://opensource.org/licenses/MIT + * at your option. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STDCPP_UTILS_H +#define STDCPP_UTILS_H + +#include <iostream> +#include <fstream> +#include <sstream> +#include <map> +#include <vector> +#include <algorithm> +#include <vector> +#include <functional> +#include <cctype> + +#include <stdio.h> +#include <string.h> + + std::string& ltrim(std::string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), + std::ptr_fun<int, int>(std::isgraph))); + return s; + } + + std::string& rtrim(std::string& s) + { + s.erase(std::find_if(s.rbegin(), s.rend(), + std::ptr_fun<int, int>(std::isgraph)).base(), s.end()); + return s; + } + + std::string& trim(std::string& s) + { + return ltrim(rtrim(s)); + } + + std::vector<std::string> tokenizer( const std::string& p_pcstStr, char delim ) { + std::vector<std::string> tokens; + std::stringstream mySstream( p_pcstStr ); + std::string temp; + + while( getline( mySstream, temp, delim ) ) { + tokens.push_back( temp ); + } + + return tokens; + } + + template<class T> + bool find_key( std::map<std::string, std::string> hash, const std::string key, T& value ) + { + std::map<std::string, std::string>::iterator it = hash.find( key.c_str() ); + if(it != hash.end()) + { + value = atoi( it->second.c_str() ); + + return true; + } + + return false; + } + + template<> + bool find_key<std::string>( std::map<std::string, std::string> hash, const std::string key, std::string& value ) + { + std::map<std::string, std::string>::iterator it = hash.find( key.c_str() ); + if(it != hash.end()) + { + value = it->second; + + return true; + } + + return false; + } + + template<class T> + bool find_key( std::map<std::string, std::string> hash, const std::string key, T& value_numerator, T& value_denominator ) + { + std::map<std::string, std::string>::iterator it = hash.find( key.c_str() ); + if(it != hash.end()) + { + std::string fraction = it->second; + std::vector<std::string> tokens = tokenizer( fraction, '/' ); + + value_numerator = atoi( tokens[0].c_str() ); + + if( tokens.size() == 2 ) + value_denominator = atoi( tokens[1].c_str() ); + else + value_denominator = 1; + + return true; + } + + return false; + } + + + template<class T> + static T parse_field(const char *tuning_sring, const char *field_name, const char* format_specifier, T default_val, bool* found = NULL ) + { + const char *foundStr = strstr(tuning_sring, field_name); + T ret_data; + + if (foundStr) + { + sscanf(foundStr + strlen(field_name), format_specifier, &ret_data); + + if(found) + *found = true; + + return ret_data; + } + + if(found) + *found = false; + + return default_val; + } + +#endif // STDCPP_UTILS_H |