Come convertire una UIView in un'immagine


94

Voglio convertire una UIView in un'immagine e salvarla nella mia app. Qualcuno può dirmi come acquisire uno screenshot di una vista o convertirlo in un'immagine e qual è il modo migliore per salvarlo in un'app (non rullino fotografico)? Ecco il codice per la vista:

var overView   = UIView(frame: CGRectMake(0, 0, self.view.frame.width/1.3, self.view.frame.height/1.3))
overView.center = CGPointMake(CGRectGetMidX(self.view.bounds),
CGRectGetMidY(self.view.bounds)-self.view.frame.height/16);
overView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(overView)
self.view.bringSubviewToFront(overView)

Risposte:


189

Un'estensione su UIViewdovrebbe fare il trucco.

extension UIView {

    // Using a function since `var image` might conflict with an existing variable
    // (like on `UIImageView`)
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
}

Apple sconsiglia di utilizzare l' UIGraphicsBeginImageContextavvio di iOS 10 con l'introduzione della gamma di colori P3. UIGraphicsBeginImageContextè solo sRGB e 32 bit. Hanno introdotto la nuova UIGraphicsImageRendererAPI che è completamente gestita dal colore, basata su blocchi, ha sottoclassi per PDF e immagini e gestisce automaticamente la durata del contesto. Controlla la sessione 205 di WWDC16 per maggiori dettagli (il rendering dell'immagine inizia intorno alle 11:50)

Per assicurarti che funzioni su tutti i dispositivi, utilizza #availablecon un fallback alle versioni precedenti di iOS:

extension UIView {

    // Using a function since `var image` might conflict with an existing variable
    // (like on `UIImageView`)
    func asImage() -> UIImage {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContext(self.frame.size)
            self.layer.render(in:UIGraphicsGetCurrentContext()!)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return UIImage(cgImage: image!.cgImage!)
        }
    }
}

9
Questo dovrebbe essere contrassegnato come la risposta corretta. Tutte le altre opzioni faranno perdere chiarezza all'immagine renderizzata e appariranno pixelati / sfocati.
TuplingD

L'unico modo giusto! Per i principianti l'utilizzo è: let image = customView.asImage ()
Fabio

1
È possibile rendere la UIView con uno sfondo trasparente? Il mio ha degli angoli arrotondati.
ixany

@ixany Questo dovrebbe già occuparsene. L'ho appena provato con quanto segue in un parco giochi e ha funzionato: let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)); view.backgroundColor = .black; view.layer.cornerRadius = 9; view.asImage();
Naveed J.

2
Grazie! Se qualcuno lo sa, sarei curioso di sapere quali differenze ci sono con il codice di hackingwithswift.com/example-code/media/… : return renderer.image {ctx in drawHierarchy (in: bounds, afterScreenUpdates: true)}
Kqtr

63

puoi usare l'estensione

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in:UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: image!.cgImage!)
    }
}

Ecco la versione swift 3/4:

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in:UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: image!.cgImage!)
    }
}

5
Sono imbarazzato per essere quello che lo chiede, ma come lo chiamo? Non ho un'immagine e una UIView che voglio essere un'immagine. Il codice sopra mi fornisce un'estensione UIImage ... ma ora cosa?
Dave G

8
let image = UIImage(view: myView)
doctorBroctor

Non funziona per me poiché UIGraphicsGetCurrentContext () può essere nullo e il codice si blocca.
Juan Carlos Ospina Gonzalez

@JuanCarlosOspinaGonzalez Se UIGraphicsGetCurrentContext ha restituito zero, sospetto che sia necessario controllare UIGraphicsBeginImageContext per capire perché non è riuscito. La mia ipotesi è che una delle dimensioni della tua taglia sia zero o altrimenti non valida, ma non ho idea di cosa possa realmente causare il fallimento.
John Stephen

2
dovresti anche tenere a mente la scala dello schermo, quindi sostituirei la prima riga dell'inizializzatore con questa: UIGraphicsBeginImageContextWithOptions(view.frame.size, false, UIScreen.main.scale)
iVentis

41

