Frage

Ich lade Sie ein Bild von einer URL von einem Drittanbieter bereitgestellt. Es gibt keine Dateierweiterung (oder Dateinamen für diese Angelegenheit) auf der URL (wie es ein verdeckter URL ist). Ich kann die Daten aus dieser nehmen (in Form von NSData) und in eine UIImage laden und zeigt es in Ordnung.

Ich möchte diese Daten in eine Datei beharren. Allerdings weiß ich nicht, welches Format die Daten in (PNG, JPG, BMP)? Ich nehme an, es JPG ist (da es ein Bild aus dem Internet) aber ist es eine programmatische Art und Weise sicher herauszufinden? Ich habe sah sich um und Stackoverflow bei der Dokumentation und nicht in der Lage, etwas zu finden.

TIA.


Edit: Habe ich wirklich die Dateierweiterung benötigen? Ich persistierenden es an einen externen Speicher (Amazon S3) aber wenn man bedenkt, dass es wird immer im Zusammenhang mit iOS oder einem Browser verwendet werden (beide scheinen gut in die Daten ohne eine Erweiterung der Interpretation) vielleicht ist dies kein Thema .

War es hilfreich?

Lösung

Wenn Sie NSData für die Bilddatei haben, dann können Sie in dem Inhaltstyp erraten, indem beim ersten Byte suchen:

+ (NSString *)contentTypeForImageData:(NSData *)data {
    uint8_t c;
    [data getBytes:&c length:1];

    switch (c) {
    case 0xFF:
        return @"image/jpeg";
    case 0x89:
        return @"image/png";
    case 0x47:
        return @"image/gif";
    case 0x49:
    case 0x4D:
        return @"image/tiff";
    }
    return nil;
}

Andere Tipps

Die Verbesserung auf wl. Antwort , hier ist eine viel erweitert und präzise Art und Weise das Image des MIME-Typ zur Vorhersage based über die Unterzeichnung. Der Code wurde weitgehend von php inspiriert ext / standard / Bild. c .

- (NSString *)mimeTypeByGuessingFromData:(NSData *)data {

    char bytes[12] = {0};
    [data getBytes:&bytes length:12];

    const char bmp[2] = {'B', 'M'};
    const char gif[3] = {'G', 'I', 'F'};
    const char swf[3] = {'F', 'W', 'S'};
    const char swc[3] = {'C', 'W', 'S'};
    const char jpg[3] = {0xff, 0xd8, 0xff};
    const char psd[4] = {'8', 'B', 'P', 'S'};
    const char iff[4] = {'F', 'O', 'R', 'M'};
    const char webp[4] = {'R', 'I', 'F', 'F'};
    const char ico[4] = {0x00, 0x00, 0x01, 0x00};
    const char tif_ii[4] = {'I','I', 0x2A, 0x00};
    const char tif_mm[4] = {'M','M', 0x00, 0x2A};
    const char png[8] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
    const char jp2[12] = {0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a};


    if (!memcmp(bytes, bmp, 2)) {
        return @"image/x-ms-bmp";
    } else if (!memcmp(bytes, gif, 3)) {
        return @"image/gif";
    } else if (!memcmp(bytes, jpg, 3)) {
        return @"image/jpeg";
    } else if (!memcmp(bytes, psd, 4)) {
        return @"image/psd";
    } else if (!memcmp(bytes, iff, 4)) {
        return @"image/iff";
    } else if (!memcmp(bytes, webp, 4)) {
        return @"image/webp";
    } else if (!memcmp(bytes, ico, 4)) {
        return @"image/vnd.microsoft.icon";
    } else if (!memcmp(bytes, tif_ii, 4) || !memcmp(bytes, tif_mm, 4)) {
        return @"image/tiff";
    } else if (!memcmp(bytes, png, 8)) {
        return @"image/png";
    } else if (!memcmp(bytes, jp2, 12)) {
        return @"image/jp2";
    }

    return @"application/octet-stream"; // default type

}

Das obige Verfahren erkennt die folgenden Bildtypen:

  • image/x-ms-bmp (bmp)
  • image/gif (gif)
  • image/jpeg (jpg, jpeg)
  • image/psd (psd)
  • image/iff (iff)
  • image/webp (webp)
  • image/vnd.microsoft.icon (ico)
  • image/tiff (tif, tiff)
  • image/png (png)
  • image/jp2 (JP2)

Leider gibt es keine einfache Möglichkeit, diese Art von Informationen aus einer UIImage Instanz zu erhalten, weil ihre eingekapselten Bitmap-Daten können nicht zugegriffen werden.

@Tai Le-Lösung für Swift 3 die Zuordnung ganzer Daten in Byte-Array. Wenn ein Bild groß ist, kann es zum Absturz bringen. Diese Lösung nur ordnet einzelnen Byte:

