UIImage: ridimensiona, quindi ritaglia


187

Ho letteralmente sfidato la mia faccia in questo per giorni ormai e anche se sento costantemente di essere al limite della rivelazione, semplicemente non riesco a raggiungere il mio obiettivo.

Ho pensato, in anticipo nelle fasi concettuali del mio progetto, che sarebbe una cosa banale catturare un'immagine dalla fotocamera o dalla libreria dell'iPhone, ridimensionarla fino a un'altezza specificata, usando una funzione equivalente all'opzione Aspect Fill di UIImageView (interamente nel codice), quindi ritagliare tutto ciò che non rientrava in un CGRect passato.

Ottenere l'immagine originale dalla fotocamera o dalla libreria, è stato banale. Sono scioccato da quanto si siano dimostrati difficili gli altri due passi.

L'immagine allegata mostra ciò che sto cercando di ottenere. Qualcuno, per favore, sarebbe così gentile da tenermi la mano? Ogni esempio di codice che ho trovato finora sembra distruggere l'immagine, essere capovolto, sembrare una schifezza, disegnare fuori dai limiti o altrimenti semplicemente non funzionare correttamente.


7
Il collegamento è interrotto per la tua immagine.

1
Una cosa che nessuno ci sorprende è che Apple non l'abbia aggiunto a UIImagePickerController - è troppo difficile ;-)
Tim

Risposte:


246

Avevo bisogno della stessa cosa: nel mio caso, scegliere la dimensione che si adattava una volta ridimensionata, quindi ritagliare ciascuna estremità per adattare il resto alla larghezza. (Sto lavorando in orizzontale, quindi potrei non aver notato alcuna carenza nella modalità ritratto.) Ecco il mio codice: fa parte di una categoria su UIImage. La dimensione target nel mio codice è sempre impostata sulla dimensione a schermo intero del dispositivo.

@implementation UIImage (Extras)

#pragma mark -
#pragma mark Scale and crop image

- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
{
    UIImage *sourceImage = self;
    UIImage *newImage = nil;    
    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;
    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;
    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;
    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) 
    {
        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor > heightFactor) 
        {
            scaleFactor = widthFactor; // scale to fit height
        }
        else
        {
            scaleFactor = heightFactor; // scale to fit width
        }

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image
        if (widthFactor > heightFactor)
        {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        }
        else
        {
            if (widthFactor < heightFactor)
            {
                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
            }
        }
    }   

    UIGraphicsBeginImageContext(targetSize); // this will crop

    CGRect thumbnailRect = CGRectZero;
    thumbnailRect.origin = thumbnailPoint;
    thumbnailRect.size.width  = scaledWidth;
    thumbnailRect.size.height = scaledHeight;

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();

    if(newImage == nil)
    {
        NSLog(@"could not scale image");
    }

    //pop the context to get back to the default
    UIGraphicsEndImageContext();

    return newImage;
}

1
curiosamente funziona nel simulatore ma sul dispositivo ricevo ExecBadAccess ..
Sorin Antohi,

5
Il problema con il exec difettoso si verifica perché le funzioni di UIImage non sono thread-safe. Ecco perché a volte si verifica un arresto anomalo, a volte no
Erik

1
Questo codice ha funzionato alla grande per me, ma era sfocato sulla retina. La combinazione di questo codice con il commento qui sotto tutto perfetto fatta: stackoverflow.com/questions/603907/...
MaxGabriel

23
Usa UIGraphicsBeginImageContextWithOptions (targetSize, YES, 0.0); per rendere piacevole l'immagine anche sulla retina.
Borut Tomazin,

1
Questo funziona per me in modalità Ritratto, ma non in orizzontale. L'altezza è allungata nel paesaggio. Qualche idea sul perché?
Darren,

77

Un post precedente contiene codice per un metodo per ridimensionare il tuo UIImage. La parte pertinente è la seguente:

