แปลง UIImage เป็น NSData และแปลงกลับเป็น UIImage ใน Swift หรือไม่


143

ฉันพยายามบันทึก a UIImageไปNSDataแล้วอ่านNSDataกลับไปใหม่UIImageใน Swift การแปลงUIImageไปNSDataฉันใช้รหัสต่อไปนี้:

let imageData: NSData = UIImagePNGRepresentation(myImage)

ฉันจะแปลงimageData(เช่นNSData) กลับเป็นใหม่ได้UIImageอย่างไร

คำตอบ:


155

UIImage(data:imageData,scale:1.0) สมมติว่าขนาดภาพเป็น 1

ใน swift 4.2 ให้ใช้โค้ดด้านล่างเพื่อรับ Data ()

image.pngData()

67

ขอบคุณ ช่วยฉันมาก แปลงเป็น Swift 3 และทำงาน

เพื่อบันทึก: let data = UIImagePNGRepresentation(image)

ในการโหลด: let image = UIImage(data: data)


1
ยังไม่let imagePt = UIImage(data: caminhodaImagem)พอเหรอ
superarts.org


17

ขณะนี้อยู่ในSwift 4.2คุณสามารถใช้pngData()วิธีการใหม่UIImageเพื่อรับข้อมูลจากภาพได้

let profileImage = UIImage(named:"profile")!
let imageData = profileImage.pngData()

Swift 4.2 เป็นเบต้าหรือไม่ ฉันไม่เห็นฟังก์ชันนี้ใช้งานได้
Daniel Springer

ดูเหมือนว่าจะถูกเปลี่ยนชื่อ
吖奇说 - 何魏奇 Archy Will เขา

'pngData ()' ถูกเปลี่ยนชื่อเป็น 'UIImagePNGR การนำเสนอ (_ :)'
j2abro

9

รายละเอียด

  • Xcode 10.2.1 (10E1001), Swift 5

โซลูชันที่ 1

guard let image = UIImage(named: "img") else { return }
let jpegData = image.jpegData(compressionQuality: 1.0)
let pngData = image.pngData()

โซลูชัน 2.1

extension UIImage {
    func toData (options: NSDictionary, type: CFString) -> Data? {
        guard let cgImage = cgImage else { return nil }
        return autoreleasepool { () -> Data? in
            let data = NSMutableData()
            guard let imageDestination = CGImageDestinationCreateWithData(data as CFMutableData, type, 1, nil) else { return nil }
            CGImageDestinationAddImage(imageDestination, cgImage, options)
            CGImageDestinationFinalize(imageDestination)
            return data as Data
        }
    }
}

การใช้งานโซลูชัน 2.1

// about properties: https://developer.apple.com/documentation/imageio/1464962-cgimagedestinationaddimage
let options: NSDictionary =     [
    kCGImagePropertyOrientation: 6,
    kCGImagePropertyHasAlpha: true,
    kCGImageDestinationLossyCompressionQuality: 0.5
]

// https://developer.apple.com/documentation/mobilecoreservices/uttype/uti_image_content_types
guard let data = image.toData(options: options, type: kUTTypeJPEG) else { return }
let size = CGFloat(data.count)/1000.0/1024.0
print("\(size) mb")

โซลูชัน 2.2

extension UIImage {

    func toJpegData (compressionQuality: CGFloat, hasAlpha: Bool = true, orientation: Int = 6) -> Data? {
        guard cgImage != nil else { return nil }
        let options: NSDictionary =     [
                                            kCGImagePropertyOrientation: orientation,
                                            kCGImagePropertyHasAlpha: hasAlpha,
                                            kCGImageDestinationLossyCompressionQuality: compressionQuality
                                        ]
        return toData(options: options, type: .jpeg)
    }

    func toData (options: NSDictionary, type: ImageType) -> Data? {
        guard cgImage != nil else { return nil }
        return toData(options: options, type: type.value)
    }
    // about properties: https://developer.apple.com/documentation/imageio/1464962-cgimagedestinationaddimage
    func toData (options: NSDictionary, type: CFString) -> Data? {
        guard let cgImage = cgImage else { return nil }
        return autoreleasepool { () -> Data? in
            let data = NSMutableData()
            guard let imageDestination = CGImageDestinationCreateWithData(data as CFMutableData, type, 1, nil) else { return nil }
            CGImageDestinationAddImage(imageDestination, cgImage, options)
            CGImageDestinationFinalize(imageDestination)
            return data as Data
        }
    }

    // https://developer.apple.com/documentation/mobilecoreservices/uttype/uti_image_content_types
    enum ImageType {
        case image // abstract image data
        case jpeg                       // JPEG image
        case jpeg2000                   // JPEG-2000 image
        case tiff                       // TIFF image
        case pict                       // Quickdraw PICT format
        case gif                        // GIF image
        case png                        // PNG image
        case quickTimeImage             // QuickTime image format (OSType 'qtif')
        case appleICNS                  // Apple icon data
        case bmp                        // Windows bitmap
        case ico                        // Windows icon data
        case rawImage                   // base type for raw image data (.raw)
        case scalableVectorGraphics     // SVG image
        case livePhoto                  // Live Photo

