/* for OPT_PROGRESSFUNCTION */ int progress_function(void *ctx, double dltotal, double dlnow, double ultotal, double ulnow) { void *go_progress_func = (void *)getCurlField((uintptr)ctx, "progressFunction"); GoInterface *clientp = (GoInterface *)getCurlField((uintptr)ctx, "progressData"); if (clientp == NULL) { return callProgressCallback(go_progress_func, nilInterface(), dltotal, dlnow, ultotal, ulnow); } return callProgressCallback(go_progress_func, *clientp, dltotal, dlnow, ultotal, ulnow); }
bool TCJpegImageFormat::saveFile(TCImage *image, FILE *file) { bool retValue = false; bool canceled = false; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; if (image->getDataFormat() != TCRgb8 && image->getDataFormat() != TCRgba8) { return false; } if (setup(cinfo, jerr)) { std::vector<TCByte> row; TCByte *imageData; int rowSize; int offset = 0; int dir = 1; TCByte *rowBytes = NULL; TCJpegOptions *options = (TCJpegOptions *)image->getCompressionOptions(); imageWidth = image->getWidth(); imageHeight = image->getHeight(); this->image = image; // WARNING: Do NOT put any C++ objects that need destructors inside the // following if statement. Doing so will result in a memory leak if any // error occurs. #ifdef WIN32 #pragma warning( push ) #pragma warning( disable : 4611 ) #endif // WIN32 if (setjmp(jumpBuf)) #ifdef WIN32 #pragma warning( pop ) #endif // WIN32 { // If we get here, there was an error below. // Note: jpeg_destroy_compress is called automatically by the JPEG // library error handling code. We really are good to just exit. return false; } jpeg_stdio_dest(&cinfo, file); callProgressCallback(_UC("SavingJPG"), 0.0f); cinfo.in_color_space = JCS_RGB; cinfo.image_width = imageWidth; cinfo.image_height = image->getHeight(); cinfo.input_components = 3; imageData = image->getImageData(); rowSize = image->getRowSize(); if (image->getFlipped()) { offset = rowSize * (imageHeight - 1); dir = -1; } if (image->getDataFormat() == TCRgba8) { row.resize(image->getWidth() * 3); rowBytes = &row[0]; } jpeg_set_defaults(&cinfo); jpeg_default_colorspace(&cinfo); jpeg_set_quality(&cinfo, options->getQuality(), FALSE); switch (options->getSubSampling()) { case TCJpegOptions::SS420: // 4:2:0 cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; break; case TCJpegOptions::SS422: // 4:2:2 cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; break; case TCJpegOptions::SS444: // 4:4:4 cinfo.comp_info[0].h_samp_factor = 1; cinfo.comp_info[0].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; break; } if (options->getProgressive()) { jpeg_simple_progression(&cinfo); } jpeg_start_compress(&cinfo, TRUE); while (cinfo.next_scanline < cinfo.image_height && !canceled) { unsigned int result; if (image->getDataFormat() == TCRgb8) { rowBytes = &imageData[offset]; } else { int dstIndex = 0; int srcIndex = offset; // Convert RGBA to RGB. for (unsigned int x = 0; x < imageWidth; x++) { rowBytes[dstIndex++] = imageData[srcIndex++]; rowBytes[dstIndex++] = imageData[srcIndex++]; rowBytes[dstIndex++] = imageData[srcIndex++]; srcIndex++; } } result = jpeg_write_scanlines(&cinfo, &rowBytes, 1); offset += result * rowSize * dir; if (!callProgressCallback(NULL, (float)cinfo.next_scanline / (float)cinfo.image_height)) { canceled = true; } } if (canceled) { jpeg_abort_compress(&cinfo); } else { jpeg_finish_compress(&cinfo); retValue = true; } jpeg_destroy_compress(&cinfo); } callProgressCallback(NULL, 2.0f); return retValue && !canceled; }
bool TCJpegImageFormat::loadFile(TCImage *image, FILE *file) { bool retValue = false; bool canceled = false; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; if (setup(cinfo, jerr)) { std::vector<TCByte> grayRow; this->image = image; jpeg_stdio_src(&cinfo, file); // WARNING: Do NOT put any C++ objects that need destructors inside the // following if statement. Doing so will result in a memory leak if any // error occurs. #ifdef WIN32 #pragma warning( push ) #pragma warning( disable : 4611 ) #endif // WIN32 if (setjmp(jumpBuf)) #ifdef WIN32 #pragma warning( pop ) #endif // WIN32 { // If we get here, there was an error below. // Note: jpeg_destroy_decompress is called automatically by the JPEG // library error handling code. We really are good to just exit. return false; } callProgressCallback(_UC("LoadingJPG"), 0.0f); if (jpeg_read_header(&cinfo, TRUE) == JPEG_HEADER_OK) { cinfo.output_components = 3; cinfo.out_color_space = JCS_RGB; if (jpeg_start_decompress(&cinfo)) { if ((cinfo.out_color_space == JCS_RGB || cinfo.out_color_space == JCS_GRAYSCALE) && (cinfo.output_components == 3 || cinfo.output_components == 1)) { TCByte *imageData; int rowSize; int offset = 0; int dir = 1; imageWidth = cinfo.output_width; imageHeight = cinfo.output_height; if (cinfo.output_components != 3) { grayRow.resize(imageWidth * cinfo.output_components); } image->setDataFormat(TCRgb8); image->setSize(imageWidth, imageHeight); image->allocateImageData(); rowSize = image->getRowSize(); imageData = image->getImageData(); if (image->getFlipped()) { offset = rowSize * (imageHeight - 1); dir = -1; } while (cinfo.output_scanline < cinfo.output_height && !canceled) { unsigned int result; if (cinfo.output_components == 1) { unsigned char *grayBytes = &grayRow[0]; // grayscale result = jpeg_read_scanlines(&cinfo, &grayBytes, 1); for (unsigned int i = 0; i < imageWidth; i++) { TCByte value = grayRow[i]; imageData[offset + i * 3] = value; imageData[offset + i * 3 + 1] = value; imageData[offset + i * 3 + 2] = value; } } else { unsigned char *rowBytes = &imageData[offset]; result = jpeg_read_scanlines(&cinfo, &rowBytes, 1); } offset += result * rowSize * dir; if (!callProgressCallback(NULL, (float)cinfo.output_scanline / (float)cinfo.output_height)) { canceled = true; } } retValue = true; } } } if (retValue && !canceled) { if (!jpeg_finish_decompress(&cinfo)) { retValue = false; } } else { jpeg_abort_decompress(&cinfo); } jpeg_destroy_decompress(&cinfo); } callProgressCallback(NULL, 2.0f); return retValue && !canceled; }