Converti il ​​tuo UIView in immagine tramite drawViewHierarchyInRect: afterScreenUpdates: che è molte volte più veloce di renderInContext

Nota importante: non chiamare questa funzione da viewDidLoad o viewWillAppear , assicurati di catturare una vista dopo che è stata visualizzata / caricata completamente

Obj C

     UIGraphicsBeginImageContextWithOptions(myView.bounds.size, myView.opaque, 0.0f);
     [myView drawViewHierarchyInRect:myView.bounds afterScreenUpdates:NO];
     UIImage *snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();

     myImageView.image =  snapshotImageFromMyView;

Salvare l'album fotografico dell'immagine modificata

     UIImageWriteToSavedPhotosAlbum(snapshotImageFromMyView, nil,nil, nil);

Swift 3/4

    UIGraphicsBeginImageContextWithOptions(myView.bounds.size, myView.isOpaque, 0.0)
    myView.drawHierarchy(in: myView.bounds, afterScreenUpdates: false)
    let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    print(snapshotImageFromMyView)
    myImageView.image = snapshotImageFromMyView

Generalizzazione super facile con estensione, iOS11, swift3 / 4

extension UIImage{
    convenience init(view: UIView) {

    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
    view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    self.init(cgImage: (image?.cgImage)!)

  }
}


Use : 
 //myView is completly loaded/visible , calling this code after only after viewDidAppear is call
 imgVV.image = UIImage.init(view: myView)
 // Simple image object
 let img =  UIImage.init(view: myView)

3
Non funziona per me, ho ottenuto uno schermo nero per la mia UiImage
Badr Filali,

Veramente ?? Puoi incollare il tuo codice qui .. U potrebbe usare un oggetto UIView sbagliato da convertire come UIImage.
ViJay Avhad

`func convertViewIntoImg () -> Void {imgFakeCard.image = UIImage.init (view: card)}` Con la tua estensione in swift 3 questa funzione è chiamata in viewDidLoad
Badr Filali

1
Grazie per aver pubblicato il tuo codice e per aver menzionato che hai chiamato viewDidLoad. Ecco cosa hai sbagliato. Stai acquisendo un'istantanea della vista prima che venga caricata in memoria. Prova a chiamare il codice in viewDidAppear, questo risolverà sicuramente il problema. Qualsiasi domanda si prega di rispondere.
ViJay Avhad

Funziona benissimo grazie, il problema è venuto da dove ho chiamato la tua estensione
Badr Filali

20

Su iOS 10:

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: (image?.cgImage)!)
    }
}

1
questo porta a crash.
KingPolygon,

18

Best practice a partire da iOS 10 e Swift 3

pur supportando iOS 9 e versioni precedenti, funziona ancora a partire da iOS 13, Xcode 11.1, Swift 5.1

extension UIView {

    func asImage() -> UIImage? {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
            defer { UIGraphicsEndImageContext() }
            guard let currentContext = UIGraphicsGetCurrentContext() else {
                return nil
            }
            self.layer.render(in: currentContext)
            return UIGraphicsGetImageFromCurrentImageContext()
        }
    }
}

Non sono sicuro di cosa significhi la domanda con:

qual è il modo migliore per salvarlo in un'app (non rullino fotografico)?


17
    UIGraphicsBeginImageContext(self.view.bounds.size);        
    self.view.layer.renderInContext(UIGraphicsGetCurrentContext())
    var screenShot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();


1
UIGraphicsGetImageFromCurrentImageContext restituisce UIImage. Non c'è bisogno di lanciarlo a UIImage
Leo Dabus

Questo cattura lo screenshot dell'intera vista, sì? Voglio solo convertire una panoramica UIView cioè nel mio codice che è sottoview di self.view in un'immagine. Non l'intera vista!
Sameer Hussain

@Vakas quando ho provato a stampare image.it display troppo piccolo. Qual è la soluzione per questo
Krutarth Patel

6
L'immagine dello screenshot non ha una buona qualità, cosa devo fare?
Neela

13

