Linux Media 03 Save as JPEG and PNG

发布于 2022-11-30  47 次阅读


  Here is an example of how to save pic as JPEG or PNG via libjpeg or libpng.

§1 JPEG

int imgwrp_jpeg_quality = 100;

int YUYV_to_JPG(uint8_t* yuvData, int imgWidth, int imgHeight)
{
    int retval = 0;

    /* ===== open file ===== */
    FILE* fp;
    fp = fopen("img.jpg", "wb");
    if (!fp)
    {
        retval = 1;
        perror("RGB24_to_JPG(): open file");
        goto out_return;
    }

    /* ===== jpg init ===== */
    JSAMPROW row_pointer[1];
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;

    cinfo.err = jpeg_std_error(&jerr);  // init error info first
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, fp);

    /* ===== img setting ===== */
    cinfo.image_width = imgWidth;
    cinfo.image_height = imgHeight;
    cinfo.input_components = 3;         // color components for each pixel
    cinfo.in_color_space = JCS_YCbCr;

    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, imgwrp_jpeg_quality, FALSE);
    jpeg_start_compress(&cinfo, TRUE);

    /* ===== write data ===== */
    uint8_t* buf = (uint8_t*)malloc(sizeof(uint8_t) * imgWidth * 3);
    while (cinfo.next_scanline < cinfo.image_height) 
    { 
        for (int i = 0; i < cinfo.image_width; i += 2) 
        { 
            buf[i*3] = yuvData[i*2]; 
            buf[i*3+1] = yuvData[i*2+1]; 
            buf[i*3+2] = yuvData[i*2+3]; 
            buf[i*3+3] = yuvData[i*2+2]; 
            buf[i*3+4] = yuvData[i*2+1]; 
            buf[i*3+5] = yuvData[i*2+3]; 
        } 
        row_pointer[0] = buf; 
        yuvData += imgWidth * 2; 
        jpeg_write_scanlines(&cinfo, row_pointer, 1); 
    }
    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);
    free(buf);

out_close_fp:
    if (fp) fclose(fp);

out_return:
    return retval;
}

§2 PNG

int RGB24_to_PNG(uint8_t* rgbData, int imgWidth, int imgHeight)
{
    int retval = 0;

    /* ===== open file ===== */
    FILE* fp;
    fp = fopen("img.png", "wb");
    if (!fp)
    {
        retval = 1;
        perror("RGB24_to_PNG(): open file");
        goto out_return;
    }

    /* ===== png struct ===== */
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!png_ptr || !info_ptr)
    {
        retval = 2;
        perror("RGB24_to_PNG(): png init");
        goto out_close_fp;
    }

    /* ===== io init ===== */
    png_init_io(png_ptr, fp);
    png_set_IHDR(png_ptr, info_ptr, imgWidth, imgHeight, 8, PNG_COLOR_TYPE_RGB,
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
    png_write_info(png_ptr, info_ptr);
    png_set_packing(png_ptr);

    /* ===== write data ===== */
    uint8_t* rowData = (uint8_t*)malloc(sizeof(uint8_t) * imgWidth * 3);
    int rgbIdx = 0;
    // for i rows
    for (int i = 0; i < imgHeight; ++i)
    {
        // copy each row data
        for (int j = 0; j < imgWidth; ++j)
        {
            rowData[j * 3 + 0] = rgbData[rgbIdx++];
            rowData[j * 3 + 1] = rgbData[rgbIdx++];
            rowData[j * 3 + 2] = rgbData[rgbIdx++];
        }
        // write row
        png_write_row(png_ptr, rowData);
    }
    png_write_end(png_ptr, info_ptr);

out_free:
    if (rowData) free(rowData);
    png_destroy_write_struct(&png_ptr, &info_ptr);

out_close_fp:
    if (fp) fclose(fp);

out_return:
    return retval;
}