Załóżmy, że zaczynasz od UIImage i chcesz go przyciąć. Najpopularniejszą metodą jest użycie CGImageCreateWithImageInRect dostać CGImageRef i utworzyć nowy obraz z niej tak:Jak przekonwertować obiekt UIImage utworzony z CGImageRef na surowe dane iz powrotem
CGRect cropRect = CGRectMake(x*width, y*height, width, height);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
Teraz powiedzmy, że później trzeba konwertować te UIImage do obiektu NSData. Na przykład stanie się tak, jeśli chcesz zapisać obraz na dysku za pomocą NSKeyedArchiver. Albo można uzyskać NSData sprzeciwić się wykonując wyraźnie następuje:
NSData *imageData = UIImagePNGRepresentation(croppedImage);
Zrobiłem to i później starałem się zrekonstruować nowego obiektu UIImage wykonując:
UIImage *image = [UIImage imageWithData:imageData];
Zrobiłem to dla seria 48 zdjęć. Większość z nich była w porządku, ale po każdych 4 zdjęciach kolejne 2 zostały uszkodzone z zamienionymi górnymi i dolnymi częściami każdego obrazu. Jeśli wyjmę konwersję na NSData iz powrotem, działa dobrze. Też mam ten sam problem, jeśli używam NSKeyedArchiver do zapisu tablicy obrazów na dysk (co, jak przypuszczam, wywołuje coś takiego jak UIImagePNGRepresentation w swojej procedurze kodowania). Moja teoria mówi, że to musi mieć coś wspólnego z tym, jak buduję obrazy z CGImageRefs.
Co to jest obejście tego problemu? Nie mogę się domyślić, jak umieścić CGImageRefs w obiekcie NSData i wolałbym rozwiązanie, które poprawnie zbuduje UIImage, aby mogło być serializowane.
Edit:
Niektórzy ludzie pytali o rzeczywisty kod uruchomiony, więc dodaję tutaj
UIImage *image = self.animationObject.image;
for (int y=0; y<[self.animationInfoObject.numInY intValue]; y++) {
for (int x=0; x<[self.animationInfoObject.numInX intValue]; x++) {
CGRect cropRect = CGRectMake(x*width, y*height, width, height);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
NSData *imageData = UIImageJPEGRepresentation(croppedImage, 1.0);
[self addImageToArray:imageData];
CFRelease(imageRef);
}
}
Obraz z self.animationObject.image ma siatki i obrazów z numInX i NUMINY zdjęć w każdym kierunku. Odcinam poszczególne obrazy z siatki 2D i zapisuję je.
Później umieszczam obrazy w widoku obrazu, aby je ożywiać. Oto kod:
NSMutableArray *animationArray = [[NSMutableArray alloc] init];
for (int frame=0; frame<[[photoObject frameArray] count]; frame++) {
NSData *imageData =[[photoObject imageArray] objectAtIndex:[[[photoObject frameArray] objectAtIndex:frame] integerValue]-1];
UIImage *image = [UIImage imageWithData:imageData];
[animationArray addObject:image];
}
To wszystko działa dobrze na iPhone 6, ale nie działa na iPhone 5. Wydaje się również, aby być tylko problem gdy siatka obrazów jest długa. Na przykład dla przykładu używam self.animationObject.image ma numInY jako 3 i numInX 2, a całkowity rozmiar obrazu to 1536x3072 (każdy mini-obraz to 768 x 1024). To są dwa dolne obrazy, które mają odwrócone szczyty i dna.
Niektóre bardziej użytecznych szczegółów. Mam złożone obrazy, z których każda zawiera 6 mniejszych obrazów w siatce 2x3. Rozmiar każdego obrazu to 768 x 1024, więc całkowity rozmiar złożonego obrazu to 1536 x 3072. Jest to 5. i 6. obraz w każdym kompozycie, które mają zamienioną dolną i górną połówkę. Czy jest coś dziwnego w CGImage, które wynika z przycięcia do dolnej części dużego obrazu? Ponownie powinienem wspomnieć, że działa to doskonale, jeśli UIImage nie jest konwertowany na NSData, a następnie z powrotem. – Mike
Tak więc w powyższym przykładzie szerokość wynosi 768, wysokość 1024 i łamie się, gdy x wynosi 0 lub 1, a y 2. Działa to dobrze, gdy y wynosi 0 lub 1. Czy jest to przypadek, w którym CGImageCreateWithImageInRect po prostu nie może sobie poradzić obrazy tak duże? – Mike
Trudno dostrzec, co może być przyczyną tego. Proponuję zapakowanie tego jako aplikacji testowej i wypełnienie radaru na stronie bugreporter.apple.com. Lub jeśli masz do czynienia z incydentem DTS, uruchom go przez nich w nadziei na obejście. –