Ad esempio, se ho una visualizzazione delle dimensioni: 50 50 a 100,100. Posso usare quanto segue per fare uno screenshot:

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), false, 0);
    self.view.drawViewHierarchyInRect(CGRectMake(-50,-5-,view.bounds.size.width,view.bounds.size.height), afterScreenUpdates: true)
    var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();

nella riga self.view c'è un errore nel parametro. penso che dovrebbe essere -5 non -5-
Krutarth Patel

@sameer ho una domanda. quando stampo questa immagine è troppo piccola
Krutarth Patel

7

A mio parere, l'approccio con l'inizializzatore non è eccezionale perché crea due immagini.

Preferisco questo:

extension UIView {
    var snapshot: UIImage? {
        UIGraphicsBeginImageContext(self.frame.size)
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }
        layer.render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

Dovresti chiamare la proprietà qualcosa di diverso dall'immagine. Ciò può interferire con le sottoclassi che hanno proprietà chiamate immagine, come UIImageView.
Hobbes the Tige

Ho seguito il suggerimento di @HobbestheTige e rinominato la proprietà
Tino

6

Swift 4.2, iOS 10

extension UIView {

    // If Swift version is lower than 4.2, 
    // You should change the name. (ex. var renderedImage: UIImage?)

    var image: UIImage? {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in layer.render(in: rendererContext.cgContext) }
    }
}

Campione

let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = .blue

let view2 = UIView(frame: CGRect(x: 10, y: 10, width: 20, height: 20))
view2.backgroundColor = .red
view.addSubview(view2)

let imageView = UIImageView(image: view.image)

inserisci qui la descrizione dell'immagine


Volevo solo sottolineare che questo deve essere chiamato in modo diverso se stai usando UIImageViews nel tuo progetto, altrimenti .image diventa di sola lettura. Forse chiamalo "screenCapture" invece di "immagine".
Chris

@ Chris Yeah, hai ragione. È necessario modificare un nome se la versione di Swift è inferiore alla 4.2. Grazie per aver sottolineato l'errore.
Den

6

Questo funziona per me per Xcode 9 / Swift 3.2 / Swift 4 e Xcode 8 / Swift 3

 if #available(iOS 10.0, *) {

     // for Xcode 9/Swift 3.2/Swift 4 -Paul Hudson's code
     let renderer = UIGraphicsImageRenderer(size: view!.bounds.size)
     let capturedImage = renderer.image { 
         (ctx) in
         view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: true)
     }
     return capturedImage

 } else {

     // for Xcode 8/Swift 3
     UIGraphicsBeginImageContextWithOptions((view!.bounds.size), view!.isOpaque, 0.0)
     view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: false)
     let capturedImage = UIGraphicsGetImageFromCurrentImageContext()
     UIGraphicsEndImageContext()
     return capturedImage!
 }

Ecco come usarlo all'interno di una funzione:

fileprivate func captureUIImageFromUIView(_ view:UIView?) -> UIImage {

     guard (view != nil) else{

        // if the view is nil (it's happened to me) return an alternative image
        let errorImage = UIImage(named: "Error Image")
        return errorImage
     }

     // if the view is all good then convert the image inside the view to a uiimage
     if #available(iOS 10.0, *) {

         let renderer = UIGraphicsImageRenderer(size: view!.bounds.size)
         let capturedImage = renderer.image { 
             (ctx) in
             view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: true)
         }
         return capturedImage

     } else {

         UIGraphicsBeginImageContextWithOptions((view!.bounds.size), view!.isOpaque, 0.0)
         view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: false)
         let capturedImage = UIGraphicsGetImageFromCurrentImageContext()
         UIGraphicsEndImageContext()
         return capturedImage!
     }
}

Ecco come fare qualcosa con l'immagine restituita dalla funzione:

@IBOutlet weak fileprivate var myCustomView: UIView!
var myPic: UIImage?

let myImageView = UIImageView()

@IBAction fileprivate func saveImageButtonTapped(_ sender: UIButton) {

   myPic = captureUIImageFromUIView(myCustomView)

   // display the pic inside a UIImageView
   myImageView.image = myPic!
}

Ho ricevuto la risposta Xcode 9 / Swift 3.2 / Swift 4 da Paul Hudson converte uiview in uiimage

