NSData 또는 UIImage에서 이미지 유형 찾기
제3자가 제공한 URL에서 이미지를 로드합니다.URL에 파일 확장자(또는 해당 파일 이름)가 없습니다(숨겨진 URL이므로).NSData 형식의 데이터를 가져와 UI 이미지에 로드하여 표시할 수 있습니다.
이 데이터를 파일로 유지하고 싶습니다.그런데 데이터가 어떤 형식(PNG, JPG, BMP)으로 되어 있는지 모르겠습니다.(웹에서 본 이미지이기 때문에) JPG라고 생각합니다만, 확실히 알 수 있는 프로그래밍 방식이 있나요?StackOverflow와 설명서를 살펴보았지만 아무것도 찾을 수 없었습니다.
TIA.
편집: 파일 확장자가 꼭 필요합니까?외장 스토리지(Amazon S3)에 지속적으로 적용하고 있지만 iOS나 브라우저(확장 없이 데이터를 해석하는 데 문제가 없어 보이는 두 브라우저)에서 항상 사용된다는 점을 고려하면 이는 문제가 아닐 수 있습니다.
이미지 파일에 대한 NSData가 있으면 첫 번째 바이트를 보고 내용 유형을 추측할 수 있습니다.
+ (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;
}
wl.의 답변을 개선하여 서명을 기반으로 이미지의 MIME 유형을 훨씬 더 확장되고 정확하게 예측할 수 있는 방법이 있습니다.코드는 주로 php의 ext/standard/image.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
}
위의 방법은 다음과 같은 이미지 유형을 인식합니다.
image/x-ms-bmp(BMP)image/gif(gif)image/jpeg(jpg, jpg)image/psd(psd)image/iff(iff)image/webp(webp)image/vnd.microsoft.icon(ico)image/tiff(tif, tiff)image/png(png)image/jp2(아래쪽2)
불행하게도, 이런 종류의 정보를 얻는 간단한 방법은 없습니다.UIImage인스턴스. 캡슐화된 비트맵 데이터에 액세스할 수 없기 때문입니다.
@Swift 3용 Tail Le 솔루션은 전체 데이터를 바이트 배열에 할당하는 것입니다.이미지가 크면 충돌이 발생할 수 있습니다.이 솔루션은 단일 바이트만 할당합니다.
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
}
}
URL에서 이미지를 검색하는 경우 HTTP 응답 헤더를 검사할 수 있습니다.하십니까?Content-Type헤더에 유용한 내용이 포함되어 있습니까? (브라우저는 아마도 이미지를 올바르게 표시할 수 있을 것이고 콘텐츠 유형이 적절하게 설정된 경우에만 그렇게 할 수 있기 때문이라고 생각합니다.)
Swift3 버전:
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
}
}
승인된 답변의 대안은 이미지의 UTI를 확인하는 것입니다.image I/O frameWorkUTI의 이미지 유형을 얻을 수 있습니다. 다음을 시도하십시오.
CGImageSourceRef imgSrc = CGImageSourceCreateWithData((CFDataRef)data, NULL);
NSString *uti = (NSString*)CGImageSourceGetType(imgSrc);
NSLog(@"%@",uti);
GIF 파일 "com.compuserve.gif"는 PNG 파일 "public.png"입니다.하지만 당신은 UTI를 달성할 수 없습니다.image I/O frameWork인식되지 않습니다.
에서 이미지 UIImage기본 Quartz 영상 데이터에서 유형 식별자(UTI)를 가져올 수 있습니다.
extension UIImage {
var typeIdentifier: String? {
cgImage?.utType as String?
}
}
URL에서 이미지 유형 식별자를 가져오려면 URL이 로컬 리소스를 가리키는지 여부에 따라 달라집니다.
extension URL {
// for local resources (fileURLs)
var typeIdentifier: String? { (try? resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier }
// for non local resources (web) you can get it asyncronously
func asyncTypeIdentifier(completion: @escaping ((String?, Error?) -> Void)) {
var request = URLRequest(url: self)
request.httpMethod = "HEAD"
URLSession.shared.dataTask(with: request) { _ , response , error in
completion((response as? HTTPURLResponse)?.mimeType, error)
}.resume()
}
}
let imageURL = URL(string: "https://i.stack.imgur.com/varL9.jpg")!
imageURL.asyncTypeIdentifier { typeIdentifier, error in
guard let typeIdentifier = typeIdentifier, error == nil else { return }
print("typeIdentifier:", typeIdentifier)
}
@ccoom 기반의 향상된 솔루션
// 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
}
}
}
몇 가지 사용 예:
//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
정말로 당신에게 문제가 된다면 바이스트림을 검토해보셔야 할 것 같습니다.JPEG는 FFD8 바이트로 시작합니다. PNG는 89504E 470D 0A 1A 0A로 시작합니다.BMP에 비슷한 헤더가 있는지는 모르겠지만, 2010년에 웹에서 그런 헤더와 마주칠 가능성은 그리 높지 않다고 생각합니다.
하지만 그게 당신에게 정말 중요한가요?그냥 알 수 없는 이미지로 취급하고 코코아 터치가 그 일을 하게 할 수는 없을까요?
알려진 각 이미지 형식에 대한 서명 검사를 구현합니다.다음은 PNG 데이터에 대해 이를 수행하는 빠른 목표 C 함수입니다.
// 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;
}
NSData의 이미지 유형을 확인하기 위해 라이브러리를 만들었습니다.
https://github.com/sweetmandm/ImageFormatInspector
언급URL : https://stackoverflow.com/questions/4147311/finding-image-type-from-nsdata-or-uiimage
'programing' 카테고리의 다른 글
| 다중 글꼴 가중치, 하나의 @ 글꼴-면 쿼리 (0) | 2023.08.01 |
|---|---|
| mysql 치명적 오류: 버퍼 풀에 메모리를 할당할 수 없습니다. (0) | 2023.08.01 |
| 그룹화, 그룹화, 그룹화, 평균화 (0) | 2023.07.27 |
| JSONP를 사용하여 html 페이지 로드 (0) | 2023.07.27 |
| dbms_scheduler.run_job('jobName)이(가) 실행되지 않음 (0) | 2023.07.27 |