Adds support for image previews
Just need to append ?preview=1 to attachment fetch operation.
This commit is contained in:
@@ -8,8 +8,11 @@
|
||||
|
||||
#import "MBIMFetchAttachmentOperation.h"
|
||||
#import "MBIMDataResponse.h"
|
||||
#import "MBIMImageUtils.h"
|
||||
|
||||
#import "IMCore_ClassDump.h"
|
||||
#import "IMSharedUtilities_ClassDump.h"
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
@implementation MBIMFetchAttachmentOperation
|
||||
|
||||
@@ -24,8 +27,8 @@
|
||||
{
|
||||
NSObject<HTTPResponse> *response = nil;
|
||||
do {
|
||||
BOOL preview = [[self valueForQueryItemWithName:@"preview"] boolValue];
|
||||
NSString *guid = [self valueForQueryItemWithName:@"guid"];
|
||||
|
||||
if (!guid) {
|
||||
MBIMLogInfo(@"No query item provided");
|
||||
response = [[HTTPErrorResponse alloc] initWithErrorCode:500];
|
||||
@@ -45,22 +48,65 @@
|
||||
break;
|
||||
}
|
||||
|
||||
NSString *localPath = [transfer localPath];
|
||||
NSData *responseData = [NSData dataWithContentsOfFile:localPath];
|
||||
NSData *responseData = nil;
|
||||
NSURL *localURL = [transfer localURL];
|
||||
NSString *extension = [[localURL pathExtension] lowercaseString];
|
||||
if (preview) {
|
||||
NSURL *previewURL = IMAttachmentPreviewFileURL(localURL, extension, YES);
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:[previewURL path]]) {
|
||||
MBIMLogInfo(@"Generating preview image for guid: %@ at %@", guid, [previewURL path]);
|
||||
|
||||
// Fetch preview constraints from transfer
|
||||
NSDictionary *previewConstraintsDict = [[transfer attributionInfo] objectForKey:@"pgenszc"];
|
||||
if (!previewConstraintsDict) {
|
||||
MBIMLogInfo(@"No preview constraints for attachment guid: %@", guid);
|
||||
response = [[HTTPErrorResponse alloc] initWithErrorCode:500];
|
||||
break;
|
||||
}
|
||||
|
||||
IMPreviewConstraints constraints = IMPreviewConstraintsFromDictionary(previewConstraintsDict);
|
||||
|
||||
// Generate preview using preview generator manager
|
||||
NSError *error = nil;
|
||||
IMPreviewGeneratorManager *generator = [IMPreviewGeneratorManager sharedInstance];
|
||||
CGImageRef previewImage = [generator newPreviewFromSourceURL:localURL withPreviewConstraints:constraints error:&error];
|
||||
if (error) {
|
||||
MBIMLogInfo(@"Unable to generate preview for attachment guid: %@", guid);
|
||||
response = [[HTTPErrorResponse alloc] initWithErrorCode:500];
|
||||
break;
|
||||
}
|
||||
|
||||
responseData = MBIMCGImageJPEGRepresentation(previewImage);
|
||||
|
||||
// Persist JPEG preview to disk
|
||||
[responseData writeToURL:previewURL atomically:YES];
|
||||
} else {
|
||||
// File exists
|
||||
MBIMLogInfo(@"Using cached preview image for guid: %@ at %@", guid, [previewURL path]);
|
||||
responseData = [NSData dataWithContentsOfURL:previewURL];
|
||||
}
|
||||
} else {
|
||||
responseData = [NSData dataWithContentsOfURL:localURL];
|
||||
}
|
||||
|
||||
if (!responseData) {
|
||||
MBIMLogInfo(@"Wasn't able to load data from local path: %@", localPath);
|
||||
MBIMLogInfo(@"Wasn't able to load data for guid: %@", guid);
|
||||
response = [[HTTPErrorResponse alloc] initWithErrorCode:404];
|
||||
break;
|
||||
}
|
||||
|
||||
NSString *mimeType = [transfer mimeType];
|
||||
if ([mimeType isEqualToString:@"image/heic"]) {
|
||||
// TODO: We should convert this to JPEG here. I don't want clients to have to deal with HEIC.
|
||||
MBIMLogInfo(@"WARNING: Returning HEIC data for attachment %@", guid);
|
||||
}
|
||||
|
||||
// It's unusual, but if this is nil, try to guess the MIME type based on the filename
|
||||
if (!mimeType) {
|
||||
NSString *extension = [[localPath pathExtension] lowercaseString];
|
||||
|
||||
// XXX: REALLY hacky
|
||||
mimeType = [NSString stringWithFormat:@"image/%@", extension];
|
||||
}
|
||||
|
||||
response = [[MBIMDataResponse alloc] initWithData:responseData contentType:mimeType];
|
||||
} while (0);
|
||||
|
||||
|
||||
12
kordophone/Bridge/Operations/Utilities/MBIMImageUtils.h
Normal file
12
kordophone/Bridge/Operations/Utilities/MBIMImageUtils.h
Normal file
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// MBIMImageUtils.h
|
||||
// kordophoned
|
||||
//
|
||||
// Created by James Magahern on 12/20/22.
|
||||
// Copyright © 2022 James Magahern. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
extern NSData* MBIMCGImageJPEGRepresentation(CGImageRef imageRef);
|
||||
37
kordophone/Bridge/Operations/Utilities/MBIMImageUtils.m
Normal file
37
kordophone/Bridge/Operations/Utilities/MBIMImageUtils.m
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// MBIMImageUtils.m
|
||||
// kordophoned
|
||||
//
|
||||
// Created by James Magahern on 12/20/22.
|
||||
// Copyright © 2022 James Magahern. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MBIMImageUtils.h"
|
||||
#import <ImageIO/ImageIO.h>
|
||||
|
||||
NSData* MBIMCGImageJPEGRepresentation(CGImageRef imageRef)
|
||||
{
|
||||
if (imageRef == NULL) return nil;
|
||||
|
||||
NSNumber *const DPI = @72.0;
|
||||
NSNumber *const compressionQuality = @0.9;
|
||||
NSDictionary *properties = @{
|
||||
(__bridge NSString *)kCGImagePropertyDPIWidth : DPI,
|
||||
(__bridge NSString *)kCGImagePropertyDPIHeight : DPI,
|
||||
(__bridge NSString *)kCGImageDestinationLossyCompressionQuality : compressionQuality,
|
||||
};
|
||||
|
||||
bool success = false;
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
if (data) {
|
||||
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((CFMutableDataRef)data, CFSTR("public.jpeg"), 1/*count*/, NULL/*options*/);
|
||||
if (imageDestination != NULL) {
|
||||
CGImageDestinationAddImage(imageDestination, imageRef, (__bridge CFDictionaryRef)properties);
|
||||
success = CGImageDestinationFinalize(imageDestination);
|
||||
CFRelease(imageDestination);
|
||||
}
|
||||
}
|
||||
|
||||
return success ? data : nil;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user