static pixel_format choose_pixel_format(convert_params& params, const crn_comp_params& comp_params, const mipmapped_texture& src_tex, texture_type tex_type) { const pixel_format src_fmt = src_tex.get_format(); const texture_file_types::format src_file_type = src_tex.get_source_file_type(); const bool is_normal_map = (tex_type == cTextureTypeNormalMap); if (params.m_always_use_source_pixel_format) return src_fmt; // Attempt to choose a reasonable/sane output pixel format. if (params.m_dst_file_type == texture_file_types::cFormatCRN) { if (is_normal_map) { if (pixel_format_helpers::is_dxt(src_fmt)) return src_fmt; else return PIXEL_FMT_DXT5_AGBR; } } else if (params.m_dst_file_type == texture_file_types::cFormatKTX) { if ((src_file_type != texture_file_types::cFormatCRN) && (src_file_type != texture_file_types::cFormatKTX) && (src_file_type != texture_file_types::cFormatDDS)) { if (is_normal_map) { return pixel_format_helpers::has_alpha(src_fmt) ? PIXEL_FMT_A8R8G8B8 : PIXEL_FMT_R8G8B8; } else if (pixel_format_helpers::is_grayscale(src_fmt)) { if (pixel_format_helpers::has_alpha(src_fmt)) return PIXEL_FMT_ETC2A; else return PIXEL_FMT_ETC1; } else if (pixel_format_helpers::has_alpha(src_fmt)) return PIXEL_FMT_ETC2A; else return PIXEL_FMT_ETC1; } } else if (params.m_dst_file_type == texture_file_types::cFormatDDS) { if ((src_file_type != texture_file_types::cFormatCRN) && (src_file_type != texture_file_types::cFormatKTX) && (src_file_type != texture_file_types::cFormatDDS)) { if (is_normal_map) { return PIXEL_FMT_DXT5_AGBR; } else if (pixel_format_helpers::is_grayscale(src_fmt)) { if (pixel_format_helpers::has_alpha(src_fmt)) return comp_params.get_flag(cCRNCompFlagDXT1AForTransparency) ? PIXEL_FMT_DXT1A : PIXEL_FMT_DXT5; else return PIXEL_FMT_DXT1; } else if (pixel_format_helpers::has_alpha(src_fmt)) return comp_params.get_flag(cCRNCompFlagDXT1AForTransparency) ? PIXEL_FMT_DXT1A : PIXEL_FMT_DXT5; else return PIXEL_FMT_DXT1; } } else { // Destination is a regular image format. if (pixel_format_helpers::is_grayscale(src_fmt)) { if (pixel_format_helpers::has_alpha(src_fmt)) return PIXEL_FMT_A8L8; else return PIXEL_FMT_L8; } else if (pixel_format_helpers::has_alpha(src_fmt)) return PIXEL_FMT_A8R8G8B8; else return PIXEL_FMT_R8G8B8; } return src_fmt; }
static void print_comp_params(const crn_comp_params& comp_params) { console::debug("\nTexture conversion compression parameters:"); console::debug(" Desired bitrate: %3.3f", comp_params.m_target_bitrate); console::debug(" CRN Quality: %i", comp_params.m_quality_level); console::debug("CRN C endpoints/selectors: %u %u", comp_params.m_crn_color_endpoint_palette_size, comp_params.m_crn_color_selector_palette_size); console::debug("CRN A endpoints/selectors: %u %u", comp_params.m_crn_alpha_endpoint_palette_size, comp_params.m_crn_alpha_selector_palette_size); console::debug(" DXT both block types: %u, Alpha threshold: %u", comp_params.get_flag(cCRNCompFlagUseBothBlockTypes), comp_params.m_dxt1a_alpha_threshold); console::debug(" DXT compression quality: %s", crn_get_dxt_quality_string(comp_params.m_dxt_quality)); console::debug(" Perceptual: %u, Large Blocks: %u", comp_params.get_flag(cCRNCompFlagPerceptual), comp_params.get_flag(cCRNCompFlagHierarchical)); console::debug(" Compressor: %s", get_dxt_compressor_name(comp_params.m_dxt_compressor_type)); console::debug(" Disable endpoint caching: %u", comp_params.get_flag(cCRNCompFlagDisableEndpointCaching)); console::debug(" Grayscale sampling: %u", comp_params.get_flag(cCRNCompFlagGrayscaleSampling)); console::debug(" Max helper threads: %u", comp_params.m_num_helper_threads); console::debug(""); }
static bool write_compressed_texture( mipmapped_texture& work_tex, convert_params& params, crn_comp_params& comp_params, pixel_format dst_format, progress_params& progress_state, bool perceptual, convert_stats& stats) { comp_params.m_file_type = (params.m_dst_file_type == texture_file_types::cFormatCRN) ? cCRNFileTypeCRN : cCRNFileTypeDDS; comp_params.m_pProgress_func = crn_progress_callback; comp_params.m_pProgress_func_data = &progress_state; comp_params.set_flag(cCRNCompFlagPerceptual, perceptual); crn_format crn_fmt = pixel_format_helpers::convert_pixel_format_to_best_crn_format(dst_format); comp_params.m_format = crn_fmt; console::message("Writing %s texture to file: \"%s\"", crn_get_format_string(crn_fmt), params.m_dst_filename.get_ptr()); uint32 actual_quality_level; float actual_bitrate; bool status = work_tex.write_to_file(params.m_dst_filename.get_ptr(), params.m_dst_file_type, &comp_params, &actual_quality_level, &actual_bitrate); if (!status) return convert_error(params, "Failed writing output file!"); if (!params.m_no_stats) { if (!stats.init(params.m_pInput_texture->get_source_filename().get_ptr(), params.m_dst_filename.get_ptr(), *params.m_pIntermediate_texture, params.m_dst_file_type, params.m_lzma_stats)) { console::warning("Unable to compute output statistics for file: %s", params.m_pInput_texture->get_source_filename().get_ptr()); } } return true; }
bool init(const crn_comp_params ¶ms) { m_comp_params = params; m_pack_params.init(params); crn_format basic_crn_fmt = crnd::crnd_get_fundamental_dxt_format(params.m_format); pixel_format basic_pixel_fmt = pixel_format_helpers::convert_crn_format_to_pixel_format(basic_crn_fmt); if ((params.get_flag(cCRNCompFlagDXT1AForTransparency)) && (basic_pixel_fmt == PIXEL_FMT_DXT1)) basic_pixel_fmt = PIXEL_FMT_DXT1A; if (!m_image.init(pixel_format_helpers::get_dxt_format(basic_pixel_fmt), cDXTBlockSize, cDXTBlockSize, false)) return false; return true; }
static bool convert_and_write_normal_texture(mipmapped_texture& work_tex, convert_params& params, const crn_comp_params& comp_params, pixel_format dst_format, progress_params& progress_state, bool formats_differ, bool perceptual, convert_stats& stats) { if (formats_differ) { dxt_image::pack_params pack_params; pack_params.m_perceptual = perceptual; pack_params.m_compressor = comp_params.m_dxt_compressor_type; pack_params.m_pProgress_callback = dxt_progress_callback_func; pack_params.m_pProgress_callback_user_data_ptr = &progress_state; pack_params.m_dxt1a_alpha_threshold = comp_params.m_dxt1a_alpha_threshold; pack_params.m_quality = comp_params.m_dxt_quality; pack_params.m_endpoint_caching = !comp_params.get_flag(cCRNCompFlagDisableEndpointCaching); pack_params.m_grayscale_sampling = comp_params.get_flag(cCRNCompFlagGrayscaleSampling); if ((!comp_params.get_flag(cCRNCompFlagUseBothBlockTypes)) && (!comp_params.get_flag(cCRNCompFlagDXT1AForTransparency))) pack_params.m_use_both_block_types = false; pack_params.m_num_helper_threads = comp_params.m_num_helper_threads; pack_params.m_use_transparent_indices_for_black = comp_params.get_flag(cCRNCompFlagUseTransparentIndicesForBlack); console::info("Converting texture format from %s to %s", pixel_format_helpers::get_pixel_format_string(work_tex.get_format()), pixel_format_helpers::get_pixel_format_string(dst_format)); timer tm; tm.start(); bool status = work_tex.convert(dst_format, pack_params); double t = tm.get_elapsed_secs(); console::info(""); if (!status) { if (progress_state.m_canceled) { params.m_canceled = true; return false; } else { return convert_error(params, "Failed converting texture to output format!"); } } console::info("Texture format conversion took %3.3fs", t); } if (params.m_write_mipmaps_to_multiple_files) { for (uint f = 0; f < work_tex.get_num_faces(); f++) { for (uint l = 0; l < work_tex.get_num_levels(); l++) { dynamic_string filename(params.m_dst_filename.get_ptr()); dynamic_string drv, dir, fn, ext; if (!file_utils::split_path(params.m_dst_filename.get_ptr(), &drv, &dir, &fn, &ext)) return false; fn += dynamic_string(cVarArg, "_face%u_mip%u", f, l).get_ptr(); filename = drv + dir + fn + ext; mip_level* pLevel = work_tex.get_level(f, l); face_vec face(1); face[0].push_back(crnlib_new<mip_level>(*pLevel)); mipmapped_texture new_tex; new_tex.assign(face); console::info("Writing texture face %u mip level %u to file %s", f, l, filename.get_ptr()); if (!new_tex.write_to_file(filename.get_ptr(), params.m_dst_file_type, NULL, NULL, NULL)) return convert_error(params, "Failed writing output file!"); } } } else { console::message("Writing texture to file: \"%s\"", params.m_dst_filename.get_ptr()); if (params.m_dst_stream) { if (!work_tex.write_to_stream(params.m_dst_stream, params.m_dst_file_type, NULL, NULL, NULL)) { return convert_error(params, "Failed writing output stream!"); } } else if (!work_tex.write_to_file(params.m_dst_filename.get_ptr(), params.m_dst_file_type, NULL, NULL, NULL)) { return convert_error(params, "Failed writing output file!"); } if (!params.m_no_stats) { if (!stats.init(params.m_pInput_texture->get_source_filename().get_ptr(), params.m_dst_filename.get_ptr(), *params.m_pIntermediate_texture, params.m_dst_file_type, params.m_lzma_stats)) { console::warning("Unable to compute output statistics for file: %s", params.m_pInput_texture->get_source_filename().get_ptr()); } } } return true; }
static pixel_format choose_pixel_format(convert_params& params, const crn_comp_params &comp_params, const dds_texture& src_tex, texture_type tex_type) { if (params.m_use_source_format) return src_tex.get_format(); const bool is_normal_map = (tex_type == cTextureTypeNormalMap); if (params.m_dst_file_type == texture_file_types::cFormatCRN) { if (is_normal_map) { switch (src_tex.get_format()) { case PIXEL_FMT_DXN: case PIXEL_FMT_3DC: case PIXEL_FMT_DXT5_xGBR: case PIXEL_FMT_DXT5_AGBR: case PIXEL_FMT_DXT5_xGxR: return src_tex.get_format(); default: return PIXEL_FMT_DXT5_AGBR; } } } else if (params.m_dst_file_type == texture_file_types::cFormatDDS) { if (src_tex.get_source_file_type() != texture_file_types::cFormatCRN) { if (is_normal_map) { switch (src_tex.get_format()) { case PIXEL_FMT_DXN: case PIXEL_FMT_3DC: case PIXEL_FMT_DXT5_xGBR: case PIXEL_FMT_DXT5_AGBR: case PIXEL_FMT_DXT5_xGxR: return src_tex.get_format(); default: return PIXEL_FMT_DXT5_AGBR; } } else if (pixel_format_helpers::is_grayscale(src_tex.get_format())) { if (pixel_format_helpers::has_alpha(src_tex.get_format())) return comp_params.get_flag(cCRNCompFlagDXT1AForTransparency) ? PIXEL_FMT_DXT1A : PIXEL_FMT_DXT5; else return PIXEL_FMT_DXT1; } else if (pixel_format_helpers::has_alpha(src_tex.get_format())) return comp_params.get_flag(cCRNCompFlagDXT1AForTransparency) ? PIXEL_FMT_DXT1A : PIXEL_FMT_DXT5; else return PIXEL_FMT_DXT1; } } else { // A regular image format. if (pixel_format_helpers::is_grayscale(src_tex.get_format())) { if (pixel_format_helpers::has_alpha(src_tex.get_format())) return PIXEL_FMT_A8L8; else return PIXEL_FMT_L8; } else if (pixel_format_helpers::has_alpha(src_tex.get_format())) return PIXEL_FMT_A8R8G8B8; else return PIXEL_FMT_R8G8B8; } return src_tex.get_format(); }