2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "loader-jpeg.h"
20 #include <dali/integration-api/bitmap.h>
21 #include "platform-capabilities.h"
22 #include "image-operations.h"
25 #include <libexif/exif-data.h>
26 #include <libexif/exif-loader.h>
27 #include <libexif/exif-tag.h>
28 #include <turbojpeg.h>
35 using Integration::Bitmap;
37 namespace TizenPlatform
42 const unsigned DECODED_PIXEL_SIZE = 3;
43 const TJPF DECODED_PIXEL_LIBJPEG_TYPE = TJPF_RGB;
45 /** Transformations that can be applied to decoded pixels to respect exif orientation
46 * codes in image headers */
49 JPGFORM_NONE = 1, /* no transformation 0th-Row = top & 0th-Column = left */
50 JPGFORM_FLIP_H, /* horizontal flip 0th-Row = top & 0th-Column = right */
51 JPGFORM_FLIP_V, /* vertical flip 0th-Row = bottom & 0th-Column = right*/
52 JPGFORM_TRANSPOSE, /* transpose across UL-to-LR axis 0th-Row = bottom & 0th-Column = left*/
53 JPGFORM_TRANSVERSE,/* transpose across UR-to-LL axis 0th-Row = left & 0th-Column = top*/
54 JPGFORM_ROT_90, /* 90-degree clockwise rotation 0th-Row = right & 0th-Column = top*/
55 JPGFORM_ROT_180, /* 180-degree rotation 0th-Row = right & 0th-Column = bottom*/
56 JPGFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) 0th-Row = left & 0th-Column = bottom*/
67 * @brief Error handling bookeeping for the JPEG Turbo library's
68 * setjmp/longjmp simulated exceptions.
70 struct JpegErrorState {
71 struct jpeg_error_mgr errorManager;
76 * @brief Called by the JPEG library when it hits an error.
77 * We jump out of the library so our loader code can return an error.
79 void JpegErrorHandler ( j_common_ptr cinfo )
81 DALI_LOG_ERROR( "JpegErrorHandler(): libjpeg-turbo fatal error in JPEG decoding.\n" );
82 /* cinfo->err really points to a JpegErrorState struct, so coerce pointer */
83 JpegErrorState * myerr = reinterpret_cast<JpegErrorState *>( cinfo->err );
85 /* Return control to the setjmp point */
86 longjmp( myerr->jumpBuffer, 1 );
89 void JpegOutputMessageHandler( j_common_ptr cinfo )
91 /* Stop libjpeg from printing to stderr - Do Nothing */
95 * LibJPEG Turbo tjDecompress2 API doesn't distinguish between errors that still allow
96 * the JPEG to be displayed and fatal errors.
98 bool IsJpegErrorFatal( const std::string& errorMessage )
100 if( ( errorMessage.find("Corrupt JPEG data") != std::string::npos ) ||
101 ( errorMessage.find("Invalid SOS parameters") != std::string::npos ) )
109 /** Simple struct to ensure xif data is deleted. */
112 ExifAutoPtr( ExifData* data)
118 exif_data_free( mData);
123 /** simple class to enforce clean-up of JPEG structures. */
126 AutoJpg(const tjhandle jpgHandle)
133 // clean up JPG resources
137 tjhandle GetHandle() const
143 AutoJpg( const AutoJpg& ); //< not defined
144 AutoJpg& operator= ( const AutoJpg& ); //< not defined
147 }; // struct AutoJpg;
149 /** RAII wrapper to free memory allocated by the jpeg-turbo library. */
152 AutoJpgMem(unsigned char * const tjMem)
162 unsigned char * Get() const
168 AutoJpgMem( const AutoJpgMem& ); //< not defined
169 AutoJpgMem& operator= ( const AutoJpgMem& ); //< not defined
171 unsigned char * const mTjMem;
174 // Workaround to avoid exceeding the maximum texture size
175 const int MAX_TEXTURE_WIDTH = 4096;
176 const int MAX_TEXTURE_HEIGHT = 4096;
179 bool JpegFlipV( RGB888Type *buffer, int width, int height );
180 bool JpegFlipH( RGB888Type *buffer, int width, int height );
181 bool JpegTranspose( RGB888Type *buffer, int width, int height );
182 bool JpegTransverse( RGB888Type *buffer, int width, int height );
183 bool JpegRotate90 ( RGB888Type *buffer, int width, int height );
184 bool JpegRotate180( RGB888Type *buffer, int width, int height );
185 bool JpegRotate270( RGB888Type *buffer, int width, int height );
186 JPGFORM_CODE ConvertExifOrientation(ExifData* exifData);
187 bool TransformSize( int requiredWidth, int requiredHeight,
188 FittingMode::Type fittingMode, SamplingMode::Type samplingMode,
189 JPGFORM_CODE transform,
190 int& preXformImageWidth, int& preXformImageHeight,
191 int& postXformImageWidth, int& postXformImageHeight );
193 bool LoadJpegHeader( FILE *fp, unsigned int &width, unsigned int &height )
195 // using libjpeg API to avoid having to read the whole file in a buffer
196 struct jpeg_decompress_struct cinfo;
197 struct JpegErrorState jerr;
198 cinfo.err = jpeg_std_error( &jerr.errorManager );
200 jerr.errorManager.output_message = JpegOutputMessageHandler;
201 jerr.errorManager.error_exit = JpegErrorHandler;
203 // On error exit from the JPEG lib, control will pass via JpegErrorHandler
204 // into this branch body for cleanup and error return:
205 if(setjmp(jerr.jumpBuffer))
207 jpeg_destroy_decompress(&cinfo);
211 // jpeg_create_decompress internally uses C casts
212 #pragma GCC diagnostic push
213 #pragma GCC diagnostic ignored "-Wold-style-cast"
214 jpeg_create_decompress( &cinfo );
215 #pragma GCC diagnostic pop
217 jpeg_stdio_src( &cinfo, fp );
219 // Check header to see if it is JPEG file
220 if( jpeg_read_header( &cinfo, TRUE ) != JPEG_HEADER_OK )
223 jpeg_destroy_decompress( &cinfo );
227 width = cinfo.image_width;
228 height = cinfo.image_height;
230 jpeg_destroy_decompress( &cinfo );
234 bool LoadBitmapFromJpeg( const ImageLoader::Input& input, Integration::Bitmap& bitmap )
237 FILE* const fp = input.file;
239 if( fseek(fp,0,SEEK_END) )
241 DALI_LOG_ERROR("Error seeking to end of file\n");
245 long positionIndicator = ftell(fp);
246 unsigned int jpegBufferSize = 0u;
247 if( positionIndicator > -1L )
249 jpegBufferSize = static_cast<unsigned int>(positionIndicator);
252 if( 0u == jpegBufferSize )
257 if( fseek(fp, 0, SEEK_SET) )
259 DALI_LOG_ERROR("Error seeking to start of file\n");
263 Vector<unsigned char> jpegBuffer;
266 jpegBuffer.Resize( jpegBufferSize );
270 DALI_LOG_ERROR( "Could not allocate temporary memory to hold JPEG file of size %uMB.\n", jpegBufferSize / 1048576U );
273 unsigned char * const jpegBufferPtr = jpegBuffer.Begin();
275 // Pull the compressed JPEG image bytes out of a file and into memory:
276 if( fread( jpegBufferPtr, 1, jpegBufferSize, fp ) != jpegBufferSize )
278 DALI_LOG_WARNING("Error on image file read.\n");
282 if( fseek(fp, 0, SEEK_SET) )
284 DALI_LOG_ERROR("Error seeking to start of file\n");
287 AutoJpg autoJpg(tjInitDecompress());
289 if(autoJpg.GetHandle() == NULL)
291 DALI_LOG_ERROR("%s\n", tjGetErrorStr());
295 JPGFORM_CODE transform = JPGFORM_NONE;
297 if( input.reorientationRequested )
299 ExifAutoPtr exifData( exif_data_new_from_data(jpegBufferPtr, jpegBufferSize) );
302 transform = ConvertExifOrientation(exifData.mData);
306 // Push jpeg data in memory buffer through TurboJPEG decoder to make a raw pixel array:
307 int chrominanceSubsampling = -1;
308 int preXformImageWidth = 0, preXformImageHeight = 0;
309 if( tjDecompressHeader2( autoJpg.GetHandle(), jpegBufferPtr, jpegBufferSize, &preXformImageWidth, &preXformImageHeight, &chrominanceSubsampling ) == -1 )
311 DALI_LOG_ERROR("%s\n", tjGetErrorStr());
312 // Do not set width and height to 0 or return early as this sometimes fails only on determining subsampling type.
315 if(preXformImageWidth == 0 || preXformImageHeight == 0)
317 DALI_LOG_WARNING("Invalid Image!\n");
321 int requiredWidth = input.scalingParameters.dimensions.GetWidth();
322 int requiredHeight = input.scalingParameters.dimensions.GetHeight();
324 // If transform is a 90 or 270 degree rotation, the logical width and height
325 // request from the client needs to be adjusted to account by effectively
326 // rotating that too, and the final width and height need to be swapped:
327 int postXformImageWidth = preXformImageWidth;
328 int postXformImageHeight = preXformImageHeight;
331 int scaledPreXformWidth = preXformImageWidth;
332 int scaledPreXformHeight = preXformImageHeight;
333 int scaledPostXformWidth = postXformImageWidth;
334 int scaledPostXformHeight = postXformImageHeight;
336 TransformSize( requiredWidth, requiredHeight,
337 input.scalingParameters.scalingMode,
338 input.scalingParameters.samplingMode,
340 scaledPreXformWidth, scaledPreXformHeight,
341 scaledPostXformWidth, scaledPostXformHeight );
343 // Allocate a bitmap and decompress the jpeg buffer into its pixel buffer:
345 RGB888Type * bitmapPixelBuffer = reinterpret_cast<RGB888Type*>( bitmap.GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGB888, scaledPostXformWidth, scaledPostXformHeight ) );
347 if( tjDecompress2( autoJpg.GetHandle(), jpegBufferPtr, jpegBufferSize, reinterpret_cast<unsigned char*>( bitmapPixelBuffer ), scaledPreXformWidth, 0, scaledPreXformHeight, DECODED_PIXEL_LIBJPEG_TYPE, flags ) == -1 )
349 std::string errorString = tjGetErrorStr();
351 if( IsJpegErrorFatal( errorString ) )
353 DALI_LOG_ERROR("%s\n", errorString.c_str() );
358 DALI_LOG_WARNING("%s\n", errorString.c_str() );
362 const unsigned int bufferWidth = GetTextureDimension( scaledPreXformWidth );
363 const unsigned int bufferHeight = GetTextureDimension( scaledPreXformHeight );
373 // 3 orientation changes for a camera held perpendicular to the ground or upside-down:
374 case JPGFORM_ROT_180:
376 result = JpegRotate180( bitmapPixelBuffer, bufferWidth, bufferHeight );
379 case JPGFORM_ROT_270:
381 result = JpegRotate270( bitmapPixelBuffer, bufferWidth, bufferHeight );
386 result = JpegRotate90( bitmapPixelBuffer, bufferWidth, bufferHeight );
391 result = JpegFlipV( bitmapPixelBuffer, bufferWidth, bufferHeight );
394 /// Less-common orientation changes, since they don't correspond to a camera's
395 // physical orientation:
398 result = JpegFlipH( bitmapPixelBuffer, bufferWidth, bufferHeight );
401 case JPGFORM_TRANSPOSE:
403 result = JpegTranspose( bitmapPixelBuffer, bufferWidth, bufferHeight );
406 case JPGFORM_TRANSVERSE:
408 result = JpegTransverse( bitmapPixelBuffer, bufferWidth, bufferHeight );
413 DALI_LOG_WARNING( "Unsupported JPEG Orientation transformation: %x.\n", transform );
420 bool JpegFlipV(RGB888Type *buffer, int width, int height )
423 int bheight = height;
424 //Destination pixel, set as the first pixel of screen
425 RGB888Type* to = buffer;
426 //Source pixel, as the image is flipped horizontally and vertically,
427 //the source pixel is the end of the buffer of size bwidth * bheight
428 RGB888Type* from = buffer + bwidth * bheight - 1;
430 unsigned int endLoop = ( bwidth * bheight ) / 2;
432 for(unsigned ix = 0; ix < endLoop; ++ ix, ++ to, -- from )
442 bool JpegFlipH(RGB888Type *buffer, int width, int height )
446 int bheight = height;
452 for(iy = 0; iy < bheight; iy ++)
454 //Set the destination pixel as the beginning of the row
455 to = buffer + bwidth * iy;
456 //Set the source pixel as the end of the row to flip in X axis
457 from = buffer + bwidth * (iy + 1) - 1;
458 for(ix = 0; ix < bwidth / 2; ix ++ , ++ to, -- from )
468 bool JpegTranspose( RGB888Type *buffer, int width, int height )
472 int bheight = height;
477 //Flip vertically only
478 for(iy = 0; iy < bheight / 2; iy ++)
480 for(ix = 0; ix < bwidth; ix ++)
482 to = buffer + iy * bwidth + ix;
483 from = buffer + (bheight - 1 - iy) * bwidth + ix;
493 bool JpegTransverse( RGB888Type *buffer, int width, int height )
496 int bheight = height;
497 Vector<RGB888Type> data;
498 data.Resize( bwidth * bheight );
499 RGB888Type *dataPtr = data.Begin();
500 memcpy(dataPtr, buffer, bwidth * bheight * DECODED_PIXEL_SIZE );
502 RGB888Type* to = buffer;
504 for( int iy = 0; iy < bwidth; iy++ )
506 for( int ix = 0; ix < bheight; ix++ )
508 from = dataPtr + ix * bwidth + iy;
517 ///@Todo: Move all these rotation functions to portable/image-operations and take "Jpeg" out of their names.
518 bool JpegRotate90(RGB888Type *buffer, int width, int height )
523 int bheight = height;
524 Vector<RGB888Type> data;
525 data.Resize(width * height);
526 RGB888Type *dataPtr = data.Begin();
527 memcpy(dataPtr, buffer, width * height * DECODED_PIXEL_SIZE );
531 hw = bwidth * bheight;
534 RGB888Type* to = buffer + bwidth - 1;
535 RGB888Type* from = dataPtr;
537 for(ix = bwidth; -- ix >= 0;)
539 for(iy = bheight; -- iy >= 0; ++from )
550 bool JpegRotate180( RGB888Type *buffer, int width, int height )
553 int bheight = height;
554 Vector<RGB888Type> data;
555 data.Resize( bwidth * bheight );
556 RGB888Type *dataPtr = data.Begin();
557 memcpy(dataPtr, buffer, bwidth * bheight * DECODED_PIXEL_SIZE );
559 RGB888Type* to = buffer;
561 for( int iy = 0; iy < bwidth; iy++ )
563 for( int ix = 0; ix < bheight; ix++ )
565 from = dataPtr + ( bheight - ix) * bwidth - 1 - iy;
574 bool JpegRotate270( RGB888Type *buffer, int width, int height )
580 int bheight = height;
581 Vector<RGB888Type> data;
582 data.Resize( width * height );
583 RGB888Type *dataPtr = data.Begin();
584 memcpy(dataPtr, buffer, width * height * DECODED_PIXEL_SIZE );
588 hw = bwidth * bheight;
590 RGB888Type* to = buffer + hw - bwidth;
591 RGB888Type* from = dataPtr;
595 for(ix = bwidth; -- ix >= 0;)
597 for(iy = bheight; -- iy >= 0;)
609 bool EncodeToJpeg( const unsigned char* const pixelBuffer, Vector< unsigned char >& encodedPixels,
610 const std::size_t width, const std::size_t height, const Pixel::Format pixelFormat, unsigned quality )
615 DALI_LOG_ERROR("Null input buffer\n");
619 // Translate pixel format enum:
620 int jpegPixelFormat = -1;
622 switch( pixelFormat )
626 jpegPixelFormat = TJPF_RGB;
629 case Pixel::RGBA8888:
632 jpegPixelFormat = TJPF_RGBX;
635 case Pixel::BGRA8888:
638 jpegPixelFormat = TJPF_BGRX;
643 DALI_LOG_ERROR( "Unsupported pixel format for encoding to JPEG.\n" );
648 // Assert quality is in the documented allowable range of the jpeg-turbo lib:
649 DALI_ASSERT_DEBUG( quality >= 1 );
650 DALI_ASSERT_DEBUG( quality <= 100 );
660 // Initialise a JPEG codec:
661 AutoJpg autoJpg( tjInitCompress() );
663 if( autoJpg.GetHandle() == NULL )
665 DALI_LOG_ERROR( "JPEG Compressor init failed: %s\n", tjGetErrorStr() );
669 // Run the compressor:
670 unsigned char* dstBuffer = NULL;
671 unsigned long dstBufferSize = 0;
674 if( tjCompress2( autoJpg.GetHandle(), const_cast<unsigned char*>(pixelBuffer), width, 0, height, jpegPixelFormat, &dstBuffer, &dstBufferSize, TJSAMP_444, quality, flags ) )
676 DALI_LOG_ERROR("JPEG Compression failed: %s\n", tjGetErrorStr());
680 // Safely wrap the jpeg codec's buffer in case we are about to throw, then
681 // save the pixels to a persistent buffer that we own and let our cleaner
682 // class clean up the buffer as it goes out of scope:
683 AutoJpgMem cleaner( dstBuffer );
684 encodedPixels.Resize( dstBufferSize );
685 memcpy( encodedPixels.Begin(), dstBuffer, dstBufferSize );
691 JPGFORM_CODE ConvertExifOrientation(ExifData* exifData)
693 JPGFORM_CODE transform = JPGFORM_NONE;
694 ExifEntry * const entry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION);
698 orientation = exif_get_short(entry->data, exif_data_get_byte_order(entry->parent->parent));
699 switch( orientation )
703 transform = JPGFORM_NONE;
708 transform = JPGFORM_FLIP_H;
713 transform = JPGFORM_FLIP_V;
718 transform = JPGFORM_TRANSPOSE;
723 transform = JPGFORM_TRANSVERSE;
728 transform = JPGFORM_ROT_90;
733 transform = JPGFORM_ROT_180;
738 transform = JPGFORM_ROT_270;
743 // Try to keep loading the file, but let app developer know there was something fishy:
744 DALI_LOG_WARNING( "Incorrect/Unknown Orientation setting found in EXIF header of JPEG image (%x). Orientation setting will be ignored.\n", entry );
752 bool TransformSize( int requiredWidth, int requiredHeight,
753 FittingMode::Type fittingMode, SamplingMode::Type samplingMode,
754 JPGFORM_CODE transform,
755 int& preXformImageWidth, int& preXformImageHeight,
756 int& postXformImageWidth, int& postXformImageHeight )
760 if( transform == JPGFORM_ROT_90 || transform == JPGFORM_ROT_270 || transform == JPGFORM_ROT_180 || transform == JPGFORM_TRANSVERSE)
762 std::swap( requiredWidth, requiredHeight );
763 std::swap( postXformImageWidth, postXformImageHeight );
766 // Apply the special rules for when there are one or two zeros in requested dimensions:
767 const ImageDimensions correctedDesired = Internal::Platform::CalculateDesiredDimensions( ImageDimensions( postXformImageWidth, postXformImageHeight), ImageDimensions( requiredWidth, requiredHeight ) );
768 requiredWidth = correctedDesired.GetWidth();
769 requiredHeight = correctedDesired.GetHeight();
771 // Rescale image during decode using one of the decoder's built-in rescaling
772 // ratios (expected to be powers of 2), keeping the final image at least as
773 // wide and high as was requested:
776 tjscalingfactor* factors = tjGetScalingFactors( &numFactors );
777 if( factors == NULL )
779 DALI_LOG_WARNING("TurboJpeg tjGetScalingFactors error!\n");
784 // Internal jpeg downscaling is the same as our BOX_X sampling modes so only
785 // apply it if the application requested one of those:
786 // (use a switch case here so this code will fail to compile if other modes are added)
787 bool downscale = true;
788 switch( samplingMode )
790 case SamplingMode::BOX:
791 case SamplingMode::BOX_THEN_NEAREST:
792 case SamplingMode::BOX_THEN_LINEAR:
793 case SamplingMode::DONT_CARE:
798 case SamplingMode::NO_FILTER:
799 case SamplingMode::NEAREST:
800 case SamplingMode::LINEAR:
807 int scaleFactorIndex( 0 );
810 // Find nearest supported scaling factor (factors are in sequential order, getting smaller)
811 for( int i = 1; i < numFactors; ++i )
813 bool widthLessRequired = TJSCALED( postXformImageWidth, factors[i]) < requiredWidth;
814 bool heightLessRequired = TJSCALED( postXformImageHeight, factors[i]) < requiredHeight;
815 // If either scaled dimension is smaller than the desired one, we were done at the last iteration
816 if ( (fittingMode == FittingMode::SCALE_TO_FILL) && (widthLessRequired || heightLessRequired) )
820 // If both dimensions are smaller than the desired one, we were done at the last iteration:
821 if ( (fittingMode == FittingMode::SHRINK_TO_FIT) && ( widthLessRequired && heightLessRequired ) )
825 // If the width is smaller than the desired one, we were done at the last iteration:
826 if ( fittingMode == FittingMode::FIT_WIDTH && widthLessRequired )
830 // If the width is smaller than the desired one, we were done at the last iteration:
831 if ( fittingMode == FittingMode::FIT_HEIGHT && heightLessRequired )
835 // This factor stays is within our fitting mode constraint so remember it:
836 scaleFactorIndex = i;
840 // Regardless of requested size, downscale to avoid exceeding the maximum texture size:
841 for( int i = scaleFactorIndex; i < numFactors; ++i )
843 // Continue downscaling to below maximum texture size (if possible)
844 scaleFactorIndex = i;
846 if( TJSCALED(postXformImageWidth, (factors[i])) < MAX_TEXTURE_WIDTH &&
847 TJSCALED(postXformImageHeight, (factors[i])) < MAX_TEXTURE_HEIGHT )
849 // Current scale-factor downscales to below maximum texture size
854 // We have finally chosen the scale-factor, return width/height values
855 if( scaleFactorIndex > 0 )
857 preXformImageWidth = TJSCALED(preXformImageWidth, (factors[scaleFactorIndex]));
858 preXformImageHeight = TJSCALED(preXformImageHeight, (factors[scaleFactorIndex]));
859 postXformImageWidth = TJSCALED(postXformImageWidth, (factors[scaleFactorIndex]));
860 postXformImageHeight = TJSCALED(postXformImageHeight, (factors[scaleFactorIndex]));
867 ExifData* LoadExifData( FILE* fp )
869 ExifData* exifData=NULL;
870 ExifLoader* exifLoader;
871 unsigned char dataBuffer[1024];
873 if( fseek( fp, 0, SEEK_SET ) )
875 DALI_LOG_ERROR("Error seeking to start of file\n");
879 exifLoader = exif_loader_new ();
883 int size = fread( dataBuffer, 1, sizeof( dataBuffer ), fp );
888 if( ! exif_loader_write( exifLoader, dataBuffer, size ) )
894 exifData = exif_loader_get_data( exifLoader );
895 exif_loader_unref( exifLoader );
901 bool LoadJpegHeader( const ImageLoader::Input& input, unsigned int& width, unsigned int& height )
903 unsigned int requiredWidth = input.scalingParameters.dimensions.GetWidth();
904 unsigned int requiredHeight = input.scalingParameters.dimensions.GetHeight();
905 FILE* const fp = input.file;
907 bool success = false;
908 if( requiredWidth == 0 && requiredHeight == 0 )
910 success = LoadJpegHeader( fp, width, height );
914 // Double check we get the same width/height from the header
915 unsigned int headerWidth;
916 unsigned int headerHeight;
917 if( LoadJpegHeader( fp, headerWidth, headerHeight ) )
919 JPGFORM_CODE transform = JPGFORM_NONE;
921 if( input.reorientationRequested )
923 ExifAutoPtr exifData( LoadExifData( fp ) );
926 transform = ConvertExifOrientation(exifData.mData);
929 int preXformImageWidth = headerWidth;
930 int preXformImageHeight = headerHeight;
931 int postXformImageWidth = headerWidth;
932 int postXformImageHeight = headerHeight;
934 success = TransformSize( requiredWidth, requiredHeight, input.scalingParameters.scalingMode, input.scalingParameters.samplingMode, transform, preXformImageWidth, preXformImageHeight, postXformImageWidth, postXformImageHeight );
937 width = postXformImageWidth;
938 height = postXformImageHeight;
945 height = headerHeight;
953 } // namespace TizenPlatform