I have a command line program to convert images to JPEG which works but is very slow at converting some HEIC images from an iPhone 16. For example, a 3MB (5712x4284) HEIC image takes 1.4s to process, whereas converting the same image saved as a 100MB TIFF only takes 0.25s. Is there any way to speed this up?
(All the time is spent in drawInRect
, actually compressing it to JPEG etc. only takes about 25ms.)
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#include <sys/xattr.h>
#include <sys/time.h>
#include <stdio.h>
long currentTimeMillis()
{
struct timeval t;
gettimeofday(&t, NULL);
return t.tv_sec*1000L + t.tv_usec/1000;
}
void convertToJPEG(const char* inf, const char* outf)
{
long t0 = currentTimeMillis();
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSString* str = [NSString stringWithUTF8String:inf];
NSImage *image = [[NSImage alloc]initWithContentsOfFile:str];
NSSize size = [image size];
printf("+%ld origsize %g x %g\n", currentTimeMillis()-t0, size.width, size.height);
size.width /= 2;
size.height /= 2;
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:size.width
pixelsHigh:size.height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bytesPerRow:0
bitsPerPixel:0];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:rep]];
printf("+%ld setup\n", currentTimeMillis()-t0);
// Draw scaled image into representation **** THIS STEP IS SLOW ****
[image drawInRect:NSMakeRect(0, 0, size.width, size.height) fromRect:NSZeroRect operation:NSCompositingOperationCopy fraction:1.0];
printf("+%ld drawInRect\n", currentTimeMillis()-t0);
[NSGraphicsContext restoreGraphicsState];
// Compress representation to JPEG
[rep setProperty:NSImageColorSyncProfileData withValue:nil];
NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:0.5] forKey:NSImageCompressionFactor];
NSData* data = [rep representationUsingType:NSBitmapImageFileTypeJPEG properties:imageProps];
printf("+%ld compressed\n", currentTimeMillis()-t0);
int length = [data length];
void* bytes = malloc(length);
[data getBytes:bytes length:length];
FILE* out = fopen(outf, "w");
fwrite(bytes, 1, length, out);
fclose(out);
free(bytes);
[rep release];
[image release];
[pool release];
printf("+%ld finished\n", currentTimeMillis()-t0);
}
int main(int argc, const char** argv)
{
convertToJPEG(argv[1], "out.jpg");
}
Compile with gcc -o tojpeg tojpeg.mm -framework CoreServices -framework AppKit
. (Apologies for the ugly mishmash of technologies, that's partly historical and partly a consequence of stripping it down to a SSCCE.)