Ho ricevuto Xcode 8 / Swift 3 da qualche parte in SO molto tempo fa e ho dimenticato dove :(


Inoltre, dove viene visualizzata e / o salvata l'immagine?
Famic Tech

@FamicTech una volta creata l'immagine spetta ai giovani decidere cosa farne. Nell'esempio dal mio codice ho appena convertito l'UIView in un UIImage chiamato "myPic" ma non ho fatto nulla con 'myPic'. Il prossimo passo possibile è visualizzare 'myPic' all'interno di un UIImageVIew come questo: myImageVIew.image = myPic. Se si utilizza una collectionView e si desidera visualizzare le immagini al suo interno, creare un UIImageVIew in ogni cella e quindi visualizzare l'immagine (myPic) all'interno di UIImageVIew tramite indexPath.item dall'origine dati ex: myImageView.image = dataSource [indexPath .item] .myPic
Lance Samaria

@FamicTech Stai commettendo un piccolo errore. Questo non ha nulla a che fare con una collectionVIew. Hai 2 diversi tipi di classe: UIImage e UIView. Entrambi possono essere utilizzati per visualizzare qualsiasi immagine, ma entrambi lo fanno in modi diversi. Praticamente tutto in iOS è una sottoclasse di una UIView, ma un UIImage può solo visualizzare immagini (2 cose diverse). Ciò che questa funzione fa è prendere l'UIVIew e convertirlo in un UIImage. Un esempio più facile. Se vuoi convertire 4.0 (un Double) in 4 (un Int), lo lanci Int (4.0), il risultato è 4. Ma con questo converti l'immagine all'interno di UIVew in un UIImage. Capire?
Lance Samaria

quello che sto cercando di fare è che l'utente venga al mio controller di visualizzazione raccolta e prema un pulsante che dovrebbe prendere la vista corrente, che sembra essere una vista raccolta 10x10 e creare un'immagine dell'intera griglia 10x10 (si noti che l'intera griglia non è completamente visibile in vista). Il tuo codice qui sopra risolve questo caso d'uso?
Famic Tech

Il pulsante si trova nel controller di navigazione. L'utente farebbe clic su di esso e "dovrebbe" prendere la vista raccolta visualizzata sotto il controller di navigazione e creare un'immagine della vista raccolta (funzionerebbe anche un PDF) con tutte le informazioni nelle celle nella vista raccolta.
Famic Tech

5
var snapshot = overView.snapshotViewAfterScreenUpdates(false)

o nell'obiettivo-c

UIView* snapshot = [overView snapshotViewAfterScreenUpdates:NO];

ImageView è uguale all'immagine? In tal caso come faccio a salvarlo nella mia app?
Sameer Hussain

4

Puoi usarlo facilmente usando l'estensione come questa

// Take a snapshot from a view (just one view)
let viewSnapshot = myView.snapshot

// Take a screenshot (with every views in screen)
let screenSnapshot = UIApplication.shared.snapshot

// Take a snapshot from UIImage initialization
UIImage(view: self.view)

Se vuoi usare questi metodi / variabili di estensione, implementali

  1. Estensione UIImage

    extension UIImage {
        convenience init(view: UIView) {
            if let cgImage = view.snapshot?.cgImage {
                self.init(cgImage: cgImage)
            } else {
                self.init()
            }
        }
    }
  2. Estensione UIView

    extension UIView {
    
        var snapshot: UIImage? {
            UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0.0)
            if UIGraphicsGetCurrentContext() != nil {
                drawHierarchy(in: bounds, afterScreenUpdates: true)
                let screenshot = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return screenshot
            }
            return nil
        }
    }
  3. Estensione dell'applicazione UIA

    extension UIApplication {
    
        var snapshot: UIImage? {
            return keyWindow?.rootViewController?.view.snapshot
        }
    }

ho avuto vista con le sottoview zPositions manipolate, e altre risposte non mi hanno dato le posizioni dei layer corrette, grazie.
Ashkan Ghodrat

3

