Skip to content

Commit 1dbe1be

Browse files
committed
modernize NSImage usage
- Fixes up NSImage to use a technique that doesn't depend on the DPI of the current screen and just uses pixels - Fixes a crash when releasing the image; the crash was caused by a `memset` call getting a different size for the filename buffer. I solved this by passing the size down, which is safer than just assuming anyway. I added an ASAN cmake option to make it easier to turn up the debugging and understand where the memory corruption had come from. refs: #14
1 parent 5501843 commit 1dbe1be

File tree

4 files changed

+64
-31
lines changed

4 files changed

+64
-31
lines changed

CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ if(NOT CMAKE_BUILD_TYPE)
55
set(CMAKE_BUILD_TYPE Release)
66
endif()
77

8+
option(ASAN "whether to enable ASAN" OFF)
9+
810
find_program(GIT git)
911
if(GIT)
1012
execute_process(
@@ -92,3 +94,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
9294
"-framework IOKit"
9395
)
9496
endif()
97+
98+
if (ASAN)
99+
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
100+
set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
101+
endif()

src/AtomicParsley.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ void APar_SupplySelectiveTypeCreatorCodes(const char *inputPath,
430430

431431
bool ResizeGivenImage(const char *filePath,
432432
PicPrefs myPicPrefs,
433-
char *resized_path);
433+
char *resized_path,
434+
size_t resized_path_len);
434435

435436
char *GenreIntToString(int genre);
436437
uint8_t StringGenreToInt(const char *genre_string);

src/nsimage.mm

+49-28
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@ static void DetermineType(const char *picfilePath, bool &isJPEG, bool &isPNG) {
4242
}
4343
}
4444

45-
static char *
46-
DeriveNewPath(const char *filePath, PicPrefs myPicPrefs, char *newpath) {
45+
static char *DeriveNewPath(const char *filePath,
46+
PicPrefs myPicPrefs,
47+
char *newpath,
48+
size_t newpath_len) {
4749
const char *suffix = strrchr(filePath, '.');
4850

4951
size_t filepath_len = strlen(filePath);
50-
memset(newpath, 0, MAXPATHLEN + 1);
52+
memset(newpath, 0, newpath_len);
5153
size_t base_len = filepath_len - strlen(suffix);
5254
memcpy(newpath, filePath, base_len);
5355
memcpy(newpath + base_len, "-resized-", 9);
@@ -74,11 +76,44 @@ static void DetermineType(const char *picfilePath, bool &isJPEG, bool &isPNG) {
7476
return newpath;
7577
}
7678

79+
static NSImage *DoResize(NSImage *sourceImage, NSSize newSize) {
80+
if (!sourceImage.isValid) {
81+
return nil;
82+
}
83+
84+
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc]
85+
initWithBitmapDataPlanes:NULL
86+
pixelsWide:newSize.width
87+
pixelsHigh:newSize.height
88+
bitsPerSample:8
89+
samplesPerPixel:4
90+
hasAlpha:YES
91+
isPlanar:NO
92+
colorSpaceName:NSCalibratedRGBColorSpace
93+
bytesPerRow:0
94+
bitsPerPixel:0];
95+
rep.size = newSize;
96+
97+
[NSGraphicsContext saveGraphicsState];
98+
[NSGraphicsContext
99+
setCurrentContext:[NSGraphicsContext
100+
graphicsContextWithBitmapImageRep:rep]];
101+
[sourceImage drawInRect:NSMakeRect(0, 0, newSize.width, newSize.height)
102+
fromRect:NSZeroRect
103+
operation:NSCompositingOperationCopy
104+
fraction:1.0];
105+
[NSGraphicsContext restoreGraphicsState];
106+
107+
NSImage *newImage = [[NSImage alloc] initWithSize:newSize];
108+
[newImage addRepresentation:rep];
109+
return newImage;
110+
}
111+
77112
bool ResizeGivenImage(const char *filePath,
78113
PicPrefs myPicPrefs,
79-
char *resized_path) {
114+
char *resized_path,
115+
size_t resized_path_len) {
80116
bool resize = false;
81-
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
82117

83118
NSImage *source = [[NSImage alloc]
84119
initWithContentsOfFile:[NSString stringWithUTF8String:filePath]];
@@ -179,37 +214,23 @@ bool ResizeGivenImage(const char *filePath,
179214
NSSize size = NSMakeSize(hmax, vmax);
180215

181216
if (resize) {
182-
[NSApplication sharedApplication];
183-
[[NSGraphicsContext currentContext]
184-
setImageInterpolation:NSImageInterpolationHigh];
185-
186-
[source setSize:size];
217+
NSImage *image = DoResize(source, size);
187218

188-
NSImage *image = [[NSImage alloc] initWithSize:size];
189-
[image lockFocus];
219+
NSData *imageData = [image TIFFRepresentation];
220+
NSBitmapImageRep *bitmap = [NSBitmapImageRep imageRepWithData:imageData];
190221

191-
NSEraseRect(destinationRect);
192-
[source drawInRect:destinationRect
193-
fromRect:destinationRect
194-
operation:NSCompositingOperationCopy
195-
fraction:1.0];
196-
197-
NSBitmapImageRep *bitmap =
198-
[[NSBitmapImageRep alloc] initWithFocusedViewRect:destinationRect];
199222
NSBitmapImageFileType filetype;
200223
NSDictionary *props;
201224

202225
if ((isPNG && !myPicPrefs.allJPEG) || myPicPrefs.allPNG) {
203226
filetype = NSBitmapImageFileTypePNG;
204227
props = nil;
205-
206228
} else {
207229
filetype = NSBitmapImageFileTypeJPEG;
208230
props = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:0.7]
209231
forKey:NSImageCompressionFactor];
210232
}
211233
NSData *data = [bitmap representationUsingType:filetype properties:props];
212-
213234
unsigned dataLength = [data length]; // holds the file length
214235

215236
int iter = 0;
@@ -227,21 +248,21 @@ bool ResizeGivenImage(const char *filePath,
227248
}
228249
}
229250

