Quick Start
The following uses PNG-to-AVIF conversion as an example to describe two calling methods: CLI and C++.
CLI
Set the environment variable.
/home/libavif/installindicates the installation path.export LD_LIBRARY_PATH=/home/libavif/install/lib/:/home/libavif/install/lib64/:$LD_LIBRARY_PATH export PATH=/home/libavif/install/bin:$PATHRun the PNG-to-AVIF conversion program.
avifenc input.png output.avif
C++
Create a
quick_start.cppfile and write the following content into the file:#include <avif/avif.h> #include <iostream> #include <fstream> #include <vector> #include <png.h> #include <stdexcept> #include <cstring> static bool decodePNGtoRGBA(const std::string& inputPath, std::vector<uint8_t>& rgbaData, int& width, int& height) { FILE* fp = fopen(inputPath.c_str(), "rb"); if (!fp) { std::cerr << "Failed to open the file: " << inputPath << std::endl; return false; } unsigned char sig[8]; if (fread(sig, 1, 8, fp) != 8 || png_sig_cmp(sig, 0, 8)) { std::cerr << "Invalid PNG file: " << inputPath << std::endl; fclose(fp); return false; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!png_ptr) { std::cerr << "Failed to create png_read_struct" << std::endl; fclose(fp); return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { std::cerr << "Failed to create png_info_struct" << std::endl; png_destroy_read_struct(&png_ptr, nullptr, nullptr); fclose(fp); return false; } if (setjmp(png_jmpbuf(png_ptr))) { std::cerr << "Internal error of libpng" << std::endl; png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); fclose(fp); return false; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); // The 8-byte signature has been read. png_read_info(png_ptr, info_ptr); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); png_byte color_type = png_get_color_type(png_ptr, info_ptr); png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGBA) { png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); } png_read_update_info(png_ptr, info_ptr); size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr); if (row_bytes != static_cast<size_t>(width) * 4) { std::cerr << "Warning: The expected number of bytes per line (" << width * 4 << ") does not match the actual number (" << row_bytes << "). The conversion may not have been performed as expected." << std::endl; } rgbaData.resize(width * height * 4); std::vector<png_bytep> row_pointers(height); for (int y = 0; y < height; ++y) { row_pointers[y] = rgbaData.data() + y * row_bytes; } png_read_image(png_ptr, row_pointers.data()); png_read_end(png_ptr, nullptr); png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); fclose(fp); The std::cout << "PNG file has been successfully decoded into the RGBA format (" << width << "x" << height << ")." << std::endl. return true; } // Encode RGBA data into an AVIF file. bool encodeRGBAtoAVIF(const std::string& outputPath, const uint8_t* rgbaData, int width, int height) { avifEncoder* encoder = avifEncoderCreate(); if (!encoder) { std::cerr << "Failed to create the AVIF encoder" << std::endl; return false; } encoder->maxThreads = 8; encoder->minQuantizer = 19; encoder->maxQuantizer = 21; encoder->minQuantizerAlpha = 0; encoder->maxQuantizerAlpha = 0; encoder->tileRowsLog2=3; encoder->tileColsLog2=3; encoder->speed = 8; encoder->codecChoice = AVIF_CODEC_CHOICE_AOM; avifImage* image = avifImageCreate(width, height, 8, AVIF_PIXEL_FORMAT_YUV420); if (!image) { std::cerr << "Failed to create an AVIF image" << std::endl; avifEncoderDestroy(encoder); return false; } image->yuvFormat = AVIF_PIXEL_FORMAT_YUV420; image->depth = 8; avifRGBImage rgbImage; avifRGBImageSetDefaults(&rgbImage, image); rgbImage.format = AVIF_RGB_FORMAT_RGBA; rgbImage.depth = 8; rgbImage.rowBytes = width * 4; rgbImage.pixels = const_cast<uint8_t*>(rgbaData); if (avifImageRGBToYUV(image, &rgbImage) != AVIF_RESULT_OK) { std::cerr << "Failed to convert RGBA data to YUV" << std::endl; avifImageDestroy(image); avifEncoderDestroy(encoder); return false; } avifRWData output = AVIF_DATA_EMPTY; if (avifEncoderWrite(encoder, image, &output) != AVIF_RESULT_OK) { std::cerr << "Encoding failed" << std::endl; avifImageDestroy(image); avifEncoderDestroy(encoder); return false; } std::ofstream outFile(outputPath, std::ios::binary); if (!outFile.write(reinterpret_cast<char*>(output.data), output.size)) { std::cerr << "Failed to write the file" << std::endl; avifRWDataFree(&output); avifImageDestroy(image); avifEncoderDestroy(encoder); return false; } avifRWDataFree(&output); avifImageDestroy(image); avifEncoderDestroy(encoder); std::cout << "AVIF file generated: " << outputPath << std::endl; return true; } int main() { std::vector<uint8_t> rgbaData; int width = 0, height = 0; // Input and output file paths std::string inputPath = "input.png"; std::string outputPathavif = "output.avif"; // Call the PNG decoding function. bool decode = decodePNGtoRGBA(inputPath, rgbaData, width, height); if (!decode) { std::cerr << "PNG decoding failed. The program exits." << std::endl; return 1; } // Convert the format to AVIF. bool encodeAvif = encodeRGBAtoAVIF(outputPathavif, rgbaData.data(), width, height); if (!encodeAvif) { std::cerr << "AVIF encoding failed. The program exits." << std::endl; return 1; } return 0; }Run the program.
g++ -o simple_convert quick_start.cpp -Ihome/libavif/install/include -L/home/libavif/install/lib -lavif -lpng -lz -lm ./quick_startIf the AVIF file is generated, the program is running normally.