o iOS 10+ puoi usare il nuovo UIGraphicsImageRenderer + il drawHierarchy consigliato, che in alcune situazioni può essere molto più veloce di layer.renderInContext

extension UIView {
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
        return renderer.image { _ in
            self.drawHierarchy(in: CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height), afterScreenUpdates: false)
        }
    }
}

3

Grazie @Bao Tuan Diep! Voglio aggiungere un supplemento.

Quando usi il codice:

yourView.layer.render(in:UIGraphicsGetCurrentContext()!)

Devi notare che:

 - If you had used `autoLayout` or `Masonry` in `yourView` (that you want to convert) .
 - If you did not add `yourView` to another view which means that `yourView` was not used as a subview but just an object.

Quindi, devi usare :

[yourView setNeedsLayout];
[yourView layoutIfNeeded];

aggiornare yourViewprimayourView.layer.render(in:UIGraphicsGetCurrentContext()!) .

Altrimenti potresti ottenere un oggetto immagine che non contiene elementi


Grazie per questo. Ha aiutato molto !!
Maksim Kniazev,

2

Swift 4.2

import Foundation
import UIKit  

extension UIImage {

    convenience init(view: UIView) {

        UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
        view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: (image?.cgImage)!)

    } 
}

utilizzando:

let img = UIImage.init (view: self.holderView)


1

Implementazione in Swift 3 :

Aggiungi il codice seguente, fuori dall'ambito della classe.

extension UIImage {
    convenience init(_ view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: (image?.cgImage)!)
    }
}

Utilizzo:

let image = UIImage( Your_View_Outlet )

ottenere l'errore "Richiede disegnare una vista (0x1040a6970, UIView) che non è stata renderizzata almeno una volta"
kishu mewara

0

Ho implementato @Naveed J. il metodo di questo modo e ha funzionato alla grande.

Ecco la sua estensione:

extension UIView {

    // Using a function since `var image` might conflict with an existing variable
    // (like on `UIImageView`)
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
}

Ecco come l'ho implementato.

//create an image from yourView to display
//determine the frame of the view/imageimage
let screen = self.superview!.bounds
let width = screen.width / 4 //make image 1/4 width of screen
let height = width
let frame = CGRect(x: 0, y: 0, width: width, height: height)
let x = (screen.size.width - frame.size.width) * 0.5
let y = (screen.size.height - frame.size.height) * 0.5
let mainFrame = CGRect(x: x, y: y, width: frame.size.width, height: frame.size.height)

let yourView = YourView() //instantiate yourView
yourView.frame = mainFrame //give it the frame
yourView.setNeedsDisplay() //tell it to display (I am not 100% sure this is needed)

let characterViewImage = yourView.asImage()

0

Inizializzatore con il nuovo UIGraphicsImageRenderer disponibile da iOS 10:

extension UIImage{
    convenience init(view: UIView) {

    let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
    let canvas = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height)
    let image = renderer.image { _ in
        self.drawHierarchy(in: canvas, afterScreenUpdates: false)
    }
    self.init(cgImage: (image?.cgImage)!)
  }
}

0

lavora bene con me!

Swift4

 extension UIView {

    func toImage() -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
        self.drawHierarchy(in: self.bounds, afterScreenUpdates: false)
        let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return snapshotImageFromMyView!
    }

    }

return snapshotImageFromMyView!Discussione 1: Errore irreversibile: inaspettatamente trovato zero durante lo scartamento di un valore opzionale
Takasur

0

Per la visualizzazione contiene una vista secondaria sfocata (ad esempio, istanza UIVisualEffectView ), solo drawViewHierarchyInRect: afterScreenUpdates .

La risposta di @ViJay Avhad è corretta per questo caso.


0

L'uso di UIGraphicsImageRenderer non funziona quando la vista contiene le sottoview di Scene Kit, Metal o Sprite Kit. In questi casi, usa

let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
let image = renderer.image { ctx in
    view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
}

-1
please try below code.
-(UIImage *)getMainImageFromContext
{
UIGraphicsBeginImageContextWithOptions(viewBG.bounds.size, viewBG.opaque, 0.0);
[viewBG.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
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.