|
@@ -9,56 +9,28 @@
|
|
|
|
|
|
|
|
#import "SDWebImageDecoder.h"
|
|
#import "SDWebImageDecoder.h"
|
|
|
|
|
|
|
|
|
|
+@implementation UIImage (ForceDecode)
|
|
|
|
|
+
|
|
|
#if SD_UIKIT || SD_WATCH
|
|
#if SD_UIKIT || SD_WATCH
|
|
|
static const size_t kBytesPerPixel = 4;
|
|
static const size_t kBytesPerPixel = 4;
|
|
|
static const size_t kBitsPerComponent = 8;
|
|
static const size_t kBitsPerComponent = 8;
|
|
|
-#endif
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-@implementation UIImage (ForceDecode)
|
|
|
|
|
|
|
|
|
|
+ (nullable UIImage *)decodedImageWithImage:(nullable UIImage *)image {
|
|
+ (nullable UIImage *)decodedImageWithImage:(nullable UIImage *)image {
|
|
|
- if (image == nil) { return nil; } // Prevent "CGBitmapContextCreateImage: invalid context 0x0" error
|
|
|
|
|
-
|
|
|
|
|
-#if SD_MAC
|
|
|
|
|
- return image;
|
|
|
|
|
-#elif SD_UIKIT || SD_WATCH
|
|
|
|
|
|
|
+ if (![UIImage shouldDecodeImage:image]) {
|
|
|
|
|
+ return image;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // while downloading huge amount of images
|
|
|
|
|
- // autorelease the bitmap context
|
|
|
|
|
- // and all vars to help system to free memory
|
|
|
|
|
- // when there are memory warning.
|
|
|
|
|
- // on iOS7, do not forget to call
|
|
|
|
|
- // [[SDImageCache sharedImageCache] clearMemory];
|
|
|
|
|
|
|
+ // autorelease the bitmap context and all vars to help system to free memory when there are memory warning.
|
|
|
|
|
+ // on iOS7, do not forget to call [[SDImageCache sharedImageCache] clearMemory];
|
|
|
@autoreleasepool{
|
|
@autoreleasepool{
|
|
|
- if (image.images != nil) { return image; } // do not decode animated images
|
|
|
|
|
|
|
|
|
|
CGImageRef imageRef = image.CGImage;
|
|
CGImageRef imageRef = image.CGImage;
|
|
|
-
|
|
|
|
|
- CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef);
|
|
|
|
|
- BOOL anyAlpha = (alpha == kCGImageAlphaFirst ||
|
|
|
|
|
- alpha == kCGImageAlphaLast ||
|
|
|
|
|
- alpha == kCGImageAlphaPremultipliedFirst ||
|
|
|
|
|
- alpha == kCGImageAlphaPremultipliedLast);
|
|
|
|
|
- if (anyAlpha) { return image; } // do not decode images with alpha
|
|
|
|
|
-
|
|
|
|
|
- // current
|
|
|
|
|
- CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(CGImageGetColorSpace(imageRef));
|
|
|
|
|
- CGColorSpaceRef colorspaceRef = CGImageGetColorSpace(imageRef);
|
|
|
|
|
-
|
|
|
|
|
- BOOL unsupportedColorSpace = (imageColorSpaceModel == kCGColorSpaceModelUnknown ||
|
|
|
|
|
- imageColorSpaceModel == kCGColorSpaceModelMonochrome ||
|
|
|
|
|
- imageColorSpaceModel == kCGColorSpaceModelCMYK ||
|
|
|
|
|
- imageColorSpaceModel == kCGColorSpaceModelIndexed);
|
|
|
|
|
- if (unsupportedColorSpace) {
|
|
|
|
|
- colorspaceRef = CGColorSpaceCreateDeviceRGB();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ CGColorSpaceRef colorspaceRef = [UIImage colorSpaceForImageRef:imageRef];
|
|
|
|
|
|
|
|
size_t width = CGImageGetWidth(imageRef);
|
|
size_t width = CGImageGetWidth(imageRef);
|
|
|
size_t height = CGImageGetHeight(imageRef);
|
|
size_t height = CGImageGetHeight(imageRef);
|
|
|
size_t bytesPerRow = kBytesPerPixel * width;
|
|
size_t bytesPerRow = kBytesPerPixel * width;
|
|
|
|
|
|
|
|
-
|
|
|
|
|
// kCGImageAlphaNone is not supported in CGBitmapContextCreate.
|
|
// kCGImageAlphaNone is not supported in CGBitmapContextCreate.
|
|
|
// Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast
|
|
// Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast
|
|
|
// to create bitmap graphics contexts without alpha info.
|
|
// to create bitmap graphics contexts without alpha info.
|
|
@@ -77,16 +49,11 @@ static const size_t kBitsPerComponent = 8;
|
|
|
scale:image.scale
|
|
scale:image.scale
|
|
|
orientation:image.imageOrientation];
|
|
orientation:image.imageOrientation];
|
|
|
|
|
|
|
|
- if (unsupportedColorSpace) {
|
|
|
|
|
- CGColorSpaceRelease(colorspaceRef);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
CGContextRelease(context);
|
|
CGContextRelease(context);
|
|
|
CGImageRelease(imageRefWithoutAlpha);
|
|
CGImageRelease(imageRefWithoutAlpha);
|
|
|
|
|
|
|
|
return imageWithoutAlpha;
|
|
return imageWithoutAlpha;
|
|
|
}
|
|
}
|
|
|
-#endif
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -95,7 +62,7 @@ static const size_t kBitsPerComponent = 8;
|
|
|
* Suggested value for iPad2 and iPhone 4: 120.
|
|
* Suggested value for iPad2 and iPhone 4: 120.
|
|
|
* Suggested value for iPhone 3G and iPod 2 and earlier devices: 30.
|
|
* Suggested value for iPhone 3G and iPod 2 and earlier devices: 30.
|
|
|
*/
|
|
*/
|
|
|
-#define kDestImageSizeMB 60.0f
|
|
|
|
|
|
|
+static const CGFloat kDestImageSizeMB = 60.0f;
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
* Defines the maximum size in MB of a tile used to decode image when the flag `SDWebImageScaleDownLargeImages` is set
|
|
* Defines the maximum size in MB of a tile used to decode image when the flag `SDWebImageScaleDownLargeImages` is set
|
|
@@ -103,47 +70,29 @@ static const size_t kBitsPerComponent = 8;
|
|
|
* Suggested value for iPad2 and iPhone 4: 40.
|
|
* Suggested value for iPad2 and iPhone 4: 40.
|
|
|
* Suggested value for iPhone 3G and iPod 2 and earlier devices: 10.
|
|
* Suggested value for iPhone 3G and iPod 2 and earlier devices: 10.
|
|
|
*/
|
|
*/
|
|
|
-#define kSourceImageTileSizeMB 20.0f
|
|
|
|
|
|
|
+static const CGFloat kSourceImageTileSizeMB = 20.0f;
|
|
|
|
|
+
|
|
|
|
|
+static const CGFloat kBytesPerMB = 1024.0f * 1024.0f;
|
|
|
|
|
+static const CGFloat kPixelsPerMB = kBytesPerMB * kBytesPerPixel;
|
|
|
|
|
+static const CGFloat kDestTotalPixels = kDestImageSizeMB * kPixelsPerMB;
|
|
|
|
|
+static const CGFloat kTileTotalPixels = kSourceImageTileSizeMB * kPixelsPerMB;
|
|
|
|
|
|
|
|
-#define bytesPerMB 1048576.0f
|
|
|
|
|
-#define pixelsPerMB ( bytesPerMB / kBytesPerPixel )
|
|
|
|
|
-#define destTotalPixels kDestImageSizeMB * pixelsPerMB
|
|
|
|
|
-#define tileTotalPixels kSourceImageTileSizeMB * pixelsPerMB
|
|
|
|
|
-#define destSeemOverlap 2.0f // the numbers of pixels to overlap the seems where tiles meet.
|
|
|
|
|
|
|
+static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to overlap the seems where tiles meet.
|
|
|
|
|
|
|
|
+ (nullable UIImage *)decodedAndScaledDownImageWithImage:(nullable UIImage *)image {
|
|
+ (nullable UIImage *)decodedAndScaledDownImageWithImage:(nullable UIImage *)image {
|
|
|
- if (image == nil) { return nil; } // Prevent "CGBitmapContextCreateImage: invalid context 0x0" error
|
|
|
|
|
-
|
|
|
|
|
-#if SD_MAC
|
|
|
|
|
- return image;
|
|
|
|
|
-#elif SD_UIKIT || SD_WATCH
|
|
|
|
|
-
|
|
|
|
|
- BOOL shouldDownSize = ({
|
|
|
|
|
- BOOL shouldDoIt = YES;
|
|
|
|
|
-
|
|
|
|
|
- CGImageRef sourceImageRef = image.CGImage;
|
|
|
|
|
- CGSize sourceResolution = CGSizeZero;
|
|
|
|
|
- sourceResolution.width = CGImageGetWidth(sourceImageRef);
|
|
|
|
|
- sourceResolution.height = CGImageGetHeight(sourceImageRef);
|
|
|
|
|
- float sourceTotalPixels = sourceResolution.width * sourceResolution.height;
|
|
|
|
|
- float imageScale = destTotalPixels / sourceTotalPixels;
|
|
|
|
|
- if (imageScale < 1) {
|
|
|
|
|
- shouldDoIt = YES;
|
|
|
|
|
- } else {
|
|
|
|
|
- shouldDoIt = NO;
|
|
|
|
|
- }
|
|
|
|
|
- shouldDoIt;
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ if (![UIImage shouldDecodeImage:image]) {
|
|
|
|
|
+ return image;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (!shouldDownSize) {
|
|
|
|
|
|
|
+ if (![UIImage shouldScaleDownImage:image]) {
|
|
|
return [UIImage decodedImageWithImage:image];
|
|
return [UIImage decodedImageWithImage:image];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
CGContextRef destContext;
|
|
CGContextRef destContext;
|
|
|
|
|
|
|
|
|
|
+ // autorelease the bitmap context and all vars to help system to free memory when there are memory warning.
|
|
|
|
|
+ // on iOS7, do not forget to call [[SDImageCache sharedImageCache] clearMemory];
|
|
|
@autoreleasepool {
|
|
@autoreleasepool {
|
|
|
- if (image.images != nil) { return image; } // do not decode animated images
|
|
|
|
|
-
|
|
|
|
|
CGImageRef sourceImageRef = image.CGImage;
|
|
CGImageRef sourceImageRef = image.CGImage;
|
|
|
|
|
|
|
|
CGSize sourceResolution = CGSizeZero;
|
|
CGSize sourceResolution = CGSizeZero;
|
|
@@ -153,42 +102,22 @@ static const size_t kBitsPerComponent = 8;
|
|
|
// Determine the scale ratio to apply to the input image
|
|
// Determine the scale ratio to apply to the input image
|
|
|
// that results in an output image of the defined size.
|
|
// that results in an output image of the defined size.
|
|
|
// see kDestImageSizeMB, and how it relates to destTotalPixels.
|
|
// see kDestImageSizeMB, and how it relates to destTotalPixels.
|
|
|
- float imageScale = destTotalPixels / sourceTotalPixels;
|
|
|
|
|
|
|
+ float imageScale = kDestTotalPixels / sourceTotalPixels;
|
|
|
CGSize destResolution = CGSizeZero;
|
|
CGSize destResolution = CGSizeZero;
|
|
|
destResolution.width = (int)(sourceResolution.width*imageScale);
|
|
destResolution.width = (int)(sourceResolution.width*imageScale);
|
|
|
destResolution.height = (int)(sourceResolution.height*imageScale);
|
|
destResolution.height = (int)(sourceResolution.height*imageScale);
|
|
|
|
|
|
|
|
- CGImageAlphaInfo alpha = CGImageGetAlphaInfo(sourceImageRef);
|
|
|
|
|
- BOOL anyAlpha = (alpha == kCGImageAlphaFirst ||
|
|
|
|
|
- alpha == kCGImageAlphaLast ||
|
|
|
|
|
- alpha == kCGImageAlphaPremultipliedFirst ||
|
|
|
|
|
- alpha == kCGImageAlphaPremultipliedLast);
|
|
|
|
|
- if (anyAlpha) { return image; } // do not decode images with alpha
|
|
|
|
|
-
|
|
|
|
|
// current color space
|
|
// current color space
|
|
|
- CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(CGImageGetColorSpace(sourceImageRef));
|
|
|
|
|
- CGColorSpaceRef colorspaceRef = CGImageGetColorSpace(sourceImageRef);
|
|
|
|
|
-
|
|
|
|
|
- BOOL unsupportedColorSpace = (imageColorSpaceModel == kCGColorSpaceModelUnknown ||
|
|
|
|
|
- imageColorSpaceModel == kCGColorSpaceModelMonochrome ||
|
|
|
|
|
- imageColorSpaceModel == kCGColorSpaceModelCMYK ||
|
|
|
|
|
- imageColorSpaceModel == kCGColorSpaceModelIndexed);
|
|
|
|
|
- if (unsupportedColorSpace) {
|
|
|
|
|
- colorspaceRef = CGColorSpaceCreateDeviceRGB();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ CGColorSpaceRef colorspaceRef = [UIImage colorSpaceForImageRef:sourceImageRef];
|
|
|
|
|
|
|
|
size_t bytesPerRow = kBytesPerPixel * destResolution.width;
|
|
size_t bytesPerRow = kBytesPerPixel * destResolution.width;
|
|
|
|
|
|
|
|
// Allocate enough pixel data to hold the output image.
|
|
// Allocate enough pixel data to hold the output image.
|
|
|
void* destBitmapData = malloc( bytesPerRow * destResolution.height );
|
|
void* destBitmapData = malloc( bytesPerRow * destResolution.height );
|
|
|
if (destBitmapData == NULL) {
|
|
if (destBitmapData == NULL) {
|
|
|
- if (unsupportedColorSpace) {
|
|
|
|
|
- CGColorSpaceRelease(colorspaceRef);
|
|
|
|
|
- }
|
|
|
|
|
return image;
|
|
return image;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
// kCGImageAlphaNone is not supported in CGBitmapContextCreate.
|
|
// kCGImageAlphaNone is not supported in CGBitmapContextCreate.
|
|
|
// Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast
|
|
// Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast
|
|
|
// to create bitmap graphics contexts without alpha info.
|
|
// to create bitmap graphics contexts without alpha info.
|
|
@@ -200,10 +129,6 @@ static const size_t kBitsPerComponent = 8;
|
|
|
colorspaceRef,
|
|
colorspaceRef,
|
|
|
kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast);
|
|
kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast);
|
|
|
|
|
|
|
|
- if (unsupportedColorSpace) {
|
|
|
|
|
- CGColorSpaceRelease(colorspaceRef);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
if (destContext == NULL) {
|
|
if (destContext == NULL) {
|
|
|
free( destBitmapData );
|
|
free( destBitmapData );
|
|
|
return image;
|
|
return image;
|
|
@@ -224,7 +149,7 @@ static const size_t kBitsPerComponent = 8;
|
|
|
// The source tile height is dynamic. Since we specified the size
|
|
// The source tile height is dynamic. Since we specified the size
|
|
|
// of the source tile in MB, see how many rows of pixels high it
|
|
// of the source tile in MB, see how many rows of pixels high it
|
|
|
// can be given the input image width.
|
|
// can be given the input image width.
|
|
|
- sourceTile.size.height = (int)( tileTotalPixels / sourceTile.size.width );
|
|
|
|
|
|
|
+ sourceTile.size.height = (int)(kTileTotalPixels / sourceTile.size.width );
|
|
|
sourceTile.origin.x = 0.0f;
|
|
sourceTile.origin.x = 0.0f;
|
|
|
// The output tile is the same proportions as the input tile, but
|
|
// The output tile is the same proportions as the input tile, but
|
|
|
// scaled to image scale.
|
|
// scaled to image scale.
|
|
@@ -234,7 +159,7 @@ static const size_t kBitsPerComponent = 8;
|
|
|
destTile.origin.x = 0.0f;
|
|
destTile.origin.x = 0.0f;
|
|
|
// The source seem overlap is proportionate to the destination seem overlap.
|
|
// The source seem overlap is proportionate to the destination seem overlap.
|
|
|
// this is the amount of pixels to overlap each tile as we assemble the ouput image.
|
|
// this is the amount of pixels to overlap each tile as we assemble the ouput image.
|
|
|
- float sourceSeemOverlap = (int)((destSeemOverlap/destResolution.height)*sourceResolution.height);
|
|
|
|
|
|
|
+ float sourceSeemOverlap = (int)((kDestSeemOverlap/destResolution.height)*sourceResolution.height);
|
|
|
CGImageRef sourceTileImageRef;
|
|
CGImageRef sourceTileImageRef;
|
|
|
// calculate the number of read/write operations required to assemble the
|
|
// calculate the number of read/write operations required to assemble the
|
|
|
// output image.
|
|
// output image.
|
|
@@ -248,11 +173,11 @@ static const size_t kBitsPerComponent = 8;
|
|
|
// Add seem overlaps to the tiles, but save the original tile height for y coordinate calculations.
|
|
// Add seem overlaps to the tiles, but save the original tile height for y coordinate calculations.
|
|
|
float sourceTileHeightMinusOverlap = sourceTile.size.height;
|
|
float sourceTileHeightMinusOverlap = sourceTile.size.height;
|
|
|
sourceTile.size.height += sourceSeemOverlap;
|
|
sourceTile.size.height += sourceSeemOverlap;
|
|
|
- destTile.size.height += destSeemOverlap;
|
|
|
|
|
|
|
+ destTile.size.height += kDestSeemOverlap;
|
|
|
for( int y = 0; y < iterations; ++y ) {
|
|
for( int y = 0; y < iterations; ++y ) {
|
|
|
@autoreleasepool {
|
|
@autoreleasepool {
|
|
|
sourceTile.origin.y = y * sourceTileHeightMinusOverlap + sourceSeemOverlap;
|
|
sourceTile.origin.y = y * sourceTileHeightMinusOverlap + sourceSeemOverlap;
|
|
|
- destTile.origin.y = destResolution.height - (( y + 1 ) * sourceTileHeightMinusOverlap * imageScale + destSeemOverlap);
|
|
|
|
|
|
|
+ destTile.origin.y = destResolution.height - (( y + 1 ) * sourceTileHeightMinusOverlap * imageScale + kDestSeemOverlap);
|
|
|
sourceTileImageRef = CGImageCreateWithImageInRect( sourceImageRef, sourceTile );
|
|
sourceTileImageRef = CGImageCreateWithImageInRect( sourceImageRef, sourceTile );
|
|
|
if( y == iterations - 1 && remainder ) {
|
|
if( y == iterations - 1 && remainder ) {
|
|
|
float dify = destTile.size.height;
|
|
float dify = destTile.size.height;
|
|
@@ -277,8 +202,75 @@ static const size_t kBitsPerComponent = 8;
|
|
|
}
|
|
}
|
|
|
return destImage;
|
|
return destImage;
|
|
|
}
|
|
}
|
|
|
-#endif
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
++ (BOOL)shouldDecodeImage:(nullable UIImage *)image {
|
|
|
|
|
+ // Prevent "CGBitmapContextCreateImage: invalid context 0x0" error
|
|
|
|
|
+ if (image == nil) {
|
|
|
|
|
+ return NO;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // do not decode animated images
|
|
|
|
|
+ if (image.images != nil) {
|
|
|
|
|
+ return NO;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ CGImageRef imageRef = image.CGImage;
|
|
|
|
|
+
|
|
|
|
|
+ CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef);
|
|
|
|
|
+ BOOL anyAlpha = (alpha == kCGImageAlphaFirst ||
|
|
|
|
|
+ alpha == kCGImageAlphaLast ||
|
|
|
|
|
+ alpha == kCGImageAlphaPremultipliedFirst ||
|
|
|
|
|
+ alpha == kCGImageAlphaPremultipliedLast);
|
|
|
|
|
+ // do not decode images with alpha
|
|
|
|
|
+ if (anyAlpha) {
|
|
|
|
|
+ return NO;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return YES;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
++ (BOOL)shouldScaleDownImage:(nonnull UIImage *)image {
|
|
|
|
|
+ BOOL shouldScaleDown = YES;
|
|
|
|
|
+
|
|
|
|
|
+ CGImageRef sourceImageRef = image.CGImage;
|
|
|
|
|
+ CGSize sourceResolution = CGSizeZero;
|
|
|
|
|
+ sourceResolution.width = CGImageGetWidth(sourceImageRef);
|
|
|
|
|
+ sourceResolution.height = CGImageGetHeight(sourceImageRef);
|
|
|
|
|
+ float sourceTotalPixels = sourceResolution.width * sourceResolution.height;
|
|
|
|
|
+ float imageScale = kDestTotalPixels / sourceTotalPixels;
|
|
|
|
|
+ if (imageScale < 1) {
|
|
|
|
|
+ shouldScaleDown = YES;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ shouldScaleDown = NO;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return shouldScaleDown;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
++ (CGColorSpaceRef)colorSpaceForImageRef:(CGImageRef)imageRef {
|
|
|
|
|
+ // current
|
|
|
|
|
+ CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(CGImageGetColorSpace(imageRef));
|
|
|
|
|
+ CGColorSpaceRef colorspaceRef = CGImageGetColorSpace(imageRef);
|
|
|
|
|
+
|
|
|
|
|
+ BOOL unsupportedColorSpace = (imageColorSpaceModel == kCGColorSpaceModelUnknown ||
|
|
|
|
|
+ imageColorSpaceModel == kCGColorSpaceModelMonochrome ||
|
|
|
|
|
+ imageColorSpaceModel == kCGColorSpaceModelCMYK ||
|
|
|
|
|
+ imageColorSpaceModel == kCGColorSpaceModelIndexed);
|
|
|
|
|
+ if (unsupportedColorSpace) {
|
|
|
|
|
+ colorspaceRef = CGColorSpaceCreateDeviceRGB();
|
|
|
|
|
+ CFAutorelease(colorspaceRef);
|
|
|
|
|
+ }
|
|
|
|
|
+ return colorspaceRef;
|
|
|
|
|
+}
|
|
|
|
|
+#elif SD_MAC
|
|
|
|
|
++ (nullable UIImage *)decodedImageWithImage:(nullable UIImage *)image {
|
|
|
|
|
+ return image;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
++ (nullable UIImage *)decodedAndScaledDownImageWithImage:(nullable UIImage *)image {
|
|
|
|
|
+ return image;
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
@end
|
|
@end
|