Пример #1
0
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;
}
Пример #2
0
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;
}