Нарезка UIImage на iPhone - PullRequest
       27

Нарезка UIImage на iPhone

13 голосов
/ 30 октября 2008

Цель: взять 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))];

В обоих случаях дисплей работал. Проблемы возникают только тогда, когда я пытаюсь вырезать часть изображения.

Ответы [ 2 ]

5 голосов
/ 30 октября 2008

После еще нескольких экспериментов я нашел следующее решение (хотя я до сих пор не знаю, почему оно не работает так, как было написано изначально). Но в любом случае срезы работают после того, как код изменения размера введен в действие даже при изменении размера не нужно:

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. Да, если / еще здесь больше не требуется. Удаление его до Я знал, что это сработает, было бы глупо.

1 голос
/ 07 июня 2009

Просто из любопытства, почему вы создали свой изменяемый массив с границей 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;
}

Ева Шиффер

...