Files
UnrealEngineUWP/Engine/Source/Developer/ImageWrapper/Private/JpegImageWrapper.cpp
2014-03-14 14:13:41 -04:00

168 lines
4.2 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
JpegImageWrapper.h: Declares the FJpegImageWrapper class.
Source code for JPEG decompression from:
http://code.google.com/p/jpeg-compressor/
=============================================================================*/
#include "ImageWrapperPrivatePCH.h"
#if WITH_UNREALJPEG
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow"
#endif
#include "jpgd.h"
#include "jpgd.cpp"
#include "jpge.h"
#include "jpge.cpp"
#ifdef __clang__
#pragma clang diagnostic pop
#endif
DEFINE_LOG_CATEGORY_STATIC(JPEGLog, Log, All);
// Only allow one thread to use JPEG decoder at a time (it's not thread safe)
FCriticalSection GJPEGSection;
/* FJpegImageWrapper structors
*****************************************************************************/
FJpegImageWrapper::FJpegImageWrapper( )
: FImageWrapperBase()
{}
/* FImageWrapperBase interface
*****************************************************************************/
bool FJpegImageWrapper::SetCompressed( const void* InCompressedData, int32 InCompressedSize )
{
jpgd::jpeg_decoder_mem_stream jpeg_memStream( (uint8*)InCompressedData, InCompressedSize );
jpgd::jpeg_decoder decoder(&jpeg_memStream);
if ( decoder.get_error_code() != jpgd::JPGD_SUCCESS )
return false;
bool bResult = FImageWrapperBase::SetCompressed( InCompressedData, InCompressedSize );
// We don't support 16 bit jpegs
BitDepth = 8;
Width = decoder.get_width();
Height = decoder.get_height();
switch ( decoder.get_num_components() )
{
case 1:
Format = ERGBFormat::Gray;
break;
case 3:
Format = ERGBFormat::RGBA;
break;
default:
return false;
}
return bResult;
}
bool FJpegImageWrapper::SetRaw( const void* InRawData, int32 InRawSize, const int32 InWidth, const int32 InHeight, const ERGBFormat::Type InFormat, const int32 InBitDepth )
{
check((InFormat == ERGBFormat::RGBA || InFormat == ERGBFormat::BGRA) && InBitDepth == 8);
bool bResult = FImageWrapperBase::SetRaw( InRawData, InRawSize, InWidth, InHeight, InFormat, InBitDepth );
return bResult;
}
void FJpegImageWrapper::Compress( int32 Quality )
{
if (CompressedData.Num() == 0)
{
FScopeLock JPEGLock(&GJPEGSection);
if (Quality == 0) {Quality = 85;}
ensure(Quality >= 1 && Quality <= 100);
Quality = FMath::Clamp(Quality, 1, 100);
check( RawData.Num() );
check( Width > 0 );
check( Height > 0 );
// re-order components if required - JPEGs expect RGBA
if(RawFormat == ERGBFormat::BGRA)
{
FColor* Colors = (FColor*)RawData.GetData();
const int32 NumColors = RawData.Num() / 4;
for(int32 ColorIndex = 0; ColorIndex < NumColors; ColorIndex++)
{
uint8 Temp = Colors[ColorIndex].B;
Colors[ColorIndex].B = Colors[ColorIndex].R;
Colors[ColorIndex].R = Temp;
}
}
CompressedData.Empty();
CompressedData.AddUninitialized(RawData.Num());
int OutBufferSize = CompressedData.Num();
jpge::params Parameters;
Parameters.m_quality = Quality;
bool bSuccess = jpge::compress_image_to_jpeg_file_in_memory(
CompressedData.GetTypedData(), OutBufferSize, Width, Height, 4, RawData.GetTypedData(), Parameters);
check(bSuccess);
CompressedData.RemoveAt(OutBufferSize, CompressedData.Num() - OutBufferSize);
}
}
void FJpegImageWrapper::Uncompress( const ERGBFormat::Type InFormat, int32 InBitDepth )
{
// Ensure we haven't already uncompressed the file.
if ( RawData.Num() != 0 )
{
return;
}
// Get the number of channels we need to extract
int Channels = 0;
if ( ( InFormat == ERGBFormat::RGBA || InFormat == ERGBFormat::BGRA ) && InBitDepth == 8 )
{
Channels = 4;
}
else if ( InFormat == ERGBFormat::Gray && InBitDepth == 8 )
{
Channels = 1;
}
else
{
check( false );
}
FScopeLock JPEGLock( &GJPEGSection );
check( CompressedData.Num() );
int32 NumColors;
uint8* OutData = jpgd::decompress_jpeg_image_from_memory(
CompressedData.GetTypedData(), CompressedData.Num(), &Width, &Height, &NumColors, Channels );
RawData.Empty();
RawData.AddUninitialized( Width * Height * Channels );
FMemory::Memcpy( RawData.GetTypedData(), OutData, RawData.Num() );
}
#endif //WITH_JPEG