Replace deprecated UIGraphicsBeginImageContextWithOptions with UIGraphicsImageRenderer (#6285)

`UIGraphicsBeginImageContextWithOptions` isn't technically deprecated, but `API_TO_BE_DEPRECATED`.  However, according to reports it's crashing in iOS 17.  Replace usage with `UIGraphicsImageRenderer`, available in iOS 10.

I kept introducing horizontal flipping bugs when I was writing this, but it wasn't causing test failures.  Changed the test images from a single color to a gradient with different colors in each corner, then updated the tests to confirm the orientation is still correct.

Generated the test image with ImageMagick:
```
magick \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) -append -filter triangle -resize 12x7\! jpgImage.jpg
```

Also avoid doing extra work if there's nothing to scale, and return the original image.

Fixes https://github.com/flutter/flutter/issues/144602
This commit is contained in:
Jenn Magder
2024-03-13 16:25:51 -07:00
committed by GitHub
parent 142a604d2a
commit 131033e635
12 changed files with 161 additions and 146 deletions

View File

@ -1,6 +1,7 @@
## NEXT
## 0.8.9+2
* Updates minimum iOS version to 12.0 and minimum Flutter version to 3.16.6.
* Replaces deprecated UIGraphicsBeginImageContextWithOptions with UIGraphicsImageRenderer.
## 0.8.9+1

View File

@ -15,59 +15,23 @@
// embedded in the test bundle. Fall back to the base64 string representation of the jpg.
data = [[NSData alloc]
initWithBase64EncodedString:
@"/9j/4AAQSkZJRgABAQAALgAuAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABA"
"AAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAAAuAAAAAQAAAC4AAAABAAOg"
"AQADAAAAAQABAACgAgAEAAAAAQAAAAygAwAEAAAAAQAAAAcAAAAA/+EJc2h0dHA6Ly9ucy5hZG9iZS5jb20"
"veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz"
"4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiP"
"iA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucy"
"MiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZ"
"G9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHBob3Rvc2hvcDpDcmVkaXQ9IsKpIEdvb2dsZSIvPiA8L3JkZjpSR"
"EY+IDwveDp4bXBtZXRhPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDw/eHBhY2tldCBlbmQ9In"
"ciPz4A/+0AVlBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAdHAFaAAMbJUccAgAAAgACHAJuAAnCqSBHb29nbG"
"UAOEJJTQQlAAAAAAAQmkt2IF3PgNJVMGnV2zijEf/AABEIAAcADAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQA"
"AAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQ"
"gjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h"
"5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp"
"6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAAB"
"AncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0R"
"FRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tr"
"e4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAQDAwMDAgQDAwMEBAQFBgoGBg"
"UFBgwICQcKDgwPDg4MDQ0PERYTDxAVEQ0NExoTFRcYGRkZDxIbHRsYHRYYGRj/2wBDAQQEBAYFBgsGBgsYEA0"
"QGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBj/3QAEAAH/2gAMAwEA"
"AhEDEQA/AMWiiivzk/qo/9k="
@"/9j/4AAQSkZJRgABAQAASABIAAD/"
@"4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABA"
@"AIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAAygAw"
@"AEAAAAAQAAAAcAAAAA/8AAEQgABwAMAwERAAIRAQMRAf/"
@"EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//"
@"EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBka"
@"JSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio"
@"6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/"
@"EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//"
@"EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEX"
@"GBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZm"
@"qKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/"
@"bAEMAAgICAgICAwICAwUDAwMFBgUFBQUGCAYGBgYGCAoICAgICAgKCgoKCgoKCgwMDAwMDA4ODg4ODw8PDw8P"
@"Dw8PD//"
@"bAEMBAgMDBAQEBwQEBxALCQsQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ"
@"EBAQEP/dAAQAAv/aAAwDAQACEQMRAD8A9S8ZfsFeG/sH/IUboe7V/JHgR4t4v+2/4XVdj908aPHLG/2P/"
@"B6PsfO5/YL8O7m/4mjdT3av966fi1ivZw/ddF2P8VZ+OeN9pP8Ac9X2P//Z"
options:0];
}
return data;
@ -82,64 +46,14 @@
// embedded in the test bundle. Fall back to the base64 string representation of the jpg.
data = [[NSData alloc]
initWithBase64EncodedString:
@"/9j/4AAQSkZJRgABAQAALgAuAAD/"
@"4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABA"
@"AIAAIdpAAQAAAABAAAAWgAAAAAAAAAuAAAAAQAAAC4AAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAASgAw"
@"AEAAAAAQAAAAcAAAAA/"
@"+EJ12h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTX"
@"BDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB"
@"0az0iWE1QIENvcmUgNi4wLjAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkv"
@"MDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczpwaG90b"
@"3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC"
@"5vcmcvZGMvZWxlbWVudHMvMS4xLyIgcGhvdG9zaG9wOkNyZWRpdD0iwqkgR29vZ2xlIj4gPGRjOnN1YmplY3Q"
@"+IDxyZGY6QmFnLz4gPC9kYzpzdWJqZWN0PiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1w"
@"bWV0YT4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
@"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC"
@"AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA"
@"gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg"
@"ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
@"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC"
@"AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA"
@"gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg"
@"ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
@"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC"
@"AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA"
@"gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg"
@"ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
@"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC"
@"AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA"
@"gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg"
@"ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
@"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC"
@"AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA"
@"gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg"
@"ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
@"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC"
@"AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA"
@"gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg"
@"ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
@"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC"
@"AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA"
@"gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg"
@"ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI"
@"CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC"
@"AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA"
@"gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg"
@"ICAgICAgICAgICAgICA8P3hwYWNrZXQgZW5kPSJ3Ij8+AP/"
@"tAFZQaG90b3Nob3AgMy4wADhCSU0EBAAAAAAAHRwBWgADGyVHHAIAAAIAAhwCbgAJwqkgR29vZ2xlADhCSU0E"
@"JQAAAAAAEJpLdiBdz4DSVTBp1ds4oxH/wAARCAAHAAQDASIAAhEBAxEB/"
@"8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/"
@"8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGR"
@"olJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqK"
@"jpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/"
@"8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/"
@"8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8R"
@"cYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJm"
@"aoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/"
@"9sAQwAEAwMDAwIEAwMDBAQEBQYKBgYFBQYMCAkHCg4MDw4ODA0NDxEWEw8QFRENDRMaExUXGBkZGQ8SGx0bGB"
@"0WGBkY/"
@"9sAQwEEBAQGBQYLBgYLGBANEBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGB"
@"gYGBgY/90ABAAB/9oADAMBAAIRAxEAPwDFooor85P6qP/Z"
@"/9j/4AAQSkZJRgABAQAAAAAAAAD/"
@"2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQE"
@"w8QEBD/"
@"2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE"
@"BAQEBD/wAARCAAHAAQDAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAABP/"
@"EAB0QAAECBwAAAAAAAAAAAAAAAAIABgQIFiVBQlH/xAAUAQEAAAAAAAAAAAAAAAAAAAAH/"
@"8QAHBEAAQQDAQAAAAAAAAAAAAAABAAHI1EIFlIX/9oADAMBAAIRAxEAPwA76kLbdSxV/"
@"PGxcTHjm7hXngUfVWgp+n0N3suLmqX/2Q=="
options:0];
}
return data;
@ -154,10 +68,26 @@
// embedded in the test bundle. Fall back to the base64 string representation of the png.
data = [[NSData alloc]
initWithBase64EncodedString:
@"iVBORw0KGgoAAAAEQ2dCSVAAIAYsuHdmAAAADUlIRFIAAAAMAAAABwgGAAAAPLKsJAAAAARnQU1BAACxjwv8Y"
"QUAAAABc1JHQgCuzhzpAAAAIGNIUk0AAHomAACAhAAA+"
"gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAJcEh"
"ZcwAABxMAAAcTAc4gDwgAAAAOSURBVGMwdX71nxTMMKqBCAwAsfuEYQAAAABJRU5ErkJggg=="
@"iVBORw0KGgoAAAANSUhEUgAAAAwAAAAHEAIAAADjQOcwAAAABGdBTUEAALGPC/"
@"xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAhGVYSWZNTQAqAAAACAA"
@"FARIAAwAAAAEAAQAAARoABQAAAAEAAABKARsABQAAAAEAAABSASgAAwAAAAEAAgAAh2kABAAAAAEAAABaAAAA"
@"AAAAAEgAAAABAAAASAAAAAEAA6ABAAMAAAABAAEAAKACAAQAAAABAAAADKADAAQAAAABAAAABwAAAACX5qZPA"
@"AAACXBIWXMAAAsTAAALEwEAmpwYAAACx2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bW"
@"xuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWx"
@"uczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRm"
@"OkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvY"
@"mUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leG"
@"lmLzEuMC8iPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICA"
@"gICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+"
@"MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+"
@"NzI8L3RpZmY6WFJlc29sdXRpb24+"
@"CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+"
@"CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4xMjwvZXhpZjpQaXhlbFhEaW1lbnNpb24+"
@"CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+"
@"MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+"
@"NzwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+"
@"CjwveDp4bXBtZXRhPgqm8GvmAAAAUElEQVQYGWP4/58BCJDJV6sYGERD9wPFHRimhjIwZK3KAopMDXUAqtv/"
@"XxQoAlKBquf/fyaQEDUACwOD2W0qGeSlSiWDPFWoZBB1vEa1wAYAWgsa+7/A1uQAAAAASUVORK5CYII="
options:0];
}
return data;