230-
[bitmap release];
231-
NSString *outFile = [NSString
232-
stringWithUTF8String:DeriveNewPath(filePath, myPicPrefs, resized_path)];
233-
// NSLog(outFile);
251+
NSString *outFile =
252+
[NSString stringWithUTF8String:DeriveNewPath(filePath,
253+
myPicPrefs,
254+
resized_path,
255+
resized_path_len)];
234256
[[NSFileManager defaultManager] createFileAtPath:outFile
235257
contents:data
236258
attributes:nil];
237259

238-
[image unlockFocus];
239260
[image release];
261+
[bitmap release];
240262
memcpy(resized_path,
241263
[outFile cStringUsingEncoding:NSUTF8StringEncoding],
242264
[outFile lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
243265
}
244266
[source release];
245-
[pool release];
246267
return resize;
247268
}

src/parsley.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -2938,9 +2938,13 @@ void APar_MetaData_atomArtwork_Set(const char *artworkPath,
29382938
// any way
29392939
myPicturePrefs = APar_ExtractPicPrefs(env_PicOptions);
29402940

2941-
char *resized_filepath = (char *)calloc(1, sizeof(char) * MAXPATHLEN + 1);
2941+
size_t resized_filepath_len = MAXPATHLEN + 1;
2942+
char *resized_filepath = (char *)calloc(1, resized_filepath_len);
29422943

2943-
if (ResizeGivenImage(artworkPath, myPicturePrefs, resized_filepath)) {
2944+
if (ResizeGivenImage(artworkPath,
2945+
myPicturePrefs,
2946+
resized_filepath,
2947+
resized_filepath_len)) {
29442948
APar_MetaData_atomArtwork_Init(desiredAtom->AtomicNumber,
29452949
resized_filepath);
29462950

0 commit comments

Comments
 (0)