سؤال

كيف يمكن حفظ NSImage كملف جديد (png, jpg, ...) في بعض الدليل ؟

هل كانت مفيدة؟

المحلول

افعل شيئًا كهذا:

NSBitmapImageRep *imgRep = [[image representations] objectAtIndex: 0];
NSData *data = [imgRep representationUsingType: NSPNGFileType properties: nil];
[data writeToFile: @"/path/to/file.png" atomically: NO];

نصائح أخرى

يمكنك إضافة فئة إلى nsimage مثل هذا

@interface NSImage(saveAsJpegWithName)
- (void) saveAsJpegWithName:(NSString*) fileName;
@end

@implementation NSImage(saveAsJpegWithName)

- (void) saveAsJpegWithName:(NSString*) fileName
{
    // Cache the reduced image
    NSData *imageData = [self TIFFRepresentation];
    NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
    NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
    imageData = [imageRep representationUsingType:NSJPEGFileType properties:imageProps];
    [imageData writeToFile:fileName atomically:NO];        
}

@end

إن الدعوة إلى "tiffrepresentation" ضرورية وإلا قد لا تحصل على صورة صالحة.

غير متأكد حول البقية, ولكن أنا أفضل الأكل بلدي كامل التفاصيل.ما هو موضح أعلاه سوف تعمل و لا شيء خطأ في ذلك ، ولكن وجدت عدد قليل من الأشياء تركت.هنا سوف أسلط الضوء على ملاحظاتي:

  • الأولى أفضل تمثيل هو المقدمة التي يبدو أن 72 نقطة في البوصة حتى لو كانت صورة القرار هو أكبر من ذلك.إذا كنت تفقد القرار
  • ثانيا ماذا عن متعدد الصفحات الصور مثل Gif المتحركة أو ملفات pdf.حاول GIF المتحركة ، سوف تجد الرسوم المتحركة فقدت
  • وأخيرا أي البيانات الوصفية مثل EXIF, نظام تحديد المواقع, إلخ...سيتم فقدان البيانات.

حتى إذا كنت ترغب في تحويل تلك الصورة, هل تريد حقا أن تخسر على كل هذا ؟ إذا كنت ترغب في تناول وجبة كاملة ، ثم يتيح قراءة على...

في بعض الأحيان وأنا لا يعني في بعض الأحيان لا يوجد شيء أفضل من أوله جيدة المدرسة القديمة التنمية.نعم هذا يعني أننا يجب أن تفعل قليلا من العمل!

دعونا نبدأ:

إنشاء فئة في NSData.هذه هي أساليب الفئة لأنك تريد هذه الأشياء موضوع آمنة وليس هناك شيء أكثر أمانا من وضع الأشياء الخاصة بك على المكدس.هناك نوعان من الأساليب واحد من أجل إخراج غير متعدد الصفحات والصور من إخراج متعدد الصفحات والصور.

قائمة من الصور واحدة: JPG, PNG, BMP, JPEG-2000

قائمة صور متعددة: PDF, GIF, TIFF

أولا إنشاء قابلة للتغيير البيانات مساحة في الذاكرة.

NSMutableData * imageData    = [NSMutableData data];

الثانية على CGImageSourceRef.نعم السبر قبيحة بالفعل أليس كذلك.الأمر ليس بهذا السوء ، دعونا نستمر...كنت تريد حقا مصدر الصورة غير تمثيل أو NSImage قطعة من البيانات.ولكن لدينا مشكلة صغيرة.المصدر قد لا تكون متوافقة ، لذلك تأكد من التحقق من UTI ضد تلك المدرجة من CGImageSourceCopyTypeIdentifiers()

بعض التعليمات البرمجية:

CGImageSourceRef imageSource = nil;
if ( /* CHECK YOUR UTI HERE */ )
    return CGImageSourceCreateWithURL( (CFURLRef)aURL, nil );

NSImage * anImage = [[NSImage alloc] initWithContentsOfURL:aURL];

if ( anImage )
    return CGImageSourceCreateWithData( (CFDataRef)[anImage TIFFRepresentation], nil );

انتظر لحظة, لماذا NSImage هناك ؟ كذلك هناك بعض الأشكال التي لا تحتوي على البيانات الوصفية و CGImageSource لا دعم, ولكن هذه هي صالحة الصور.مثال على ذلك هو النمط القديم PICT الصور.