+ (UIImage*)imageWithImage:(UIImage*)image 
               scaledToSize:(CGSize)newSize;
{
   UIGraphicsBeginImageContext( newSize );
   [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
   UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   return newImage;
}

Per quanto riguarda il ritaglio, credo che se si modifica il metodo per utilizzare una dimensione diversa per il ridimensionamento rispetto al contesto, l'immagine risultante dovrebbe essere ritagliata ai limiti del contesto.


3
Non ha senso il motivo per cui questo risolve l'orientamento dell'immagine, ma lo fa e quindi risolto il mio problema con la fotocamera che non restituisce il giusto orientamento nel originalImage. Grazie.
Brenden,

10
Ho scoperto che il ridimensionamento di un'immagine su un dispositivo retina sembrava sfocato. Per mantenere la chiarezza, ho modificato la prima linea alla seguente: UIGraphicsBeginImageContextWithOptions(newSize, 1.0f, 0.0f);. (spiegato qui: stackoverflow.com/questions/4334233/... )
johngraham

Ruota l'immagine, ma non la ritaglia correttamente! Perché ha così tanti voti?
Dejell,

18
+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize {
    //If scaleFactor is not touched, no scaling will occur      
    CGFloat scaleFactor = 1.0;

    //Deciding which factor to use to scale the image (factor = targetSize / imageSize)
    if (image.size.width > targetSize.width || image.size.height > targetSize.height)
        if (!((scaleFactor = (targetSize.width / image.size.width)) > (targetSize.height / image.size.height))) //scale to fit width, or
            scaleFactor = targetSize.height / image.size.height; // scale to fit heigth.

    UIGraphicsBeginImageContext(targetSize); 

    //Creating the rect where the scaled image is drawn in
    CGRect rect = CGRectMake((targetSize.width - image.size.width * scaleFactor) / 2,
                             (targetSize.height -  image.size.height * scaleFactor) / 2,
                             image.size.width * scaleFactor, image.size.height * scaleFactor);

    //Draw the image into the rect
    [image drawInRect:rect];

    //Saving the image, ending image context
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return scaledImage;
}

Propongo questo. Non è una bellezza? ;)


1
Questo è buono, se rimuovi prima l'istruzione if si comporta come AspectFill.
RaffAl


7

Ecco qui. Questo è perfetto ;-)

EDIT: vedi il commento qui sotto - "Non funziona con alcune immagini, non riesce con: CGContextSetInterpolationQuality: errore 0x0 di contesto non valido"

