NSImage のサイズを最大ファイルサイズに合わせる最善の方法はありますか?
-
21-09-2019 - |
質問
これまでに私が得たものは次のとおりです。
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:
[file.image TIFFRepresentation]];
// Resize image to 200x200
CGFloat maxSize = 200.0;
NSSize imageSize = imageRep.size;
if (imageSize.height>maxSize || imageSize.width>maxSize) {
// Find the aspect ratio
CGFloat aspectRatio = imageSize.height/imageSize.width;
CGSize newImageSize;
if (aspectRatio > 1.0) {
newImageSize = CGSizeMake(maxSize / aspectRatio, maxSize);
} else if (aspectRatio < 1.0) {
newImageSize = CGSizeMake(maxSize, maxSize * aspectRatio);
} else {
newImageSize = CGSizeMake(maxSize, maxSize);
}
[imageRep setSize:NSSizeFromCGSize(newImageSize)];
}
NSData *imageData = [imageRep representationUsingType:NSPNGFileType properties:nil];
NSString *outputFilePath = [@"~/Desktop/output.png" stringByExpandingTildeInPath];
[imageData writeToFile:outputFilePath atomically:NO];
このコードでは、200x200 の PNG が 128K 未満であると想定しています。これは、私のサイズ制限です。200x200 で十分な大きさですが、可能であれば最大サイズにしたいと考えています。
ここに私の問題が 2 つあります。
- コードが機能しません。エクスポートされたファイルのサイズを確認すると、元のファイルと同じサイズです。
- エクスポートする前に出力ファイルのサイズを予測して、サイズを最大にしても 128K 未満の画像を取得できるようにする方法はありますか?
動作するコードは次のとおりです。かなりいい加減なので、最適化が必要かもしれませんが、現時点では気にならないほど高速に動作します。ほとんどの画像では 100 回以上反復され、数ミリ秒で終了します。また、このメソッドは次のカテゴリで宣言されています。 NSImage
.
- (NSData *)resizeImageWithBitSize:(NSInteger)size
andImageType:(NSBitmapImageFileType)fileType {
CGFloat maxSize = 500.0;
NSSize originalImageSize = self.size;
NSSize newImageSize;
NSData *returnImageData;
NSInteger imageIsTooBig = 1000;
while (imageIsTooBig > 0) {
if (originalImageSize.height>maxSize || originalImageSize.width>maxSize) {
// Find the aspect ratio
CGFloat aspectRatio = originalImageSize.height/originalImageSize.width;
if (aspectRatio > 1.0) {
newImageSize = NSMakeSize(maxSize / aspectRatio, maxSize);
} else if (aspectRatio < 1.0) {
newImageSize = NSMakeSize(maxSize, maxSize * aspectRatio);
} else {
newImageSize = NSMakeSize(maxSize, maxSize);
}
} else {
newImageSize = originalImageSize;
}
NSImage *resizedImage = [[NSImage alloc] initWithSize:newImageSize];
[resizedImage lockFocus];
[self drawInRect:NSMakeRect(0, 0, newImageSize.width, newImageSize.height)
fromRect: NSMakeRect(0, 0, originalImageSize.width, originalImageSize.height)
operation: NSCompositeSourceOver
fraction: 1.0];
[resizedImage unlockFocus];
NSData *tiffData = [resizedImage TIFFRepresentation];
[resizedImage release];
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:tiffData];
NSDictionary *imagePropDict = [NSDictionary
dictionaryWithObject:[NSNumber numberWithFloat:0.85]
forKey:NSImageCompressionFactor];
returnImageData = [imageRep representationUsingType:fileType properties:imagePropDict];
[imageRep release];
if ([returnImageData length] > size) {
maxSize = maxSize * 0.99;
imageIsTooBig--;
} else {
imageIsTooBig = 0;
}
}
return returnImageData;
}
解決
別のポスターは、上述したように、
は、setSizeのみ変更は、基礎となる画像ファイルの実際の画素データを画像のサイズを表示し、しない。
サイズを変更するには、あなたが別のNSImageRepに元画像を再描画して、ファイルにそれを書きたいことがあります。
このブログ記事は、このようにリサイズを行う方法にいくつかのサンプルコードが含まれています。
2については、
私は少なくとも、メモリ内のオブジェクトを作成し、画像の長さを確認せずにあなたができるとは思いません。使用される実際のバイトは、画像の種類に依存するであろう。 ARGBとビットマップはその大きさを予測することは容易になりますが、PNGとJPEGははるかに困難になります。
他のヒント
[imageData length]
NSData のコンテンツの長さが表示されるはずです。これは、ディスクに書き込まれるときの最終的なファイル サイズであると理解しています。これにより、実際にファイルを書き込む前にファイルのサイズを最大化する機会が得られます。
画像が縮小または拡大しない理由については、次のとおりです。 setSize のドキュメント:
画像表現のサイズと画像データの物理的寸法を組み合わせて、画像の解像度が決まります。
したがって、解像度を変更せずにサイズを設定することで、ピクセルを変更するのではなく、ピクセルの解釈方法を変更するだけである可能性があります。