Open li195111 opened 3 years ago
Hi, thanks for sharing this awesome lib. I have some problems when I test to read from iPhone's .HEIC file and want to rewrite to .heic.
First I try to use your simple encoding API but not work, after that I use the code from example/heif_enc.cc but still have this problem.
Here is my code
int main(int argc, char** argv) { const char* file_path = "Path/to/IMG_6894.HEIC"; const char* output_path = "Path/to/vs_output.heic"; vector<string> raw_params = { "x265:crf=20.5", "x265:colorprim=smpte170m", "x265:rdoq-level=1", "x265:aq-strength=1.2", "x265:deblock=-2:-2" }; int master_alpha = 1; int two_colr_boxes = 0; int thumb_alpha = 1; int list_encoders = 0; const char* encoderId = nullptr; int nclx_matrix_coefficients = 6; int nclx_colour_primaries = 2; int nclx_transfer_characteristic = 2; int nclx_full_range = true; bool lossless = false; int logging_level = 0; int thumbnail_bbox_size = 0; bool enc_av1f = false; bool crop_to_even_size = false; heif_context* ctx = heif_context_alloc(); if (!ctx) { std::cerr << "Could not create context object\n"; return 1; } // get the default encoder heif_encoder* encoder = nullptr; heif_context_get_encoder_for_format(ctx, heif_compression_HEVC, &encoder); #define MAX_ENCODERS 5 const heif_encoder_descriptor* encoder_descriptors[MAX_ENCODERS]; int count = heif_context_get_encoder_descriptors(ctx, enc_av1f ? heif_compression_AV1 : heif_compression_HEVC, nullptr, encoder_descriptors, MAX_ENCODERS); if (list_encoders) { show_list_of_encoders(encoder_descriptors, count); return 0; } if (count > 0) { int idx = 0; if (encoderId != nullptr) { for (int i = 0; i <= count; i++) { if (i == count) { std::cerr << "Unknown encoder ID. Choose one from the list below.\n"; show_list_of_encoders(encoder_descriptors, count); return 5; } if (strcmp(encoderId, heif_encoder_descriptor_get_id_name(encoder_descriptors[i])) == 0) { idx = i; break; } } } heif_error error = heif_context_get_encoder(ctx, encoder_descriptors[idx], &encoder); if (error.code) { std::cerr << error.message << "\n"; return 5; } } else { std::cerr << "No " << (enc_av1f ? "AV1" : "HEVC") << " encoder available.\n"; return 5; } tuple<uint8_t*, int, int, int, int, heif_image*> datas = read_heif_data(file_path); uint8_t* data = get<0>(datas); int stride = get<1>(datas); int width = get<2>(datas); int height = get<3>(datas); int has_alpha = get<4>(datas); int channels = has_alpha ? 4 : 3; struct heif_image* image = get<5>(datas); struct heif_error err; err = heif_image_create((int)width, (int)height, heif_colorspace_RGB, has_alpha ? heif_chroma_interleaved_RGBA : heif_chroma_interleaved_RGB, &image); (void)err; heif_image_add_plane(image, heif_channel_interleaved, (int)width, (int)height, has_alpha ? 32 : 24); int img_stride; uint8_t* p = (uint8_t*)heif_image_get_plane(image, heif_channel_interleaved, &img_stride); cout << "Read Width: " << width << endl << "Read Height: " << height << endl << "Read Stride: " << stride << endl << "Write Width: " << width << endl << "Write Height: " << height << endl << "Write Stride: " << img_stride << endl ; for (uint32_t y = 0; y < height; y++) { uint32_t prow = y * img_stride; uint32_t irow = y * stride; uint32_t row_len = width * channels; memcpy(p + prow, data + irow, row_len); } struct heif_error error; // encode the image heif_color_profile_nclx nclx; nclx.matrix_coefficients = (heif_matrix_coefficients)nclx_matrix_coefficients; nclx.transfer_characteristics = (heif_transfer_characteristics)nclx_transfer_characteristic; nclx.color_primaries = (heif_color_primaries)nclx_colour_primaries; nclx.full_range_flag = (uint8_t)nclx_full_range; heif_image_set_nclx_color_profile(image, &nclx); //// set the encoder parameters heif_encoder_set_lossy_quality(encoder, 50); heif_encoder_set_lossless(encoder, lossless); heif_encoder_set_logging_level(encoder, logging_level); set_params(encoder, raw_params); heif_encoding_options* opts = heif_encoding_options_alloc(); opts->save_alpha_channel = (uint8_t)master_alpha; opts->save_two_colr_boxes_when_ICC_and_nclx_available = (uint8_t)two_colr_boxes; if (crop_to_even_size) { if (heif_image_get_primary_width(image) == 1 || heif_image_get_primary_height(image) == 1) { std::cerr << "Image only has a size of 1 pixel width or height. Cannot crop to even size.\n"; return 1; } std::cerr << "Warning: option --even-size/-E is deprecated as it is not needed anymore.\n"; int right = heif_image_get_primary_width(image) % 2; int bottom = heif_image_get_primary_height(image) % 2; error = heif_image_crop(image, 0, right, 0, bottom); if (error.code != 0) { heif_encoding_options_free(opts); std::cerr << "Could not crop image: " << error.message << "\n"; return 1; } } heif_image_handle* handle; error = heif_context_encode_image(ctx, image, encoder, opts, &handle); if (error.code != 0) { heif_encoding_options_free(opts); std::cerr << "Could not encode HEIF/AVIF file: " << error.message << "\n"; return 1; } if (thumbnail_bbox_size > 0) { // encode thumbnail struct heif_image_handle* thumbnail_handle; opts->save_alpha_channel = master_alpha && thumb_alpha; error = heif_context_encode_thumbnail(ctx, image, handle, encoder, opts, thumbnail_bbox_size, &thumbnail_handle); if (error.code) { heif_encoding_options_free(opts); std::cerr << "Could not generate thumbnail: " << error.message << "\n"; return 5; } if (thumbnail_handle) { heif_image_handle_release(thumbnail_handle); } } heif_image_handle_release(handle); heif_encoding_options_free(opts); heif_encoder_release(encoder); error = heif_context_write_to_file(ctx, output_path); if (error.code) { std::cerr << error.message << "\n"; return NULL; } //write_heif_data(image, 50, output_path); datas = read_heif_data(output_path); data = get<0>(datas); stride = get<1>(datas); width = get<2>(datas); height = get<3>(datas); cout << "Read Width: " << width << endl << "Read Height: " << height << endl << "Read Stride: " << stride << endl ; return 0; }
My read_heif_data function is following:
tuple<uint8_t*,int,int,int,int, heif_image*> read_heif_data(const char* input_filename) { heif_context* ctx = heif_context_alloc(); heif_context_read_from_file(ctx, input_filename, nullptr); int num_images = heif_context_get_number_of_top_level_images(ctx); // get a handle to the primary image heif_image_handle* handle; heif_context_get_primary_image_handle(ctx, &handle); int img_width = heif_image_handle_get_width(handle); int img_height = heif_image_handle_get_height(handle); int has_alpha = heif_image_handle_has_alpha_channel(handle); struct heif_image* img; struct heif_error err; int stride; // bytes per line uint8_t* data; // decode the image and convert colorspace to RGB, saved as 24bit interleaved err = heif_decode_image(handle, &img, heif_colorspace_RGB, has_alpha ? heif_chroma_interleaved_RGBA : heif_chroma_interleaved_RGB, nullptr); if (err.code) { heif_image_handle_release(handle); std::cerr << "Could not decode image: " << ": " << err.message << "\n"; return { data, stride, img_width, img_height, has_alpha, img }; } data = heif_image_get_plane(img, heif_channel_interleaved, &stride); //err = heif_image_get_nclx_color_profile(img, &nclx); return { data, stride, img_width, img_height, has_alpha, img }; }
Here is the output I got.
Read Width: 2268 Read Height: 4032 Read Stride: 6816 Write Width: 2268 Write Height: 4032 Write Stride: 6816 Read Width: 0 Read Height: 0 Read Stride: 6816
My Original Input Image like this
and my output .heic file got this
You can see the black border there.
Is there something I need to know? I'm a newbie in C++.
thanks for the reply. 😄
My OS env is Windows 10 21H2 Microsoft Visual Studio Community 2019 16.10.3 Install libheif by Vcpkg
Hi, thanks for sharing this awesome lib. I have some problems when I test to read from iPhone's .HEIC file and want to rewrite to .heic.
First I try to use your simple encoding API but not work, after that I use the code from example/heif_enc.cc but still have this problem.
Here is my code
My read_heif_data function is following:
Here is the output I got.
My Original Input Image like this
and my output .heic file got this
You can see the black border there.
Is there something I need to know? I'm a newbie in C++.
thanks for the reply. 😄