الآن لدينا CGImageSourceRef, تأكد من انها ليست صفرا ثم دعونا الآن الحصول على CGImageDestinationRef.واو كل هذه الحكم أن تتبع.حتى الآن نحن في 2!

سوف نستخدم هذه الدالة:CGImageDestinationCreateWithData()

  • 1 Param هو imageData (يلقي CFMutableDataRef)
  • 2 Param هو الإخراج الخاص بك في المسالك البولية ، تذكر القائمة أعلاه.(مثلا ، kUTTypePNG)
  • 3 Param هو عدد من الصور إلى حفظ.واحد ملفات الصور هذا 1 وإلا يمكنك ببساطة استخدام ما يلي:

    CGImageSourceGetCount( imageSource );

  • 4 Param هو النيل.

تحقق لمعرفة ما إذا كان لديك هذا CGImageDestinationRef والآن دعونا إضافة الصور من المصدر إلى ذلك سوف تشمل أيضا أي/كافة البيانات الإبقاء على القرار.

متعددة الصور نحن حلقة:

for ( NSUInteger i = 0; i < count; ++i )
                CGImageDestinationAddImageFromSource( imageDest, imageSource, i, nil );

على صورة واحدة انه سطر واحد من التعليمات البرمجية في الفهرس 0:

CGImageDestinationAddImageFromSource( imageDest, imageSource, 0, nil);

حسنا, في الصيغة النهائية التي يكتب على القرص أو حاوية البيانات:

CGImageDestinationFinalize( imageDest );

بحيث قابلة للتغيير البيانات من بداية كل صورة البيانات والبيانات الوصفية في ذلك الآن.

هل انتهينا ؟ تقريبا حتى مع جمع القمامة لديك لتنظيف!تذكر اثنين الحكم واحد على مصدر واحد للحصول على وجهة حتى لا CFRelease()

الآن نحن انتهينا و ما كنت في نهاية المطاف مع هو تحويل صورة الاحتفاظ كافة البيانات الوصفية القرار ، الخ...

بلدي NSData الفئة أساليب تبدو مثل هذا:

+ (NSData *) JPGDataFromURL:(NSURL *)aURL;
+ (NSData *) PNGDataFromURL:(NSURL *)aURL;
+ (NSData *) BMPDataFromURL:(NSURL *)aURL;
+ (NSData *) JPG2DataFromURL:(NSURL *)aURL;

+ (NSData *) PDFDataFromURL:(NSURL *)aURL;
+ (NSData *) GIFDataFromURL:(NSURL *)aURL;
+ (NSData *) TIFFDataFromURL:(NSURL *)aURL;

ماذا عن تغيير حجم أو ICO / ICNS ؟ هذا هو يوم آخر ، لكن في ملخص عليك أولا معالجة حجم...

  1. إنشاء السياق مع الحجم الجديد:CGBitmapContextCreate()
  2. الحصول على صورة الحكم من مؤشر:CGImageSourceCreateImageAtIndex()
  3. الحصول على نسخة من البيانات الوصفية:CGImageSourceCopyPropertiesAtIndex()
  4. رسم الصورة في السياق:CGContextDrawImage()
  5. الحصول على تغيير حجم الصورة من السياق:CGBitmapContextCreateImage()
  6. الآن إضافة الصورة الوصفية إلى دست الحكم:CGImageDestinationAddImage()

شطف وتكرار متعددة-الصور المضمنة في المصدر.

الفرق الوحيد بين ICO و ICNS هو صورة واحدة في حين أن الآخر هو عدة صور في ملف واحد.الرهان يمكنك تخمين ما هو؟!;-) هذه الأشكال عليك أن حجم أسفل إلى حجم معين وإلا خطأ سوف تترتب على ذلك.العملية وإن كان هو نفسه تماما حيث يمكنك استخدام السليم UTI ، ولكن حجم هو قليلا أكثر صرامة.

طيب ويساعد هذا الأمل الآخرين هناك و أنت الكامل كما أنا الآن!

انتبه, نسيت أن أذكر.عندما تحصل على NSData كائن لا كما تريد مع ذلك مثل writeToFile, writeToURL ، أو هيك خلق آخر NSImage إذا كنت تريد.