// Resizes the image according to the given content mode, taking into account the image's orientation
- (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode imageToScale:(UIImage*)imageToScale bounds:(CGSize)bounds interpolationQuality:(CGInterpolationQuality)quality {
    //Get the size we want to scale it to
    CGFloat horizontalRatio = bounds.width / imageToScale.size.width;
    CGFloat verticalRatio = bounds.height / imageToScale.size.height;
    CGFloat ratio;

    switch (contentMode) {
        case UIViewContentModeScaleAspectFill:
            ratio = MAX(horizontalRatio, verticalRatio);
            break;

        case UIViewContentModeScaleAspectFit:
            ratio = MIN(horizontalRatio, verticalRatio);
            break;

        default:
            [NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %d", contentMode];
    }

    //...and here it is
    CGSize newSize = CGSizeMake(imageToScale.size.width * ratio, imageToScale.size.height * ratio);


    //start scaling it
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGImageRef imageRef = imageToScale.CGImage;
    CGContextRef bitmap = CGBitmapContextCreate(NULL,
                                                newRect.size.width,
                                                newRect.size.height,
                                                CGImageGetBitsPerComponent(imageRef),
                                                0,
                                                CGImageGetColorSpace(imageRef),
                                                CGImageGetBitmapInfo(imageRef));

    CGContextSetInterpolationQuality(bitmap, quality);

    // Draw into the context; this scales the image
    CGContextDrawImage(bitmap, newRect, imageRef);

    // Get the resized image from the context and a UIImage
    CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    // Clean up
    CGContextRelease(bitmap);
    CGImageRelease(newImageRef);

    return newImage;
}

1
Sembra davvero bello :) Mi piace InterpolazioneQualità qui
Kostiantyn Sokolinskyi

Non funziona con alcune immagini, non riesce con: CGContextSetInterpolationQuality: errore 0x0 contesto non valido
RaffAl

6

Questa è una versione della risposta di Jane Sales in Swift. Saluti!

public func resizeImage(image: UIImage, size: CGSize) -> UIImage? {
    var returnImage: UIImage?

    var scaleFactor: CGFloat = 1.0
    var scaledWidth = size.width
    var scaledHeight = size.height
    var thumbnailPoint = CGPointMake(0, 0)

    if !CGSizeEqualToSize(image.size, size) {
        let widthFactor = size.width / image.size.width
        let heightFactor = size.height / image.size.height

        if widthFactor > heightFactor {
            scaleFactor = widthFactor
        } else {
            scaleFactor = heightFactor
        }

        scaledWidth = image.size.width * scaleFactor
        scaledHeight = image.size.height * scaleFactor

        if widthFactor > heightFactor {
            thumbnailPoint.y = (size.height - scaledHeight) * 0.5
        } else if widthFactor < heightFactor {
            thumbnailPoint.x = (size.width - scaledWidth) * 0.5
        }
    }

    UIGraphicsBeginImageContextWithOptions(size, true, 0)

    var thumbnailRect = CGRectZero
    thumbnailRect.origin = thumbnailPoint
    thumbnailRect.size.width = scaledWidth
    thumbnailRect.size.height = scaledHeight

    image.drawInRect(thumbnailRect)
    returnImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return returnImage
}

2

Ho modificato il codice di Brad Larson. Aspetto riempirà l'immagine in un dato rettangolo.

-(UIImage*) scaleAndCropToSize:(CGSize)newSize;
{
    float ratio = self.size.width / self.size.height;

    UIGraphicsBeginImageContext(newSize);

    if (ratio > 1) {
        CGFloat newWidth = ratio * newSize.width;
        CGFloat newHeight = newSize.height;
        CGFloat leftMargin = (newWidth - newHeight) / 2;
        [self drawInRect:CGRectMake(-leftMargin, 0, newWidth, newHeight)];
    }
    else {
        CGFloat newWidth = newSize.width;
        CGFloat newHeight = newSize.height / ratio;
        CGFloat topMargin = (newHeight - newWidth) / 2;
        [self drawInRect:CGRectMake(0, -topMargin, newSize.width, newSize.height/ratio)];
    }

    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

1
Testato con altre due immagini, ritratto e paesaggio. Questo NON sta eseguendo il riempimento aspetto.
RaffAl

2

La versione Xamarin.iOS per la risposta accettata su come ridimensionare e quindi ritagliare UIImage (Aspect Fill) è inferiore

    public static UIImage ScaleAndCropImage(UIImage sourceImage, SizeF targetSize)
    {
        var imageSize = sourceImage.Size;
        UIImage newImage = null;
        var width = imageSize.Width;
        var height = imageSize.Height;
        var targetWidth = targetSize.Width;
        var targetHeight = targetSize.Height;
        var scaleFactor = 0.0f;
        var scaledWidth = targetWidth;
        var scaledHeight = targetHeight;
        var thumbnailPoint = PointF.Empty;
        if (imageSize != targetSize)
        {
            var widthFactor = targetWidth / width;
            var heightFactor = targetHeight / height;
            if (widthFactor > heightFactor)
            {
                scaleFactor = widthFactor;// scale to fit height
            }
            else
            {
                scaleFactor = heightFactor;// scale to fit width
            }
            scaledWidth = width * scaleFactor;
            scaledHeight = height * scaleFactor;
            // center the image
            if (widthFactor > heightFactor)
            {
                thumbnailPoint.Y = (targetHeight - scaledHeight) * 0.5f;
            }
            else
            {
                if (widthFactor < heightFactor)
                {
                    thumbnailPoint.X = (targetWidth - scaledWidth) * 0.5f;
                }
            }
        }
        UIGraphics.BeginImageContextWithOptions(targetSize, false, 0.0f);
        var thumbnailRect = new RectangleF(thumbnailPoint, new SizeF(scaledWidth, scaledHeight));
        sourceImage.Draw(thumbnailRect);
        newImage = UIGraphics.GetImageFromCurrentImageContext();
        if (newImage == null)
        {
            Console.WriteLine("could not scale image");
        }
        //pop the context to get back to the default
        UIGraphics.EndImageContext();

        return newImage;
    }

2

Ho convertito la guida di Sam Wirch in rapida e ha funzionato bene per me, anche se nell'immagine finale c'è un leggero "schiacciamento" che non sono riuscito a risolvere.

func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage {
    var ratio: CGFloat = 0
    var delta: CGFloat = 0
    var offset = CGPointZero
    if image.size.width > image.size.height {
        ratio = newSize.width / image.size.width
        delta = (ratio * image.size.width) - (ratio * image.size.height)
        offset = CGPointMake(delta / 2, 0)
    } else {
        ratio = newSize.width / image.size.height
        delta = (ratio * image.size.height) - (ratio * image.size.width)
        offset = CGPointMake(0, delta / 2)
    }
    let clipRect = CGRectMake(-offset.x, -offset.y, (ratio * image.size.width) + delta, (ratio * image.size.height) + delta)
    UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
    UIRectClip(clipRect)
    image.drawInRect(clipRect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

Se qualcuno vuole la versione obiettivo c, è sul suo sito web.


2

Ho scoperto che Swift 3 pubblicato da Evgenii Kanvets non ridimensiona uniformemente l'immagine.

Ecco la mia versione di Swift 4 della funzione che non schiaccia l'immagine:

static func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage? {

    // This function returns a newImage, based on image
    // - image is scaled uniformaly to fit into a rect of size newSize
    // - if the newSize rect is of a different aspect ratio from the source image
    //     the new image is cropped to be in the center of the source image
    //     (the excess source image is removed)

    var ratio: CGFloat = 0
    var delta: CGFloat = 0
    var drawRect = CGRect()

    if newSize.width > newSize.height {

        ratio = newSize.width / image.size.width
        delta = (ratio * image.size.height) - newSize.height
        drawRect = CGRect(x: 0, y: -delta / 2, width: newSize.width, height: newSize.height + delta)

    } else {

        ratio = newSize.height / image.size.height
        delta = (ratio * image.size.width) - newSize.width
        drawRect = CGRect(x: -delta / 2, y: 0, width: newSize.width + delta, height: newSize.height)

    }

    UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
    image.draw(in: drawRect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
} 

Ho dovuto impostare il ridimensionamento su 1.0 UIGraphicsBeginImageContextWithOptionsma altri hanno funzionato perfettamente. Grazie!
maxmzd,

1

Il seguente semplice codice ha funzionato per me.

[imageView setContentMode:UIViewContentModeScaleAspectFill];
[imageView setClipsToBounds:YES];

Il tuo codice funziona bene per gli UIImageViewoggetti. Tuttavia, questa domanda riguarda il ridimensionamento UIImagedell'oggetto stesso.
Rickster,

1
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0,0.0,ScreenWidth,ScreenHeigth)];
    [scrollView setBackgroundColor:[UIColor blackColor]];
    [scrollView setDelegate:self];
    [scrollView setShowsHorizontalScrollIndicator:NO];
    [scrollView setShowsVerticalScrollIndicator:NO];
    [scrollView setMaximumZoomScale:2.0];
    image=[image scaleToSize:CGSizeMake(ScreenWidth, ScreenHeigth)];
    imageView = [[UIImageView alloc] initWithImage:image];
    UIImageView* imageViewBk = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]];
    [self.view addSubview:imageViewBk];
    CGRect rect;
    rect.origin.x=0;
    rect.origin.y=0;
    rect.size.width = image.size.width;
    rect.size.height = image.size.height;

    [imageView setFrame:rect];

    [scrollView setContentSize:[imageView frame].size];
    [scrollView setMinimumZoomScale:[scrollView frame].size.width / [imageView frame].size.width];
    [scrollView setZoomScale:[scrollView minimumZoomScale]];
    [scrollView addSubview:imageView];

    [[self view] addSubview:scrollView];

allora puoi fare delle schermate alla tua immagine in questo modo

float zoomScale = 1.0 / [scrollView zoomScale];
CGRect rect;
rect.origin.x = [scrollView contentOffset].x * zoomScale;
rect.origin.y = [scrollView contentOffset].y * zoomScale;
rect.size.width = [scrollView bounds].size.width * zoomScale;
rect.size.height = [scrollView bounds].size.height * zoomScale;

CGImageRef cr = CGImageCreateWithImageInRect([[imageView image] CGImage], rect);

UIImage *cropped = [UIImage imageWithCGImage:cr];

CGImageRelease(cr);

0
- (UIImage*)imageScale:(CGFloat)scaleFactor cropForSize:(CGSize)targetSize
{
    targetSize = !targetSize.width?self.size:targetSize;
    UIGraphicsBeginImageContext(targetSize); // this will crop

    CGRect thumbnailRect = CGRectZero;

    thumbnailRect.size.width  = targetSize.width*scaleFactor;
    thumbnailRect.size.height = targetSize.height*scaleFactor;
    CGFloat xOffset = (targetSize.width- thumbnailRect.size.width)/2;
    CGFloat yOffset = (targetSize.height- thumbnailRect.size.height)/2;
    thumbnailRect.origin = CGPointMake(xOffset,yOffset);

    [self drawInRect:thumbnailRect];

    UIImage *newImage  = UIGraphicsGetImageFromCurrentImageContext();

    if(newImage == nil)
    {
        NSLog(@"could not scale image");
    }

    UIGraphicsEndImageContext();

    return newImage;
}

Di seguito l'esempio di lavoro: Immagine a sinistra - (immagine di origine); Immagine a destra con scala x2

inserisci qui la descrizione dell'immagine

Se vuoi ridimensionare l'immagine ma conservarne la cornice (proporzioni), chiama il metodo in questo modo:

[yourImage imageScale:2.0f cropForSize:CGSizeZero];

0

Questa domanda sembra essere stata messa a tacere, ma nella mia ricerca di una soluzione che potrei comprendere più facilmente (e scritta in Swift), sono arrivato a questo (pubblicato anche su: Come ritagliare l'UIImage? )


Volevo essere in grado di ritagliare da una regione in base a un rapporto proporzioni e ridimensionare a una dimensione in base a un limite esterno. Ecco la mia variazione:

import AVFoundation
import ImageIO

class Image {

    class func crop(image:UIImage, crop source:CGRect, aspect:CGSize, outputExtent:CGSize) -> UIImage {

        let sourceRect = AVMakeRectWithAspectRatioInsideRect(aspect, source)
        let targetRect = AVMakeRectWithAspectRatioInsideRect(aspect, CGRect(origin: CGPointZero, size: outputExtent))

        let opaque = true, deviceScale:CGFloat = 0.0 // use scale of device's main screen
        UIGraphicsBeginImageContextWithOptions(targetRect.size, opaque, deviceScale)

        let scale = max(
            targetRect.size.width / sourceRect.size.width,
            targetRect.size.height / sourceRect.size.height)

        let drawRect = CGRect(origin: -sourceRect.origin * scale, size: image.size * scale)
        image.drawInRect(drawRect)

        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return scaledImage
    }
}

Ci sono un paio di cose che ho trovato confuse, le preoccupazioni separate di ritaglio e ridimensionamento. Il ritaglio viene gestito con l'origine del rettangolo che si passa a drawInRect e il ridimensionamento viene gestito dalla porzione di dimensione. Nel mio caso, avevo bisogno di mettere in relazione le dimensioni del rettangolo di ritaglio sulla sorgente, con il mio rettangolo di output dello stesso formato. Il fattore di scala viene quindi emesso / immesso e questo deve essere applicato a drawRect (passato a drawInRect).

Un avvertimento è che questo approccio presuppone effettivamente che l'immagine che stai disegnando sia più grande del contesto dell'immagine. Non l'ho provato, ma penso che tu possa usare questo codice per gestire il ritaglio / zoom, ma definendo esplicitamente il parametro di scala come parametro di scala sopra menzionato. Per impostazione predefinita, UIKit applica un moltiplicatore basato sulla risoluzione dello schermo.

Infine, va notato che questo approccio UIKit è di livello superiore rispetto agli approcci CoreGraphics / Quartz e Core Image e sembra gestire i problemi di orientamento delle immagini. Vale anche la pena ricordare che è abbastanza veloce, secondo ImageIO, secondo questo post qui: http://nshipster.com/image-resizing/


0

Versione rapida:

    static func imageWithImage(image:UIImage, newSize:CGSize) ->UIImage {
    UIGraphicsBeginImageContextWithOptions(newSize, true, UIScreen.mainScreen().scale);
    image.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))

    let newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
    return newImage
}

1
Bella piccola funzione ma sono abbastanza sicuro che questo estende l'immagine a una dimensione particolare, non mantiene le proporzioni e il ritaglio ...
William T.

Sì, hai ragione, questo è solo per ridurre l'immagine a una dimensione paritcolare.
Roman Barzyczak,

0

Ecco una versione Swift 3 della guida di Sam Wirch a Swift pubblicata da William T.

extension UIImage {

    static func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage? {
        var ratio: CGFloat = 0
        var delta: CGFloat = 0
        var offset = CGPoint.zero

        if image.size.width > image.size.height {
            ratio = newSize.width / image.size.width
            delta = (ratio * image.size.width) - (ratio * image.size.height)
            offset = CGPoint(x: delta / 2, y: 0)
        } else {
            ratio = newSize.width / image.size.height
            delta = (ratio * image.size.height) - (ratio * image.size.width)
            offset = CGPoint(x: 0, y: delta / 2)
        }

        let clipRect = CGRect(x: -offset.x, y: -offset.y, width: (ratio * image.size.width) + delta, height: (ratio * image.size.height) + delta)
        UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
        UIRectClip(clipRect)
        image.draw(in: clipRect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage
    }

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.