9

各画像を.PNGファイルとして配列に保存しようとしています(Retina Mac dpiの問題のために拡大せずに、適切なサイズとしても)、解決策が見つからないようです。How to save PNG file from NSImage (retina issues)の解決策はどれもうまくいかないようです。私はそれぞれを試しましたが、それぞれが72x72ファイルをretina .etcに144x144として保存します。

より具体的には、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;

}

1 人のユーザーがこの 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
4

4 に答える 4

4

Tad - このコードをどうもありがとうございました - 私はこれについて何日も苦しんでいました! MacにRetinaディスプレイがインストールされているにもかかわらず、解像度を72DPIに保ちながら、NSImageからファイルを書き込むのに役立ちました。NSImage を特定のピクセル サイズとタイプ (PNG、JPG など) のファイルに 72 DPI の解像度で保存したい他の人のために、ここに私のために働いたコードがあります。これを機能させるには、 unscaledBitmapImageRep を呼び出す前に、画像のサイズを設定する必要があることがわかりました。

-(void)saveImage:(NSImage *)image
     AsImageType:(NSBitmapImageFileType)imageType
         forSize:(NSSize)targetSize
          atPath:(NSString *)path
{
    image.size = targetSize;

    NSBitmapImageRep * rep = [image unscaledBitmapImageRep:targetSize];

    // Write the target image out to a file
    NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
    NSData *targetData = [rep representationUsingType:imageType properties:imageProps];
    [targetData writeToFile:path atomically: NO];

    return;
}

以下に、カテゴリ ヘッダーと .m ファイルのソース コードも含めます。

NSImage+Scaling.h ファイル:

#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>

@interface NSImage (Scaling)

-(NSBitmapImageRep *)unscaledBitmapImageRep;

@end

そして NSImage+Scaling.m ファイル:

#import "NSImage+Scaling.h"

#pragma mark - NSImage_Scaling
@implementation NSImage (Scaling)

-(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];

    [NSGraphicsContext saveGraphicsState];
    [NSGraphicsContext setCurrentContext:
    [NSGraphicsContext graphicsContextWithBitmapImageRep:rep]];    

    [self drawAtPoint:NSMakePoint(0, 0)
             fromRect:NSZeroRect
            operation:NSCompositeSourceOver
             fraction:1.0];

    [NSGraphicsContext restoreGraphicsState];
    return rep;
}

@end
于 2015-11-18T12:56:59.877 に答える