Нарезка UIImage на iPhone
Цель: взять UIImage, вырезать квадрат посередине, изменить размер квадрата на 320x320 пикселей, нарезать изображение на 16 80x80 изображений, сохранить 16 изображений в массиве.
Здесь мой код:
CGImageRef originalImage, resizedImage, finalImage, tmp;
float imgWidth, imgHeight, diff;
UIImage *squareImage, *playImage;
NSMutableArray *tileImgArray;
int r, c;
originalImage = [image CGImage];
imgWidth = image.size.width;
imgHeight = image.size.height;
diff = fabs(imgWidth - imgHeight);
if(imgWidth > imgHeight){
resizedImage = CGImageCreateWithImageInRect(originalImage, CGRectMake(floor(diff/2), 0, imgHeight, imgHeight));
}else{
resizedImage = CGImageCreateWithImageInRect(originalImage, CGRectMake(0, floor(diff/2), imgWidth, imgWidth));
}
CGImageRelease(originalImage);
squareImage = [UIImage imageWithCGImage:resizedImage];
if(squareImage.size.width != squareImage.size.height){
NSLog(@"image cutout error!");
//*code to return to main menu of app, irrelevant here
}else{
float newDim = squareImage.size.width;
if(newDim != 320.0){
CGSize finalSize = CGSizeMake(320.0, 320.0);
UIGraphicsBeginImageContext(finalSize);
[squareImage drawInRect:CGRectMake(0, 0, finalSize.width, finalSize.height)];
playImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}else{
playImage = squareImage;
}
}
finalImage = [playImage CGImage];
tileImgArray = [NSMutableArray arrayWithCapacity:0];
for(int i = 0; i < 16; i++){
r = i/4;
c = i%4;
//*
tmp = CGImageCreateWithImageInRect(finalImage, CGRectMake(c*tileSize, r*tileSize, tileSize, tileSize));
[tileImgArray addObject:[UIImage imageWithCGImage:tmp]];
}
Код работает правильно, когда исходное (переменное изображение) имеет меньший размер, размер которого больше или меньше 320 пикселей. Когда он ровно 320, результирующие изображения 80x80 почти полностью черные, некоторые с несколькими пикселями по краям, которые могут (я не могу сказать), быть в исходном изображении.
Я тестировал, отображая полное изображение как напрямую:
[UIImage imageWithCGImage:finalImage];
И косвенно:
[UIImage imageWithCGImage:CGImageCreateWithImageInRect(finalImage, CGRectMake(0, 0, 320, 320))];
В обоих случаях дисплей работал. Проблемы возникают только при попытке отрезать часть изображения.
Ответы
Ответ 1
После нескольких экспериментов я нашел следующее решение (я до сих пор не знаю, почему он не работал, как изначально написанный.) Но в любом случае, нарезка работает после изменения кода изменения размера даже при изменении размера не требуется:
if(newDim != 320.0){
CGSize finalSize = CGSizeMake(320.0, 320.0);
UIGraphicsBeginImageContext(finalSize);
[squareImage drawInRect:CGRectMake(0, 0, finalSize.width, finalSize.height)];
playImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}else{
CGSize finalSize = CGSizeMake(320.0, 320.0);
UIGraphicsBeginImageContext(finalSize);
[squareImage drawInRect:CGRectMake(0, 0, finalSize.width, finalSize.height)];
playImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
У кого-нибудь есть подсказка, ПОЧЕМУ это происходит?
P.S. Да, если /else больше не требуется здесь. Удаление раньше Я знал, что это будет работать, было бы глупо.
Ответ 2
Просто из любопытства, почему вы создали свой изменяемый массив с ограничением 0, когда вы знаете, что собираетесь положить в него 16 вещей?
Ну, кроме этого, я пробовал основные методы, которые вы использовали для изменения размера и нарезки (мне не нужно обрезать, потому что я работаю с изображениями, которые уже являются квадратными), и я не могу воспроизвести ваши проблема в симуляторе. Вы можете попытаться разбить свой код на три отдельные функции (обрезать до квадрата, изменить размер и срез на кусочки), а затем проверить три отдельно, чтобы вы могли выяснить, какой из трех этапов вызывает проблемы (то есть входные изображения, которые вы управляетесь в обычной графической программе, а не используете объектив c, а затем проверяете, что вы получите!).
Я приложу свои версии функций изменения размера и среза ниже, которые, надеюсь, будут полезны. Приятно было, чтобы ваши версии смотрели, так как мне не приходилось каждый раз находить все методы.:)
Как примечание, упомянутый двухмерный массив - это мой собственный класс, построенный из NSMutableArrays, но вы можете легко реализовать свою собственную версию или вместо этого использовать плоский NSMutableArray.;)
// cut the given image into a grid of equally sized smaller images
// this assumes that the image can be equally divided in the requested increments
// the images will be stored in the return array in [row][column] order
+ (TwoDimensionalArray *) chopImageIntoGrid : (UIImage *) originalImage : (int) numberOfRows : (int) numberOfColumns
{
// figure out the size of our tiles
int tileWidth = originalImage.size.width / numberOfColumns;
int tileHeight = originalImage.size.height / numberOfRows;
// create our return array
TwoDimensionalArray * toReturn = [[TwoDimensionalArray alloc] initWithBounds : numberOfRows
: numberOfColumns];
// get a CGI image version of our image
CGImageRef cgVersionOfOriginal = [originalImage CGImage];
// loop to chop up each row
for(int row = 0; row < numberOfRows ; row++){
// loop to chop up each individual piece by column
for (int column = 0; column < numberOfColumns; column++)
{
CGImageRef tempImage =
CGImageCreateWithImageInRect(cgVersionOfOriginal,
CGRectMake(column * tileWidth,
row * tileHeight,
tileWidth,
tileHeight));
[toReturn setObjectAt : row : column : [UIImage imageWithCGImage:tempImage]];
}
}
// now return the set of images we created
return [toReturn autorelease];
}
// this method resizes an image to the requested dimentions
// be a bit careful when using this method, since the resize will not respect
// the proportions of the image
+ (UIImage *) resize : (UIImage *) originalImage : (int) newWidth : (int) newHeight
{
// translate the image to the new size
CGSize newSize = CGSizeMake(newWidth, newHeight); // the new size we want the image to be
UIGraphicsBeginImageContext(newSize); // downside: this can't go on a background thread, I'm told
[originalImage drawInRect : CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); // get our new image
UIGraphicsEndImageContext();
// return our brand new image
return newImage;
}
Ева Шиффер