        var value: CFString {
            switch self {
            case .image: return kUTTypeImage
            case .jpeg: return kUTTypeJPEG
            case .jpeg2000: return kUTTypeJPEG2000
            case .tiff: return kUTTypeTIFF
            case .pict: return kUTTypePICT
            case .gif: return kUTTypeGIF
            case .png: return kUTTypePNG
            case .quickTimeImage: return kUTTypeQuickTimeImage
            case .appleICNS: return kUTTypeAppleICNS
            case .bmp: return kUTTypeBMP
            case .ico: return kUTTypeICO
            case .rawImage: return kUTTypeRawImage
            case .scalableVectorGraphics: return kUTTypeScalableVectorGraphics
            case .livePhoto: return kUTTypeLivePhoto
            }
        }
    }
}

การใช้งานโซลูชัน 2.2

let compressionQuality: CGFloat = 0.4
guard let data = image.toJpegData(compressionQuality: compressionQuality) else { return }
printSize(of: data)

let options: NSDictionary =     [
                                    kCGImagePropertyHasAlpha: true,
                                    kCGImageDestinationLossyCompressionQuality: compressionQuality
                                ]
guard let data2 = image.toData(options: options, type: .png) else { return }
printSize(of: data2)

ปัญหาที่เกิดขึ้น

รูปภาพที่แสดงจะใช้ทรัพยากร cpu และหน่วยความจำจำนวนมาก ดังนั้นในกรณีนี้จะเป็นการดีกว่าถ้าทำตามกฎหลายข้อ:

- ห้ามรัน jpegData (compressionQuality :) บนคิวหลัก

- รัน jpegData เพียงครั้งเดียว (compressionQuality :) พร้อมกัน

ไม่ถูกต้อง:

for i in 0...50 {
    DispatchQueue.global(qos: .utility).async {
        let quality = 0.02 * CGFloat(i)
        //let data = image.toJpegData(compressionQuality: quality)
        let data = image.jpegData(compressionQuality: quality)
        let size = CGFloat(data!.count)/1000.0/1024.0
        print("\(i), quality: \(quality), \(size.rounded()) mb")
    }
}

ขวา:

let serialQueue = DispatchQueue(label: "queue", qos: .utility, attributes: [], autoreleaseFrequency: .workItem, target: nil)

for i in 0...50 {
    serialQueue.async {
        let quality = 0.02 * CGFloat(i)
        //let data = image.toJpegData(compressionQuality: quality)
        let data = image.jpegData(compressionQuality: quality)
        let size = CGFloat(data!.count)/1000.0/1024.0
        print("\(i), quality: \(quality), \(size.rounded()) mb")
    }
}

การเชื่อมโยง


Vasily นี้เป็นประโยชน์อย่างมาก ฉันสามารถแปลง UIImages เป็น bmps โดยใช้รหัสของคุณ ฉันต้องลบอัลฟาจาก bmp ด้วย ฉันพยายามตั้งค่าตัวเลือกเพื่อลบอัลฟาและดูเหมือนจะไม่สามารถกำจัดมันได้ ฉันกำลังเรียกสิ่งนี้: let options: NSDictionary = [kCGImagePropertyHasAlpha: false] let convertToBmp = image.toData (ตัวเลือก: ตัวเลือกประเภท: .bmp)
Gallaugher

@Galugher คุณแน่ใจหรือว่ามันไม่ทำงาน? ลองสร้างภาพ png โดยไม่ใช้อัลฟ่าและตรวจสอบ อาจเป็นไปไม่ได้ที่จะใช้คุณสมบัติ kCGImagePropertyHasAlpha กับ bmp
Vasily Bodnarchuk

@ vasily-bodnarchuk ขอบคุณสำหรับผู้นำ (และรหัสก่อนหน้า) ฉันกำจัดอัลฟา - ฉันไม่สามารถทำได้ผ่าน png แต่ฉันใช้ resizedImage.toJpegData กับอัลฟ่าเป็นเท็จแล้วแปลงข้อมูลนี้กลับเป็น UIImage จากนั้นทำดาต้าเป็นประเภท. bmp ตัวเลือกไม่มีผลกระทบ แต่เป็นการลบเลเยอร์อัลฟาใน Photoshop และสร้างไฟล์ขนาดเล็กลง ยังไม่สามารถสร้างรูปแบบ bmp กราฟิกแรสเตอร์ bmp ที่แน่นอนที่ฉันต้องการสำหรับ PyPortal ได้ ด้วยเหตุผลบางอย่างข้อมูล conveted ไม่แสดงเมื่อฉันแปลงผ่านเครื่องมือเช่นการแปลงออนไลน์ ขอบคุณ.
Gallaugher