View File

@ -8,31 +8,106 @@
@import image_picker_ios.Test;
@import XCTest;
// Corner colors of test image scaled to 3x2. Format is "R G B A".
static NSString *const kColorRepresentation3x2BottomLeftYellow = @"1 0.776471 0 1";
static NSString *const kColorRepresentation3x2TopLeftRed = @"1 0.0666667 0 1";
static NSString *const kColorRepresentation3x2BottomRightCyan = @"0 0.772549 1 1";
static NSString *const kColorRepresentation3x2TopRightBlue = @"0 0.0705882 0.996078 1";
@interface ImageUtilTests : XCTestCase
@end
@implementation ImageUtilTests
static NSString *ColorStringAtPixel(UIImage *image, int pixelX, int pixelY) {
CGImageRef cgImage = image.CGImage;
uint32_t argb;
CGContextRef context1 = CGBitmapContextCreate(
&argb, 1, 1, CGImageGetBitsPerComponent(cgImage), CGImageGetBytesPerRow(cgImage),
CGColorSpaceCreateDeviceRGB(), CGImageGetBitmapInfo(cgImage));
CGContextDrawImage(
context1, CGRectMake(-pixelX, -pixelY, CGImageGetWidth(cgImage), CGImageGetHeight(cgImage)),
cgImage);
CGContextRelease(context1);
int blue = argb & 0xff;
int green = argb >> 8 & 0xff;
int red = argb >> 16 & 0xff;
int alpha = argb >> 24 & 0xff;
return [CIColor colorWithRed:red / 255.f
green:green / 255.f
blue:blue / 255.f
alpha:alpha / 255.f]
.stringRepresentation;
}
- (void)testScaledImage_EqualSizeReturnsSameImage {
UIImage *image = [UIImage imageWithData:ImagePickerTestImages.JPGTestData];
UIImage *scaledImage = [FLTImagePickerImageUtil scaledImage:image
maxWidth:@(image.size.width)
maxHeight:@(image.size.height)
isMetadataAvailable:YES];
// Assert the same bytes pointer (not just equal objects).
XCTAssertEqual(image, scaledImage);
}
- (void)testScaledImage_NilSizeReturnsSameImage {
UIImage *image = [UIImage imageWithData:ImagePickerTestImages.JPGTestData];
UIImage *scaledImage = [FLTImagePickerImageUtil scaledImage:image
maxWidth:nil
maxHeight:nil
isMetadataAvailable:YES];
// Assert the same bytes pointer (not just equal objects).
XCTAssertEqual(image, scaledImage);
}
- (void)testScaledImage_ShouldBeScaled {
UIImage *image = [UIImage imageWithData:ImagePickerTestImages.JPGTestData];
UIImage *newImage = [FLTImagePickerImageUtil scaledImage:image
maxWidth:@3
maxHeight:@2
isMetadataAvailable:YES];
XCTAssertEqual(newImage.size.width, 3);
XCTAssertEqual(newImage.size.height, 2);
CGFloat scaledWidth = 3;
CGFloat scaledHeight = 2;
UIImage *scaledImage = [FLTImagePickerImageUtil scaledImage:image
maxWidth:@(scaledWidth)
maxHeight:@(scaledHeight)
isMetadataAvailable:YES];
XCTAssertEqual(scaledImage.size.width, scaledWidth);
XCTAssertEqual(scaledImage.size.height, scaledHeight);
// Check the corners to make sure nothing has been rotated.
XCTAssertEqualObjects(ColorStringAtPixel(scaledImage, 0, 0),
kColorRepresentation3x2BottomLeftYellow);
XCTAssertEqualObjects(ColorStringAtPixel(scaledImage, 0, scaledHeight - 1),
kColorRepresentation3x2TopLeftRed);
XCTAssertEqualObjects(ColorStringAtPixel(scaledImage, scaledWidth - 1, 0),
kColorRepresentation3x2BottomRightCyan);
XCTAssertEqualObjects(ColorStringAtPixel(scaledImage, scaledWidth - 1, scaledHeight - 1),
kColorRepresentation3x2TopRightBlue);
}
- (void)testScaledImage_ShouldBeScaledWithNoMetadata {
UIImage *image = [UIImage imageWithData:ImagePickerTestImages.JPGTestData];
UIImage *newImage = [FLTImagePickerImageUtil scaledImage:image
maxWidth:@3
maxHeight:@2
isMetadataAvailable:NO];
XCTAssertEqual(newImage.size.width, 3);
XCTAssertEqual(newImage.size.height, 2);
CGFloat scaledWidth = 3;
CGFloat scaledHeight = 2;
UIImage *scaledImage = [FLTImagePickerImageUtil scaledImage:image
maxWidth:@(scaledWidth)
maxHeight:@(scaledHeight)
isMetadataAvailable:NO];
XCTAssertEqual(scaledImage.size.width, scaledWidth);
XCTAssertEqual(scaledImage.size.height, scaledHeight);
// Check the corners to make sure nothing has been rotated.
XCTAssertEqualObjects(ColorStringAtPixel(scaledImage, 0, 0),
kColorRepresentation3x2BottomLeftYellow);
XCTAssertEqualObjects(ColorStringAtPixel(scaledImage, 0, scaledHeight - 1),
kColorRepresentation3x2TopLeftRed);
XCTAssertEqualObjects(ColorStringAtPixel(scaledImage, scaledWidth - 1, 0),
kColorRepresentation3x2BottomRightCyan);
XCTAssertEqualObjects(ColorStringAtPixel(scaledImage, scaledWidth - 1, scaledHeight - 1),
kColorRepresentation3x2TopRightBlue);
}
- (void)testScaledImage_ShouldBeCorrectRotation {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 B

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 593 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 106 B

View File

@ -28,16 +28,37 @@
@implementation FLTImagePickerImageUtil : NSObject
static UIImage *FLTImagePickerDrawScaledImage(UIImage *imageToScale, double width, double height) {
UIGraphicsImageRenderer *imageRenderer =
[[UIGraphicsImageRenderer alloc] initWithSize:CGSizeMake(width, height)
format:imageToScale.imageRendererFormat];
return [imageRenderer imageWithActions:^(UIGraphicsImageRendererContext *rendererContext) {
CGContextRef cgContext = rendererContext.CGContext;
// Flip vertically to translate between UIKit and Quartz.
CGContextTranslateCTM(cgContext, 0, height);
CGContextScaleCTM(cgContext, 1, -1);
CGContextDrawImage(cgContext, CGRectMake(0, 0, width, height), imageToScale.CGImage);
}];
}
+ (UIImage *)scaledImage:(UIImage *)image
maxWidth:(NSNumber *)maxWidth
maxHeight:(NSNumber *)maxHeight
isMetadataAvailable:(BOOL)isMetadataAvailable {
double originalWidth = image.size.width;
double originalHeight = image.size.height;
double aspectRatio = originalWidth / originalHeight;
bool hasMaxWidth = maxWidth != nil;
bool hasMaxHeight = maxHeight != nil;
BOOL hasMaxWidth = maxWidth != nil;
BOOL hasMaxHeight = maxHeight != nil;
if ((originalWidth == maxWidth.doubleValue && originalHeight == maxHeight.doubleValue) ||
(!hasMaxWidth && !hasMaxHeight)) {
// Nothing to scale.
return image;
}
double aspectRatio = originalWidth / originalHeight;
double width = hasMaxWidth ? MIN(round([maxWidth doubleValue]), originalWidth) : originalWidth;
double height =
@ -62,13 +83,7 @@
UIImage *imageToScale = [UIImage imageWithCGImage:image.CGImage
scale:1
orientation:image.imageOrientation];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 1.0);
[imageToScale drawInRect:CGRectMake(0, 0, width, height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
return FLTImagePickerDrawScaledImage(imageToScale, width, height);
}
// Scaling the image always rotate itself based on the current imageOrientation of the original
@ -91,13 +106,7 @@
width = height;
height = temp;
}
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 1.0);
[imageToScale drawInRect:CGRectMake(0, 0, width, height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
return FLTImagePickerDrawScaledImage(imageToScale, width, height);
}
+ (GIFInfo *)scaledGIFImage:(NSData *)data

View File

@ -2,7 +2,7 @@ name: image_picker_ios
description: iOS implementation of the image_picker plugin.
repository: https://github.com/flutter/packages/tree/main/packages/image_picker/image_picker_ios
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22
version: 0.8.9+1
version: 0.8.9+2
environment:
sdk: ^3.2.3