import Foundation

public extension Data {
    var fileExtension: String {
        var values = [UInt8](repeating:0, count:1)
        self.copyBytes(to: &values, count: 1)

        let ext: String
        switch (values[0]) {
        case 0xFF:
            ext = ".jpg"
        case 0x89:
            ext = ".png"
        case 0x47:
            ext = ".gif"
        case 0x49, 0x4D :
            ext = ".tiff"
        default:
            ext = ".png"
        }
        return ext
    }
}

Wenn Sie das Bild von einer URL abrufen, dann vermutlich können Sie die HTTP-Response-Header inspizieren. Hat der Content-Type Header etwas Nützliches enthalten? (Ich könnte mir vorstellen, es wäre da ein Browser wahrscheinlich das Bild korrekt angezeigt wäre in der Lage, und es könnte nur tun, wenn der Inhaltstyp wurden entsprechend eingestellt)

swift3 Version:

let data: Data = UIImagePNGRepresentation(yourImage)!

extension Data {
    var format: String {
        let array = [UInt8](self)
        let ext: String
        switch (array[0]) {
        case 0xFF:
            ext = "jpg"
        case 0x89:
            ext = "png"
        case 0x47:
            ext = "gif"
        case 0x49, 0x4D :
            ext = "tiff"
        default:
            ext = "unknown"
        }
        return ext
    }
}

Wenn es wirklich zu Ihnen wichtig ist, glaube ich, werden Sie die Bytestrom zu untersuchen haben. Ein JPEG beginnt mit der FF D8 Bytes. Ein PNG wird mit 89 50 4E 47 0D 0A 1A 0A starten. Ich weiß nicht, ob BMP einen ähnlichen Header hat, aber ich glaube nicht, dass Sie auch wahrscheinlich sind, im Jahr 2010 in die auf dem Web auszuführen.

Aber ist es wirklich für Sie? Kannst du nicht einfach als ein unbekanntes Bild behandeln und lassen Sie die Arbeit Cocoa Touch tun?

Eine Alternative der akzeptierten Antwort prüft Bild UTI mit image I/O frameWork. Sie können Bildtyp Form UTI erreichen. versuchen Sie dies:

CGImageSourceRef imgSrc = CGImageSourceCreateWithData((CFDataRef)data, NULL);
NSString *uti = (NSString*)CGImageSourceGetType(imgSrc);
NSLog(@"%@",uti);

Zum Beispiel ein GIF-Bild UTI ist „com.compuserve.gif“ und UTI PNG-Bild ist „public.png“ .Aber Sie können UTI nicht von Bild erreichen, die image I/O frameWork erkannt nicht.

Implementieren Sie eine Signaturprüfung für jedes bekannte Bildformat. Hier ist eine kurze Objective-C-Funktion, macht das für PNG Daten:

// Verify that NSData contains PNG data by checking the signature

- (BOOL) isPNGData:(NSData*)data
{
  // Verify that the PNG file signature matches

  static const
  unsigned char   png_sign[8] = {137, 80, 78, 71, 13, 10, 26, 10};

  unsigned char   sig[8] = {0, 0, 0, 0, 0, 0, 0, 0};

  if ([data length] <= 8) {
    return FALSE;
  }

  [data getBytes:&sig length:8];

  BOOL same = (memcmp(sig, png_sign, 8) == 0);

  return same;
}

habe ich eine Bibliothek den Bildtyp von NSData zu überprüfen:

https://github.com/sweetmandm/ImageFormatInspector

Meine verbesserte Lösung basierend auf @ccoroom

//  Data+ImageContentType.swift

import Foundation

extension Data {  
    enum ImageContentType: String {
        case jpg, png, gif, tiff, unknown

        var fileExtension: String {
            return self.rawValue
        }
    }

    var imageContentType: ImageContentType {

        var values = [UInt8](repeating: 0, count: 1)

        self.copyBytes(to: &values, count: 1)

        switch (values[0]) {
        case 0xFF:
            return .jpg
        case 0x89:
            return .png
        case 0x47:
           return .gif
        case 0x49, 0x4D :
           return .tiff
        default:
            return .unknown
        }
    }
}

Einige Anwendungsbeispiele:

//load some image
do {
    let imageData = try Data(contentsOf: URL(string: "https://myServer/images/test.jpg")!)
} catch {
    print("Unable to load image: \(error)")
}

//content type check
guard [Data.ImageContentType.jpg,
       Data.ImageContentType.png].contains(imageData.imageContentType) else {
    print("unsupported image type")
            return
        }

//set file extension
let image = "myImage.\(imageData.imageContentType.fileExtension)" //myImage.jpg
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top