NSData 또는 UIImage에서 이미지 유형 찾기
타사에서 제공 한 URL에서 이미지를로드하고 있습니다. URL에는 파일 확장자 (또는 파일 이름)가 없습니다 (가려진 URL이므로). 이 데이터 (NSData 형식)를 가져 와서 UIImage에로드하고 잘 표시 할 수 있습니다.
이 데이터를 파일에 저장하고 싶습니다. 그런데 데이터가 어떤 형식 (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, jpeg)image/psd(psd)image/iff(iff)image/webp(webp)image/vnd.microsoft.icon(ico)image/tiff(티프, tiff)image/png(png)image/jp2(jp2)
불행히도 UIImage캡슐화 된 비트 맵 데이터에 액세스 할 수 없기 때문에 인스턴스 에서 이러한 종류의 정보를 얻는 간단한 방법이 없습니다 .
@Tai Le의 Swift 3 솔루션은 전체 데이터를 바이트 배열에 할당하는 것입니다. 이미지가 크면 충돌이 발생할 수 있습니다. 이 솔루션은 단일 바이트 만 할당합니다.
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
}
}
If it really matters to you, I believe you'll have to examine the bytestream. A JPEG will start with the bytes FF D8. A PNG will start with 89 50 4E 47 0D 0A 1A 0A. I don't know if BMP has a similar header, but I don't think you're too likely to run into those on the web in 2010.
But does it really matter to you? Can't you just treat it as an unknown image and let Cocoa Touch do the work?
An alternative of accepted answer is checking image's UTI with image I/O frameWork. You can achieve image type form UTI. try this:
CGImageSourceRef imgSrc = CGImageSourceCreateWithData((CFDataRef)data, NULL);
NSString *uti = (NSString*)CGImageSourceGetType(imgSrc);
NSLog(@"%@",uti);
For example, a GIF image's UTI is "com.compuserve.gif" and PNG image's UTI is "public.png".BUT you can't achieve UTI from image which image I/O frameWork doesn't recognized.
Implement a signature check for each known image format. Here is a quick Objective-C function that does that for PNG data:
// 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;
}
I made a library to check the image type of NSData:
https://github.com/sweetmandm/ImageFormatInspector
My improved solution based on @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
}
}
}
Some usage examples:
//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
참고URL : https://stackoverflow.com/questions/4147311/finding-image-type-from-nsdata-or-uiimage
'program story' 카테고리의 다른 글
| 프로덕션에 업로드하려고 할 때 Android 서명 APK가 서명되지 않은 APK로 표시됨 (0) | 2020.11.16 |
|---|---|
| gcc로 C ++ 프로그램 컴파일 (0) | 2020.11.16 |
| Google지도 API V3 메서드 fitBounds () (0) | 2020.11.16 |
| C #의 Zip 폴더 (0) | 2020.11.16 |
| 다음 월요일, 화요일 등의 날짜 가져 오기 (0) | 2020.11.16 |