سعيد الترميز!

حفظ كما PNG باستخدام Swift3

import AppKit

extension NSImage {
    @discardableResult
    func saveAsPNG(url: URL) -> Bool {
        guard let tiffData = self.tiffRepresentation else {
            print("failed to get tiffRepresentation. url: \(url)")
            return false
        }
        let imageRep = NSBitmapImageRep(data: tiffData)
        guard let imageData = imageRep?.representation(using: .PNG, properties: [:]) else {
            print("failed to get PNG representation. url: \(url)")
            return false
        }
        do {
            try imageData.write(to: url)
            return true
        } catch {
            print("failed to write to disk. url: \(url)")
            return false
        }
    }
}

الحلول 4.2 الحل

public extension NSImage {
    public func writePNG(toURL url: URL) {

        guard let data = tiffRepresentation,
              let rep = NSBitmapImageRep(data: data),
              let imgData = rep.representation(using: .png, properties: [.compressionFactor : NSNumber(floatLiteral: 1.0)]) else {

            Swift.print("\(self) Error Function '\(#function)' Line: \(#line) No tiff rep found for image writing to \(url)")
            return
        }

        do {
            try imgData.write(to: url)
        }catch let error {
            Swift.print("\(self) Error Function '\(#function)' Line: \(#line) \(error.localizedDescription)")
        }
    }
}

النمط السريع:

if let imgRep = image?.representations[0] as? NSBitmapImageRep
{
      if let data = imgRep.representationUsingType(NSBitmapImageFileType.NSPNGFileType, properties: [:])
      {
           data.writeToFile("/path/to/file.png", atomically: false)
      }
}

فقط واحد مضمون للعمل النهج باستخدام Swift:

لدي "صورة جيدًا" أين يمكن للمستخدم إسقاط أي صورة. وهذا "الصورة جيدًا" يحتوي على خاصية صورة (من نوع nsimage) التي يتم الوصول إليها عبر منفذ:

@IBOutlet weak var imageWell: NSImageView!

والرمز الذي يحفظ هذه الصورة (يمكنك وضعها داخل إجراء الزر) هو:

if imageWell.image != nil {
   let bMImg = NSBitmapImageRep(data: (imageWell?.image?.TIFFRepresentation)!)
   let dataToSave = bMImg?.representationUsingType(NSBitmapImageFileType.NSJPEGFileType, properties: [NSImageCompressionFactor : 1])
   dataToSave?.writeToFile("/users/user/desktop/image.jpg", atomically: true)
}

في السطر الأول من الرمز المحدد ، نتحقق مما إذا كانت صورتنا جيدة.

في السطر الثاني نقوم بعمل تمثيل نقطات لتلك الصورة.

في السطر الثالث ، نقوم بتحويل تمثيل BitmapRepresent إلى نوع JPG مع عامل ضغط تم تعيينه على "1" (بدون ضغط).

في السطر الرابع نقوم بحفظ بيانات JPG مع مسار معين. "ذري: صحيح" يعني أن الملف يتم حفظه كقطعة واحدة ويؤكد لنا أن العملية ستكون ناجحة.

NB: يمكنك استخدام nsbitmapimageFileType آخر في السطر الثالث ، لحفظ صورتك لتنسيق آخر. لديها الكثير:

NSBitmapImageFileType.NSBMPFileType
NSBitmapImageFileType.NSGIFFileType
NSBitmapImageFileType.NSPNGFileType

إلخ.

للمساعدة في الكود عبر المنصات ، قمت بتطبيق إصدار منUIImagePNGRepresentation() الذي يعمل على Mac (ويستخدم NSImage).

#if os(macOS)

public func UIImagePNGRepresentation(_ image: NSImage) -> Data? {
    guard let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil)
        else { return nil }
    let imageRep = NSBitmapImageRep(cgImage: cgImage)
    imageRep.size = image.size // display size in points
    return imageRep.representation(using: .png, properties: [:])
}

#endif

الاستخدام:

if let data = UIImagePNGRepresentation(myImage) {
    do { try data.write(to: url, options: [.atomic]) }
    catch let error { print("Error writing image (\(error))") }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top