هل هناك أفضل طريقة لحجم 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];
يفترض الرمز أن PNG 200x200 سيكون أقل من 128 ألف ، وهو حد مقاسي. 200x200 كبير بما يكفي ، لكنني أفضل أن أفرغ الحجم إن أمكن ذلك.
ها هي مشكلتي:
- الرمز لا يعمل. أتحقق من حجم الملف الذي تم تصديره وهو بنفس حجم الأصلي.
- هل هناك طريقة للتنبؤ بحجم ملف الإخراج قبل التصدير ، حتى أتمكن من الحد من الأبعاد ولكن ما زلت أحصل على صورة أقل من 128 ألف؟
ها هو رمز العمل. إنه قذر إلى حد ما ويمكن أن يستخدم بعض التحسينات ، ولكن في هذه المرحلة ، يتم تشغيله بسرعة كافية لدرجة أنني لا أهتم. يكرر أكثر من 100x لمعظم الصور ، وينتهي بالميلي ثانية. أيضا ، يتم الإعلان عن هذه الطريقة في فئة على 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;
}
المحلول
ل 1.
كما ذكر ملصق آخر ، يغير تعيين فقط أحجام عرض الصورة ، وليس بيانات البكسل الفعلية لملف الصورة الأساسي.
لتغيير الحجم ، قد ترغب في إعادة رسم الصورة المصدر على nsimagerep ثم كتابة ذلك إلى ملف.
يحتوي منشور المدونة هذا على بعض رمز النماذج حول كيفية القيام بتغيير الحجم بهذه الطريقة.
ل 2.
لا أعتقد أنه لا يمكنك على الأقل إنشاء الكائن في الذاكرة والتحقق من طول الصورة. سوف تعتمد البايتات الفعلية المستخدمة على نوع الصورة. سيكون من السهل التنبؤ بحجم النقطات مع ArgB ، لكن PNG و JPEG سيكونون أكثر صعوبة.
نصائح أخرى
[imageData length]
يجب أن يعطيك طول محتويات NSData ، والتي أفهم أنها حجم الملف النهائي عند كتابتها إلى القرص. يجب أن يمنحك ذلك فرصة لزيادة حجم الملف قبل كتابته بالفعل.
لماذا لا تتقلص الصورة أو تنمو مستندات setSize:
يحدد حجم تمثيل الصورة مع الأبعاد الفعلية لبيانات الصورة دقة الصورة.
لذلك قد يكون ذلك من خلال تحديد الحجم وعدم تغيير الدقة ، فأنت لا تقوم بتعديل أي وحدات بكسل ، فقط الطريقة التي يجب أن تفسر بها وحدات البكسل.