@ vasily-bodnarchuk, bmp ที่ฉันบันทึกไว้โดยใช้รหัสที่เป็นประโยชน์ของคุณจะเปิดขึ้นใน Photoshop พร้อมตัวเลือก bmp "ลำดับแถวพลิก" หากฉันบันทึก & ยกเลิกการทำเครื่องหมายตัวเลือกนี้ในหน้าจอ "ตัวเลือก BMP" ปรากฏขึ้นหลังจาก "บันทึกเป็น ... " ให้โหลด bmp บน PyPortal ที่อัปเดตแล้ว bmp แสดง ฉันไม่เห็นเอกสารของ Apple ที่ดูเหมือนตัวเลือก "คำสั่งพลิกแถว" ฉันไม่แน่ใจว่าทำไมสิ่งนี้ถึงปรากฏเป็นบันทึกเริ่มต้น & ฉันไม่แน่ใจว่าจะ "เลิกทำ" ใน Swift ได้อย่างไร BTW: ฉันโพสต์คำถาม & ไฟล์ที่เกี่ยวข้องที่: stackoverflow.com/questions/57241391/…ขอบคุณ!
Gallaugher

8

วิธีบันทึกเป็นข้อมูล:

จาก StoryBoard หากคุณต้องการบันทึกข้อมูล "ภาพ" ใน imageView ของ MainStoryBoard รหัสต่อไปนี้จะใช้งานได้

let image = UIImagePNGRepresentation(imageView.image!) as NSData?

ในการโหลด "image" ไปที่ imageView: ดูเครื่องหมายอัศเจรีย์ "!", "?" อย่างใกล้ชิดไม่ว่าจะเป็นเช่นเดียวกับอันนี้

imageView.image = UIImage(data: image as! Data)

ประเภท "NSData" จะถูกแปลงเป็นประเภท "ข้อมูล" โดยอัตโนมัติในระหว่างกระบวนการนี้


6

เพื่อความปลอดภัยในการใช้รหัสให้ใช้if-letblock with Dataเพื่อป้องกันไม่ให้แอปขัดข้อง & เนื่องจากฟังก์ชันUIImagePNGRepresentationจะส่งคืนค่าที่ไม่จำเป็น

if let img = UIImage(named: "TestImage.png") {
    if let data:Data = UIImagePNGRepresentation(img) {
       // Handle operations with data here...         
    }
}

หมายเหตุ: ข้อมูลเป็นคลาส Swift 3+ ใช้ข้อมูลแทน NSData ด้วย Swift 3+

การใช้งานรูปภาพทั่วไป (เช่น png & jpg ทั้งคู่):

if let img = UIImage(named: "TestImage.png") {  //UIImage(named: "TestImage.jpg")
        if let data:Data = UIImagePNGRepresentation(img) {
               handleOperationWithData(data: data)     
        } else if let data:Data = UIImageJPEGRepresentation(img, 1.0) {
               handleOperationWithData(data: data)     
        }
}

*******
func handleOperationWithData(data: Data) {
     // Handle operations with data here...
     if let image = UIImage(data: data) {
        // Use image...
     }
}

โดยใช้ส่วนขยาย:

extension UIImage {

    var pngRepresentationData: Data? {
        return UIImagePNGRepresentation(self)
    }

    var jpegRepresentationData: Data? {
        return UIImageJPEGRepresentation(self, 1.0)
    }
}

*******
if let img = UIImage(named: "TestImage.png") {  //UIImage(named: "TestImage.jpg")
      if let data = img.pngRepresentationData {
              handleOperationWithData(data: data)     
      } else if let data = img.jpegRepresentationData {
              handleOperationWithData(data: data)     
     }
}

*******
func handleOperationWithData(data: Data) {
     // Handle operations with data here...
     if let image = UIImage(data: data) {
        // Use image...
     }
}

4

ภาพไปยังข้อมูล: -

    if let img = UIImage(named: "xxx.png") {
        let pngdata = img.pngData()
    }

   if let img = UIImage(named: "xxx.jpeg") {
        let jpegdata = img.jpegData(compressionQuality: 1)
    }

ข้อมูลไปยังรูปภาพ: -

 let image = UIImage(data: pngData)

1

สวิฟท์ 5

ปล่อยให้รูปภาพที่คุณสร้างเป็น UIImage เป็นรูปภาพ

image.pngData() as NSData? 

โปรดใช้เวลาสักครู่เพื่ออ่านผ่านความช่วยเหลือแก้ไขในศูนย์ช่วยเหลือ การจัดรูปแบบใน Stack Overflow นั้นแตกต่างจากไซต์อื่น ๆ
Dharman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.