Domanda

Obiettivo: prendere un UIImage, ritagliare un quadrato nel mezzo, cambiare la dimensione del quadrato in 320x320 pixel, suddividere l'immagine in 16 immagini 80x80, salvare le 16 immagini in un array.

Ecco il mio codice:

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]];
}

Il codice funziona correttamente quando l'originale (l'immagine variabile) ha una dimensione minore o maggiore o minore di 320 pixel. Quando sono esattamente 320, le immagini 80x80 risultanti sono quasi interamente nere, alcune con alcuni pixel ai bordi che potrebbero (non posso davvero dirlo) dall'immagine originale.

Ho provato visualizzando l'immagine completa sia direttamente:

[UIImage imageWithCGImage:finalImage];

E indirettamente:

[UIImage imageWithCGImage:CGImageCreateWithImageInRect(finalImage, CGRectMake(0, 0, 320, 320))];

In entrambi i casi, il display ha funzionato. I problemi sorgono solo quando provo a tagliare una parte dell'immagine.

È stato utile?

Soluzione

Dopo qualche altra sperimentazione, ho trovato la seguente soluzione (non so ancora perché non abbia funzionato come scritto in origine, però). Comunque, lo slicing funziona dopo che il codice di ridimensionamento viene messo in atto anche quando si ridimensiona non è necessario:

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();
}

Qualcuno ha qualche idea PERCHÉ sta succedendo?

P.S. Sì, se / else non è più richiesto qui. Rimuoverlo prima sapevo che avrebbe funzionato sarebbe stato stupido, però.

Altri suggerimenti

Solo per curiosità, perché hai creato il tuo array mutabile con limite di 0 quando sai che ci metterai 16 cose?

Bene, a parte questo, ho provato le tecniche di base che hai usato per ridimensionare e tagliare (non avevo bisogno di ritagliare, perché sto lavorando con immagini che sono già quadrate) e non riesco a riprodurre il tuo problema nel simulatore. Potresti voler provare a suddividere il codice in tre funzioni separate (ritagliare per quadrare, ridimensionare e tagliare in pezzi) e quindi testare i tre separatamente in modo da poter capire quale dei tre passaggi sta causando i problemi (ad esempio immagini di input che hai manipolato in un normale programma di grafica invece di utilizzare l'obiettivo c e quindi ispezionare ciò che torni indietro!).

Allegherò le mie versioni delle funzioni di ridimensionamento e divisione di seguito, che si spera siano utili. È stato bello avere le tue versioni da guardare, dal momento che non ho dovuto trovare tutti i metodi da solo per una volta. :)

Proprio come una nota, l'array bidimensionale menzionato è la mia classe costruita con NSMutableArrays, ma potresti facilmente implementare la tua versione o utilizzare invece un NSMutableArray piatto. ;)

// 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;
}

Eva Schiffer

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top