bool ImageLoaderJPG::LoadParams(Image &cImage, File &cFile, bool bBlockSmoothing, bool bFancyUpsampling) { jpeg_decompress_struct sInfo; jpeg_error_mgr sError; sInfo.err = jpeg_std_error(&sError); sInfo.err->error_exit = ExitErrorHandle; jpeg_create_decompress(&sInfo); // Set the user given parameters sInfo.do_block_smoothing = bBlockSmoothing; sInfo.do_fancy_upsampling = bFancyUpsampling; jpeg_read_init(&sInfo, &cFile); jpeg_read_header(&sInfo, TRUE); jpeg_start_decompress(&sInfo); // Get the color format EColorFormat nColorFormat; switch (sInfo.num_components) { case 1: nColorFormat = ColorGrayscale; break; case 3: nColorFormat = ColorRGB; break; case 4: nColorFormat = ColorRGBA; break; default: // Error: Unsupported color format return false; } // Create image buffer ImageBuffer *pImageBuffer = cImage.CreatePart()->CreateMipmap(); pImageBuffer->CreateImage(DataByte, nColorFormat, Vector3i(sInfo.output_width, sInfo.output_height, 1)); // Read in the data uint8 *pCurrentData = pImageBuffer->GetData(); while (sInfo.output_scanline < sInfo.output_height) { jpeg_read_scanlines(&sInfo, &pCurrentData, 1); pCurrentData += pImageBuffer->GetBytesPerRow(); } // Cleanup jpeg_finish_decompress(&sInfo); jpeg_destroy_decompress(&sInfo); // Done return true; }
bool ImageLoaderJPG::SaveParams(const Image &cImage, File &cFile, uint32 nQuality) { // Get the image buffer ImageBuffer *pImageBuffer = cImage.GetBuffer(); if (pImageBuffer && pImageBuffer->GetBytesPerRow()) { // We only support 1 or 3 byte per pixel component if (pImageBuffer->GetBytesPerPixelComponent() == 1 || pImageBuffer->GetBytesPerPixelComponent() == 3) { jpeg_compress_struct sInfo; jpeg_error_mgr sError; sInfo.err = jpeg_std_error(&sError); sInfo.err->error_exit = ExitErrorHandle; jpeg_create_compress(&sInfo); const int nComponents = pImageBuffer->GetComponentsPerPixel(); sInfo.in_color_space = (nComponents == 1)? JCS_GRAYSCALE : JCS_RGB; jpeg_set_defaults(&sInfo); sInfo.input_components = nComponents; sInfo.num_components = (nComponents == 1) ? 1 : 3; sInfo.image_width = pImageBuffer->GetSize().x; sInfo.image_height = pImageBuffer->GetSize().y; sInfo.data_precision = 8; sInfo.input_gamma = 1.0; // Set the user given parameter jpeg_set_quality(&sInfo, nQuality, FALSE); jpeg_write_init(&sInfo, &cFile); jpeg_start_compress(&sInfo, TRUE); // Is the input image RGBA? If so, we really need to throw away the alpha channel... if (nComponents == 4) { // Allocate memory for an converted output row uint8 *pOutputRow = new uint8[sInfo.image_width*sInfo.num_components]; // Write the data const uint8 *pCurrentImageData = pImageBuffer->GetData(); for (uint32 y=0; y<sInfo.image_height; y++) { // Convert the current row for (uint32 x=0; x<sInfo.image_width; x++) { const uint8 *pnPixelIn = &pCurrentImageData[x*4]; uint8 *pnPixelOut = &pOutputRow[x*3]; pnPixelOut[0] = pnPixelIn[0]; pnPixelOut[1] = pnPixelIn[1]; pnPixelOut[2] = pnPixelIn[2]; } // Write out the current row jpeg_write_scanlines(&sInfo, &pOutputRow, 1); // Next, please pCurrentImageData += pImageBuffer->GetBytesPerRow(); } // Free the allocated output row memory delete [] pOutputRow; } else { // Write the data uint8 *pCurrentImageData = pImageBuffer->GetData(); for (uint32 y=0; y<sInfo.image_height; y++) { jpeg_write_scanlines(&sInfo, &pCurrentImageData, 1); pCurrentImageData += pImageBuffer->GetBytesPerRow(); } } // Cleanup jpeg_finish_compress(&sInfo); jpeg_destroy_compress(&sInfo); // Done return true; } else { // Error: Unsupported number of bytes per pixel component } } else { // Error: Failed to get image buffer } // Error! return false; }