@@ -182,6 +182,11 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(SDImageCoderOptions *)
182182
183183 // Animated image
184184 NSMutableArray <SDImageFrame *> *frames = [NSMutableArray array ];
185+ // if repetitionCount is a non-negative integer `n`, then the image sequence should be played back `n + 1` times.
186+ int loopCount = decoder->repetitionCount + 1 ;
187+ if (loopCount < 0 ) {
188+ loopCount = 0 ;
189+ }
185190 while (avifDecoderNextImage (decoder) == AVIF_RESULT_OK) {
186191 @autoreleasepool {
187192 CGImageRef originImageRef = SDCreateCGImageFromAVIF (decoder->image );
@@ -209,7 +214,7 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(SDImageCoderOptions *)
209214 avifDecoderDestroy (decoder);
210215
211216 UIImage *animatedImage = [SDImageCoderHelper animatedImageWithFrames: frames];
212- animatedImage.sd_imageLoopCount = 0 ;
217+ animatedImage.sd_imageLoopCount = loopCount ;
213218 animatedImage.sd_imageFormat = SDImageFormatAVIF;
214219
215220 return animatedImage;
@@ -305,24 +310,62 @@ - (nullable NSData *)encodedDataWithImage:(nullable UIImage *)image format:(SDIm
305310 avifImageRGBToYUV (avif, &rgb);
306311 free (dest.data );
307312
308- NSData *iccProfile = (__bridge_transfer NSData *)CGColorSpaceCopyICCProfile ([SDImageCoderHelper colorSpaceGetDeviceRGB ]);
309-
310- avifImageSetProfileICC (avif, (uint8_t *)iccProfile.bytes , iccProfile.length );
313+ // We must prefer the input CGImage's color space, which may contains ICC profile
314+ CGColorSpaceRef colorSpace = CGImageGetColorSpace (imageRef);
315+ // We only supports RGB colorspace, filter the un-supported one (like Monochrome, CMYK, etc)
316+ if (CGColorSpaceGetModel (colorSpace) != kCGColorSpaceModelRGB ) {
317+ // Ignore and convert, we don't know how to encode this colorspace directlly to WebP
318+ // This may cause little visible difference because of colorpsace conversion
319+ colorSpace = NULL ;
320+ }
321+ if (!colorSpace) {
322+ colorSpace = [SDImageCoderHelper colorSpaceGetDeviceRGB ];
323+ }
324+ // Add ICC profile if present
325+ CFDataRef iccData = NULL ;
326+ if (colorSpace) {
327+ if (@available (iOS 10 , tvOS 10 , macOS 10.12 , watchOS 3 , *)) {
328+ iccData = CGColorSpaceCopyICCData (colorSpace);
329+ }
330+ }
331+ if (iccData && CFDataGetLength (iccData) > 0 ) {
332+ avifImageSetProfileICC (avif, CFDataGetBytePtr (iccData), CFDataGetLength (iccData));
333+ }
311334
312335 double compressionQuality = 1 ;
313336 if (options[SDImageCoderEncodeCompressionQuality]) {
314337 compressionQuality = [options[SDImageCoderEncodeCompressionQuality] doubleValue ];
315338 }
316- int rescaledQuality = AVIF_QUANTIZER_WORST_QUALITY - (int )((compressionQuality) * AVIF_QUANTIZER_WORST_QUALITY);
339+ int quality = compressionQuality * (AVIF_QUALITY_BEST - AVIF_QUALITY_WORST);
340+ CGSize maxPixelSize = CGSizeZero;
341+ NSValue *maxPixelSizeValue = options[SDImageCoderEncodeMaxPixelSize];
342+ if (maxPixelSizeValue != nil ) {
343+ #if SD_MAC
344+ maxPixelSize = maxPixelSizeValue.sizeValue ;
345+ #else
346+ maxPixelSize = maxPixelSizeValue.CGSizeValue ;
347+ #endif
348+ }
317349
318350 avifRWData raw = AVIF_DATA_EMPTY;
319351 avifEncoder *encoder = avifEncoderCreate ();
320352 encoder->codecChoice = codecChoice;
321- encoder->minQuantizer = rescaledQuality;
322- encoder->maxQuantizer = rescaledQuality;
323- encoder->minQuantizerAlpha = rescaledQuality;
324- encoder->maxQuantizerAlpha = rescaledQuality;
353+ encoder->quality = quality;
354+ encoder->qualityAlpha = quality;
325355 encoder->maxThreads = 2 ;
356+ // Check if need to scale pixel size
357+ CGSize scaledSize = [SDImageCoderHelper scaledSizeWithImageSize: CGSizeMake (width, height) scaleSize: maxPixelSize preserveAspectRatio: YES shouldScaleUp: NO ];
358+ if (!CGSizeEqualToSize (scaledSize, CGSizeMake (width, height))) {
359+ // Thumbnail Encoding
360+ assert (scaledSize.width <= width);
361+ assert (scaledSize.height <= height);
362+ avifScalingMode scale;
363+ scale.horizontal .n = (int )scaledSize.width ;
364+ scale.horizontal .d = (int )width;
365+ scale.vertical .n = (int )scaledSize.height ;
366+ scale.vertical .d = (int )height;
367+ encoder->scalingMode = scale;
368+ }
326369 avifResult result = avifEncoderWrite (encoder, avif, &raw);
327370
328371 avifImageDestroy (avif);
@@ -361,7 +404,11 @@ - (instancetype)initWithAnimatedImageData:(NSData *)data options:(SDImageCoderOp
361404 }
362405 // TODO: Optimize the performance like WebPCoder (frame meta cache, etc)
363406 _frameCount = decoder->imageCount ;
364- _loopCount = 0 ;
407+ int loopCount = decoder->repetitionCount + 1 ;
408+ if (loopCount < 0 ) {
409+ loopCount = 0 ;
410+ }
411+ _loopCount = loopCount;
365412 _hasAnimation = decoder->imageCount > 1 ;
366413 CGFloat scale = 1 ;
367414 NSNumber *scaleFactor = options[SDImageCoderDecodeScaleFactor];
0 commit comments