bool process(convert_params& params, convert_stats& stats) { texture_type tex_type = params.m_texture_type; crn_comp_params comp_params(params.m_comp_params); crn_mipmap_params mipmap_params(params.m_mipmap_params); progress_params progress_state; progress_state.m_pParams = ¶ms; progress_state.m_canceled = false; progress_state.m_start_percentage = 0; params.m_status = false; params.m_error_message.clear(); if (params.m_pIntermediate_texture) { crnlib_delete(params.m_pIntermediate_texture); params.m_pIntermediate_texture = NULL; } params.m_pIntermediate_texture = crnlib_new<mipmapped_texture>(*params.m_pInput_texture); mipmapped_texture& work_tex = *params.m_pInput_texture; if ((params.m_unflip) && (work_tex.is_flipped())) { console::info("Unflipping texture"); work_tex.unflip(true, true); } if (params.m_y_flip) { console::info("Flipping texture on Y axis"); // This is awkward - if we're writing to KTX, then go ahead and properly update the work texture's orientation flags. // Otherwise, don't bother updating the orientation flags because the writer may then attempt to unflip the texture before writing to formats // that don't support flipped textures (ugh). const bool bOutputFormatSupportsFlippedTextures = params.m_dst_file_type == texture_file_types::cFormatKTX; if (!work_tex.flip_y(bOutputFormatSupportsFlippedTextures)) { console::warning("Failed flipping texture on Y axis"); } } if ((params.m_dst_format != PIXEL_FMT_INVALID) && (pixel_format_helpers::is_alpha_only(params.m_dst_format))) { if ((work_tex.get_comp_flags() & pixel_format_helpers::cCompFlagAValid) == 0) { console::warning("Output format is alpha-only, but input doesn't have alpha, so setting alpha to luminance."); work_tex.convert(PIXEL_FMT_A8, crnlib::dxt_image::pack_params()); if (tex_type == cTextureTypeNormalMap) tex_type = cTextureTypeRegularMap; } } pixel_format dst_format = params.m_dst_format; if (pixel_format_helpers::is_dxt(dst_format)) { if ((params.m_dst_file_type != texture_file_types::cFormatCRN) && (params.m_dst_file_type != texture_file_types::cFormatDDS) && (params.m_dst_file_type != texture_file_types::cFormatKTX)) { console::warning("Output file format does not support DXTc - automatically choosing a non-DXT pixel format."); dst_format = PIXEL_FMT_INVALID; } } if (dst_format == PIXEL_FMT_INVALID) { // Caller didn't specify a format to use, so try to pick something reasonable. // This is actually much trickier than it seems, and the current approach kind of sucks. dst_format = choose_pixel_format(params, comp_params, work_tex, tex_type); } if ((dst_format == PIXEL_FMT_DXT1) && (comp_params.get_flag(cCRNCompFlagDXT1AForTransparency))) dst_format = PIXEL_FMT_DXT1A; else if (dst_format == PIXEL_FMT_DXT1A) comp_params.set_flag(cCRNCompFlagDXT1AForTransparency, true); if ((dst_format == PIXEL_FMT_DXT1A) && (params.m_dst_file_type == texture_file_types::cFormatCRN)) { console::warning("CRN file format does not support DXT1A compressed textures - converting to DXT5 instead."); dst_format = PIXEL_FMT_DXT5; } const bool is_normal_map = (tex_type == cTextureTypeNormalMap); bool perceptual = comp_params.get_flag(cCRNCompFlagPerceptual); if (is_normal_map) { perceptual = false; mipmap_params.m_gamma_filtering = false; } if (pixel_format_helpers::is_pixel_format_non_srgb(dst_format)) { if (perceptual) { console::message("Output pixel format is swizzled or not RGB, disabling perceptual color metrics"); perceptual = false; } } if (pixel_format_helpers::is_normal_map(dst_format)) { if (perceptual) console::message("Output pixel format is intended for normal maps, disabling perceptual color metrics"); perceptual = false; } bool generate_mipmaps = texture_file_types::supports_mipmaps(params.m_dst_file_type); if ((params.m_write_mipmaps_to_multiple_files) && ((params.m_dst_file_type != texture_file_types::cFormatCRN) && (params.m_dst_file_type != texture_file_types::cFormatDDS) && (params.m_dst_file_type != texture_file_types::cFormatKTX))) { generate_mipmaps = true; } if (params.m_param_debugging) { params.print(); print_comp_params(comp_params); print_mipmap_params(mipmap_params); } if (!create_texture_mipmaps(work_tex, comp_params, mipmap_params, generate_mipmaps)) return convert_error(params, "Failed creating texture mipmaps!"); bool formats_differ = work_tex.get_format() != dst_format; if (formats_differ) { if (pixel_format_helpers::is_dxt1(work_tex.get_format()) && pixel_format_helpers::is_dxt1(dst_format)) formats_differ = false; } bool status = false; timer t; t.start(); if ((params.m_dst_file_type == texture_file_types::cFormatCRN) || ((params.m_dst_file_type == texture_file_types::cFormatDDS) && (pixel_format_helpers::is_dxt(dst_format)) && //((formats_differ) || (comp_params.m_target_bitrate > 0.0f) || (comp_params.m_quality_level < cCRNMaxQualityLevel)) ((comp_params.m_target_bitrate > 0.0f) || (comp_params.m_quality_level < cCRNMaxQualityLevel)))) { status = write_compressed_texture(work_tex, params, comp_params, dst_format, progress_state, perceptual, stats); } else { if ((comp_params.m_target_bitrate > 0.0f) || (comp_params.m_quality_level < cCRNMaxQualityLevel)) { console::warning("Target bitrate/quality level is not supported for this output file format.\n"); } status = convert_and_write_normal_texture(work_tex, params, comp_params, dst_format, progress_state, formats_differ, perceptual, stats); } console::progress(""); if (progress_state.m_canceled) { params.m_canceled = true; return false; } double total_write_time = t.get_elapsed_secs(); if (status) { if (params.m_param_debugging) console::info("Work texture format: %s, desired destination format: %s", pixel_format_helpers::get_pixel_format_string(work_tex.get_format()), pixel_format_helpers::get_pixel_format_string(dst_format)); console::message("Texture successfully written in %3.3fs", total_write_time); } else { dynamic_string str; if (work_tex.get_last_error().is_empty()) str.format("Failed writing texture to file \"%s\"", params.m_dst_filename.get_ptr()); else str.format("Failed writing texture to file \"%s\", Reason: %s", params.m_dst_filename.get_ptr(), work_tex.get_last_error().get_ptr()); return convert_error(params, str.get_ptr()); } if (params.m_debugging) { crnlib_print_mem_stats(); } params.m_status = true; return true; }
bool process(convert_params& params, convert_stats& stats) { texture_type tex_type = params.m_texture_type; crn_comp_params comp_params(params.m_comp_params); crn_mipmap_params mipmap_params(params.m_mipmap_params); progress_params progress_state; progress_state.m_pParams = ¶ms; progress_state.m_canceled = false; progress_state.m_start_percentage = 0; params.m_status = false; params.m_error_message.clear(); if (params.m_pIntermediate_texture) { crnlib_delete(params.m_pIntermediate_texture); params.m_pIntermediate_texture = NULL; } params.m_pIntermediate_texture = crnlib_new<dds_texture>(*params.m_pInput_texture); dds_texture& work_tex = *params.m_pInput_texture; if ((params.m_dst_format != PIXEL_FMT_INVALID) && (pixel_format_helpers::is_alpha_only(params.m_dst_format))) { if ((work_tex.get_comp_flags() & pixel_format_helpers::cCompFlagAValid) == 0) { console::warning(L"Output format is alpha-only, but input doesn't have alpha, so setting alpha to luminance."); work_tex.convert(PIXEL_FMT_A8, crnlib::dxt_image::pack_params()); if (tex_type == cTextureTypeNormalMap) tex_type = cTextureTypeRegularMap; } } pixel_format dst_format = params.m_dst_format; if (dst_format == PIXEL_FMT_INVALID) { // Caller didn't specify a format to use, so try to pick something reasonable. // This is actually much trickier than it seems, and the current approach kind of sucks. dst_format = choose_pixel_format(params, comp_params, work_tex, tex_type); } if ((dst_format == PIXEL_FMT_DXT1) && (comp_params.get_flag(cCRNCompFlagDXT1AForTransparency))) dst_format = PIXEL_FMT_DXT1A; else if (dst_format == PIXEL_FMT_DXT1A) comp_params.set_flag(cCRNCompFlagDXT1AForTransparency, true); const bool is_normal_map = (tex_type == cTextureTypeNormalMap); bool perceptual = comp_params.get_flag(cCRNCompFlagPerceptual); if (is_normal_map) { perceptual = false; mipmap_params.m_gamma_filtering = false; } if (pixel_format_helpers::is_pixel_format_non_srgb(dst_format)) { if (perceptual) { //console::warning(L"Output pixel format is swizzled or not RGB, disabling perceptual color metrics"); perceptual = false; } } if (pixel_format_helpers::is_normal_map(dst_format)) { //if (perceptual) //console::warning(L"Output pixel format is intended for normal maps, disabling perceptual color metrics"); perceptual = false; } bool generate_mipmaps = texture_file_types::supports_mipmaps(params.m_dst_file_type); if ((params.m_write_mipmaps_to_multiple_files) && ((params.m_dst_file_type != texture_file_types::cFormatCRN) && (params.m_dst_file_type != texture_file_types::cFormatDDS))) { generate_mipmaps = true; } if (params.m_param_debugging) { params.print(); print_comp_params(comp_params); print_mipmap_params(mipmap_params); } if (!create_texture_mipmaps(work_tex, comp_params, mipmap_params, generate_mipmaps)) return convert_error(params, L"Failed creating texture mipmaps!"); bool formats_differ = work_tex.get_format() != dst_format; if (formats_differ) { if (pixel_format_helpers::is_dxt1(work_tex.get_format()) && pixel_format_helpers::is_dxt1(dst_format)) formats_differ = false; } bool status = false; timer t; t.start(); if ( (params.m_dst_file_type == texture_file_types::cFormatCRN) || ( (params.m_dst_file_type == texture_file_types::cFormatDDS) && (pixel_format_helpers::is_dxt(dst_format)) && ((formats_differ) || (comp_params.m_target_bitrate > 0.0f) || (comp_params.m_quality_level < cCRNMaxQualityLevel)) ) ) { status = write_compressed_texture(work_tex, params, comp_params, dst_format, progress_state, perceptual, stats); } else { status = convert_and_write_normal_texture(work_tex, params, comp_params, dst_format, progress_state, formats_differ, perceptual, stats); } console::progress(L""); if (progress_state.m_canceled) { params.m_canceled = true; return false; } double total_write_time = t.get_elapsed_secs(); if (status) { if (params.m_param_debugging) console::info(L"Work texture format: %s, desired destination format: %s", pixel_format_helpers::get_pixel_format_string(work_tex.get_format()), pixel_format_helpers::get_pixel_format_string(dst_format)); console::message(L"Texture successfully written in %3.3fs", total_write_time); } else { dynamic_wstring str; if (work_tex.get_last_error().is_empty()) str.format(L"Failed writing texture to file \"%s\"", params.m_dst_filename.get_ptr()); else str.format(L"Failed writing texture to file \"%s\", Reason: %s", params.m_dst_filename.get_ptr(), work_tex.get_last_error().get_ptr()); return convert_error(params, str.get_ptr()); } if (params.m_debugging) { crnlib_print_mem_stats(); } params.m_status = true; return true; }