xcode – 如何从NSImage保存PNG文件(视网膜问题)正确的方法?
发布时间:2020-12-14 19:34:59 所属栏目:百科 来源:网络整理
导读:我试图将数组中的每个图像保存为.PNG文件(也是正确的大小,因为视网膜mac dpi问题没有按比例放大)并且似乎无法找到解决方案.在 How to save PNG file from NSImage (retina issues)没有任何解决方案似乎对我有用.我已经尝试了每一个,他们每个人仍然会在视网膜
我试图将数组中的每个图像保存为.PNG文件(也是正确的大小,因为视网膜mac dpi问题没有按比例放大)并且似乎无法找到解决方案.在
How to save PNG file from NSImage (retina issues)没有任何解决方案似乎对我有用.我已经尝试了每一个,他们每个人仍然会在视网膜.etc中将72×72文件保存为144×144.
更具体地说,我正在寻找一个NSImage类别(是的,我在Mac环境中工作) 我试图让用户选择一个目录来保存它们并执行从数组中保存图像,如下所示: - (IBAction)saveImages:(id)sender { // Prepare Images that are checked and put them in an array [self prepareImages]; if ([preparedImages count] == 0) { NSLog(@"We have no preparedImages to save!"); NSAlert *alert = [[NSAlert alloc] init]; [alert setAlertStyle:NSInformationalAlertStyle]; [alert setMessageText:NSLocalizedString(@"Error",@"Save Images Error Text")]; [alert setInformativeText:NSLocalizedString(@"You have not selected any images to create.",@"Save Images Error Informative Text")]; [alert beginSheetModalForWindow:self.window modalDelegate:self didEndSelector:@selector(testDatabaseConnectionDidEnd:returnCode: contextInfo:) contextInfo:nil]; return; } else { NSLog(@"We have prepared %lu images.",(unsigned long)[preparedImages count]); } // Save Dialog // Create a File Open Dialog class. //NSOpenPanel* openDlg = [NSOpenPanel openPanel]; NSSavePanel *panel = [NSSavePanel savePanel]; // Set array of file types NSArray *fileTypesArray; fileTypesArray = [NSArray arrayWithObjects:@"jpg",@"gif",@"png",nil]; // Enable options in the dialog. //[openDlg setCanChooseFiles:YES]; //[openDlg setAllowedFileTypes:fileTypesArray]; //[openDlg setAllowsMultipleSelection:TRUE]; [panel setNameFieldStringValue:@"Images.png"]; [panel setDirectoryURL:directoryPath]; // Display the dialog box. If the OK pressed,// process the files. [panel beginWithCompletionHandler:^(NSInteger result) { if (result == NSFileHandlingPanelOKButton) { NSLog(@"OK Button!"); // create a file manager and grab the save panel's returned URL NSFileManager *manager = [NSFileManager defaultManager]; directoryPath = [panel URL]; [[self directoryLabel] setStringValue:[NSString stringWithFormat:@"%@",directoryPath]]; // then copy a previous file to the new location // copy item at URL was self.myURL // copy images that are created from array to this path for (NSImage *image in preparedImages) { #warning Fix Copy Item At URL to copy image from preparedImages array to save each one NSString *imageName = image.name; NSString *imagePath = [[directoryPath absoluteString] stringByAppendingPathComponent:imageName]; //[manager copyItemAtURL:nil toURL:directoryPath error:nil]; NSLog(@"Trying to write IMAGE: %@ to URL: %@",imageName,imagePath); //[image writePNGToURL:[NSURL URLWithString:imagePath] outputSizeInPixels:image.size error:nil]; [self saveImage:image atPath:imagePath]; } //[manager copyItemAtURL:nil toURL:directoryPath error:nil]; } }]; [preparedImages removeAllObjects]; return; } 一个用户试图通过使用此NSImage类别来回答他,但它不会为我生成任何文件或PNG. @interface NSImage (SSWPNGAdditions) - (BOOL)writePNGToURL:(NSURL*)URL outputSizeInPixels:(NSSize)outputSizePx error:(NSError*__autoreleasing*)error; @end @implementation NSImage (SSWPNGAdditions) - (BOOL)writePNGToURL:(NSURL*)URL outputSizeInPixels:(NSSize)outputSizePx error:(NSError*__autoreleasing*)error { BOOL result = YES; NSImage* scalingImage = [NSImage imageWithSize:[self size] flipped:[self isFlipped] drawingHandler:^BOOL(NSRect dstRect) { [self drawAtPoint:NSMakePoint(0.0,0.0) fromRect:dstRect operation:NSCompositeSourceOver fraction:1.0]; return YES; }]; NSRect proposedRect = NSMakeRect(0.0,0.0,outputSizePx.width,outputSizePx.height); CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); CGContextRef cgContext = CGBitmapContextCreate(NULL,proposedRect.size.width,proposedRect.size.height,8,4*proposedRect.size.width,colorSpace,kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(colorSpace); NSGraphicsContext* context = [NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:NO]; CGContextRelease(cgContext); CGImageRef cgImage = [scalingImage CGImageForProposedRect:&proposedRect context:context hints:nil]; CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)(URL),kUTTypePNG,1,NULL); CGImageDestinationAddImage(destination,cgImage,nil); if(!CGImageDestinationFinalize(destination)) { NSDictionary* details = @{NSLocalizedDescriptionKey:@"Error writing PNG image"}; [details setValue:@"ran out of money" forKey:NSLocalizedDescriptionKey]; *error = [NSError errorWithDomain:@"SSWPNGAdditionsErrorDomain" code:10 userInfo:details]; result = NO; } CFRelease(destination); return result; } @end 解决方法
我在原始
thread中提供的答案也遇到了麻烦.进一步的阅读使得Erica Sadun在
post上找到了与没有视网膜显示器的视网膜显示器调试代码有关的问题.她创建了所需大小的位图,然后将当前绘图上下文(基于显示/视网膜受影响)替换为与新位图关联的通用图形.然后,她将原始图像渲染到位图中(使用通用图形上下文).
我拿了她的代码并在NSImage上做了一个快速的类别,它似乎为我做了这个工作.打电话后 NSBitmapImageRep *myRep = [myImage unscaledBitmapImageRep]; 你应该有一个正确(原始)尺寸的位图,无论你开始使用什么类型的物理显示.从这一点开始,您可以在未缩放的位图上调用representationUsingType:属性,以获得您要写出的任何格式. 这是我的类别(标题省略).注意 – 您可能需要公开位图初始化程序的颜色空间部分.这是适用于我的特定情况的价值. -(NSBitmapImageRep *)unscaledBitmapImageRep { NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:self.size.width pixelsHigh:self.size.height bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:0 bitsPerPixel:0]; rep.size = self.size; [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithBitmapImageRep:rep]]; [self drawAtPoint:NSMakePoint(0,0) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; [NSGraphicsContext restoreGraphicsState]; return rep; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |