📄 cconv-libjpeg.cpp
字号:
#include "cconv-libjpeg.h"#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>/* This part is copied from libjpeg and is licensed according to the libjpeg license. */void prepare_range_limit_table (j_decompress_ptr cinfo)/* Allocate and fill in the sample_range_limit table */{ JSAMPLE * table; int i; table = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * sizeof(JSAMPLE)); table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ cinfo->sample_range_limit = table; /* First segment of "simple" table: limit[x] = 0 for x < 0 */ memset(table - (MAXJSAMPLE+1), 0, (MAXJSAMPLE+1) * sizeof(JSAMPLE)); /* Main part of "simple" table: limit[x] = x */ for (i = 0; i <= MAXJSAMPLE; i++) table[i] = (JSAMPLE) i; table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ /* End of simple table, rest of first half of post-IDCT table */ for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) table[i] = MAXJSAMPLE; /* Second half of post-IDCT table */ memset(table + (2 * (MAXJSAMPLE+1)), 0, (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * sizeof(JSAMPLE)); memcpy(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), cinfo->sample_range_limit, CENTERJSAMPLE * sizeof(JSAMPLE));}ColorConverter::ColorConverter() { dinfo.client_data = (void*) this; dinfo.err = jpeg_std_error(&jerr); cinfo.client_data = (void*) this; cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = error_exit; jerr.output_message = output_message; jpeg_create_decompress(&dinfo); jpeg_create_compress(&cinfo); yPlane = NULL; cbPlane = NULL; crPlane = NULL; rgbPlane = NULL; planeHeight = 0; rgbRows = NULL; yRows = NULL; cbRows = NULL; crRows = NULL; rowLength = 0; buffer = NULL; bufferSize = 0;}ColorConverter::~ColorConverter() { free(buffer); jpeg_destroy_decompress(&dinfo); jpeg_destroy_compress(&cinfo); free(yPlane); free(cbPlane); free(crPlane); free(rgbPlane); free(rgbRows); free(yRows); free(cbRows); free(crRows);}const uint32_t* ColorConverter::convertToRGB(const uint8_t* yuv, int width, int height) { if (buffer == NULL || bufferSize < int(sizeof(uint32_t)*width*height)) { bufferSize = sizeof(uint32_t)*width*height; buffer = (uint8_t*) realloc(buffer, bufferSize); } if (setjmp(returnpoint)) { printf("Error: %s\n", messagebuffer); return NULL; } prepare_range_limit_table(&dinfo); dinfo.scale_num = dinfo.scale_denom = 1; dinfo.output_width = width; dinfo.output_height = height; dinfo.out_color_components = 3; dinfo.num_components = 3; dinfo.max_v_samp_factor = 2; jinit_merged_upsampler(&dinfo); dinfo.upsample->start_pass(&dinfo); dinfo.output_scanline = 0; if (yPlane == NULL || planeHeight < height) { free(yPlane); free(cbPlane); free(crPlane); free(rgbPlane); yPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*height); cbPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*(height/2)); crPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*(height/2)); rgbPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*height); planeHeight = height; } if (rgbRows == NULL || rowLength < width) { free(rgbRows); free(yRows); free(cbRows); free(crRows); rgbRows = (uint8_t*) malloc(3*width*2); yRows = (uint8_t*) malloc(width*2); cbRows = (uint8_t*) malloc(width*2); crRows = (uint8_t*) malloc(width*2); rowLength = width; } for (int i = 0; i < height; i++) { yPlane[i] = (uint8_t*) &yuv[i*width]; rgbPlane[i] = (uint8_t*) &buffer[i*sizeof(uint32_t)*width]; } for (int i = 0; i < height/2; i++) { cbPlane[i] = (uint8_t*) &yuv[width*height + i*(width/2)]; crPlane[i] = (uint8_t*) &yuv[width*height + (width/2)*(height/2) + i*(width/2)]; } JDIMENSION in_row = 0; JDIMENSION out_row = 0; while (int(out_row) < height) { JSAMPARRAY planes[3]; planes[0] = yPlane; planes[1] = cbPlane; planes[2] = crPlane; dinfo.upsample->upsample(&dinfo, planes, &in_row, height, rgbPlane, &out_row, height); } for (int i = 0; i < height; i++) { memcpy(rgbRows, rgbPlane[i], 3*width); uint8_t* rowptr = rgbRows; uint32_t* pixel = (uint32_t*) rgbPlane[i]; for (int x = 0; x < width; x++) { int r = rowptr[0]; int g = rowptr[1]; int b = rowptr[2]; rowptr += 3; *pixel++ = (r<<16) | (g<<8) | b; } } jpeg_abort((j_common_ptr) &dinfo); // free memory return (uint32_t*) buffer;}const uint8_t* ColorConverter::convertToYUV(const uint32_t* rgb, int width, int height) { if (buffer == NULL || bufferSize < width*height + width*height/2) { bufferSize = width*height + width*height/2; buffer = (uint8_t*) realloc(buffer, bufferSize); } cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; cinfo.jpeg_color_space = JCS_YCbCr; cinfo.num_components = 3; cinfo.image_width = width; cinfo.max_h_samp_factor = 2; cinfo.max_v_samp_factor = 2; cinfo.smoothing_factor = 0; cinfo.comp_info = (jpeg_component_info*) cinfo.mem->alloc_small((j_common_ptr) &cinfo, JPOOL_IMAGE, 3*sizeof(jpeg_component_info)); cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[0].width_in_blocks = width/DCTSIZE; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[1].width_in_blocks = (width/2)/DCTSIZE; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; cinfo.comp_info[2].width_in_blocks = (width/2)/DCTSIZE; jinit_color_converter(&cinfo); jinit_downsampler(&cinfo); cinfo.cconvert->start_pass(&cinfo); cinfo.downsample->start_pass(&cinfo); if (yPlane == NULL || planeHeight < height) { free(yPlane); free(cbPlane); free(crPlane); free(rgbPlane); yPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*height); cbPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*(height/2)); crPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*(height/2)); rgbPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*height); planeHeight = height; } if (rgbRows == NULL || rowLength < width) { free(rgbRows); free(yRows); free(cbRows); free(crRows); rgbRows = (uint8_t*) malloc(3*width*2); yRows = (uint8_t*) malloc(width*2); cbRows = (uint8_t*) malloc(width*2); crRows = (uint8_t*) malloc(width*2); rowLength = width; } for (int i = 0; i < height; i++) { yPlane[i] = (uint8_t*) &buffer[i*width]; } for (int i = 0; i < height/2; i++) { cbPlane[i] = (uint8_t*) &buffer[width*height + i*(width/2)]; crPlane[i] = (uint8_t*) &buffer[width*height + (width/2)*(height/2) + i*(width/2)]; } uint8_t *rows = (uint8_t*) malloc(3*width*2); for (int i = 0; i < height/2; i++) { JSAMPROW tempY[2], tempCb[2], tempCr[2]; tempY[0] = yRows + 0*width; tempY[1] = yRows + 1*width; tempCb[0] = cbRows + 0*width; tempCb[1] = cbRows + 1*width; tempCr[0] = crRows + 0*width; tempCr[1] = crRows + 1*width; JSAMPARRAY tempplanes[3]; tempplanes[0] = tempY; tempplanes[1] = tempCb; tempplanes[2] = tempCr; JSAMPARRAY planes[3]; planes[0] = yPlane; planes[1] = cbPlane; planes[2] = crPlane; rgbPlane[0] = rgbRows + 0*3*width; rgbPlane[1] = rgbRows + 1*3*width; for (int y = 0; y < 2; y++) { uint8_t *outptr = rgbRows + y*3*width; const uint32_t* inptr = &rgb[(2*i + y)*width]; for (int x = 0; x < width; x++) { uint32_t pixel = *inptr++; outptr[0] = (pixel >> 16) & 0xff; outptr[1] = (pixel >> 8) & 0xff; outptr[2] = (pixel >> 0) & 0xff; outptr += 3; } } cinfo.cconvert->color_convert(&cinfo, rgbPlane, tempplanes, 0, 2); cinfo.downsample->downsample(&cinfo, tempplanes, 0, planes, i); } jpeg_abort((j_common_ptr) &cinfo); // free memory return buffer;}void ColorConverter::error_exit(j_common_ptr cinfo) { ColorConverter* data = (ColorConverter*) cinfo->client_data; cinfo->err->format_message(cinfo, data->messagebuffer); longjmp(data->returnpoint, 1);}void ColorConverter::output_message(j_common_ptr cinfo) { printf("Outputting message:\n"); char buf[JMSG_LENGTH_MAX+1]; cinfo->err->format_message(cinfo, buf); printf("%s\n", buf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -