Странные артефакты после CILanczosScaleTransform - PullRequest
2 голосов
/ 05 февраля 2010

Я пытаюсь выполнить масштабирование изображения с помощью Core Image, используя фильтр преобразования масштаба Ланцоша. Это хорошо, когда я делаю масштабирование. Но при уменьшении масштаба и сохранении в JPEG я нашел класс изображений, которые производят странные шумовые артефакты и поведение.

Для умножения inputScale на 0,5: 0,5, 0,25, 0,125 и т. Д. Это всегда хорошо. Для других значений inputScale он не работает.

Когда я сохраняю в TIFF, PNG, JPEG2000 или рисую на экране - это нормально. Когда я сохраняю в JPG или BMP - он не работает.

Я загрузил образцы изображений: ( оригинал, 4272x2848, 3,4 МБ ) [http://www.zoomfoot.com/get/package/517e2423-7795-4239-a166-03d507ec51d8]

( масштабируется с шумом, 1920x1280, 2,2Mb ) [http://www.zoomfoot.com/get/package/6eb64d33-3a30-4e8d-9953-67ce1e7d7ef9]

Это также очень хорошо воспроизводится на изображениях «заката».

Я пробовал еще пару способов масштабирования изображений. Использование CIAffineTransform и рисование с использованием самого NSImage. Оба обеспечивают результаты без шума.

Вот код, который я использовал для масштабирования и сохранения:

================= Ланцош ==============

<code><br>
- (NSImage *) scaleLanczosImage:(NSString *)path
       Width:(int) desiredWidth
      Height:(int) desiredHeight
{
 CIImage *image=[CIImage imageWithContentsOfURL:
       [NSURL fileURLWithPath:path]];</p>

<p>CIFilter *scaleFilter = [CIFilter filterWithName:@"CILanczosScaleTransform"];
 int originalHeight=[image extent].size.height;
 int originalWidth=[image extent].size.width;</p>

<p>float yScale=(float)desiredHeight / (float)originalHeight; 
 float xScale=(float)desiredWidth / (float)originalWidth; 
 float scale=fminf(yScale, xScale);</p>

<p>[scaleFilter setValue:[NSNumber numberWithFloat:scale]
    forKey:@"inputScale"]; 
 [scaleFilter setValue:[NSNumber numberWithFloat:1.0]
    forKey:@"inputAspectRatio"];
 [scaleFilter setValue: image
    forKey:@"inputImage"];</p>

<p>image = [scaleFilter valueForKey:@"outputImage"]; </p>

<p>NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithCIImage:image];
 NSMutableDictionary *options=[NSMutableDictionary dictionaryWithObject:[NSDecimalNumber numberWithFloat:1.0] 
               forKey:NSImageCompressionFactor];</p>

<p>[options setValue:[NSNumber numberWithBool:YES] forKey:NSImageProgressive];
 NSData* jpegData = [rep representationUsingType:NSJPEGFileType
           properties:options];</p>

<p>[jpegData writeToFile:@"/Users/dmitry/tmp/img_4389-800x600.jpg" atomically:YES];
}  </p>

<h1>

================= NSImage ==============

<code><br>
- (void) scaleNSImage:(NSString *)path
    Width:(int) desiredWidth
      Height:(int) desiredHeight
{
 NSImage *sourceImage = [[NSImage alloc] initWithContentsOfFile:path];
 NSImage *resizedImage = [[NSImage alloc] initWithSize: 
        NSMakeSize(desiredWidth, desiredHeight)];</p>

<p>NSSize originalSize = [sourceImage size];</p>

<p>[resizedImage lockFocus];
 [sourceImage drawInRect: NSMakeRect(0, 0, desiredWidth, desiredHeight) 
       fromRect: NSMakeRect(0, 0, originalSize.width, originalSize.height) 
      operation: NSCompositeSourceOver fraction: 1.0];</p>

<p>[resizedImage unlockFocus];</p>

<p>NSMutableDictionary *options=[NSMutableDictionary dictionaryWithObject:[NSDecimalNumber numberWithFloat:1.0] 
                 forKey:NSImageCompressionFactor];</p>

<p>[options setValue:[NSNumber numberWithBool:YES] forKey:NSImageProgressive];</p>

<p>NSBitmapImageRep *rep  = [[NSBitmapImageRep alloc] 
            initWithData:[resizedImage TIFFRepresentation]];</p>

<p>NSData* jpegData = [rep representationUsingType:NSJPEGFileType
           properties:options];</p>

<p>[jpegData writeToFile:@"~/nsimg_4389-800x600.jpg" atomically:YES];</p>

<p>} </p>

<h1>

Если кто-то может объяснить или предложить что-то здесь, я действительно ценю это.

Спасибо.

Ответы [ 3 ]

1 голос
/ 05 февраля 2010

Насколько я понимаю, из-за своей природы аппаратный рендерер Core Image имеет некоторые странные причуды при рендеринге для чего угодно, кроме отображения на экране. Поэтому рекомендуется использовать программный рендерер для других ситуаций.

http://developer.apple.com/mac/library/qa/qa2005/qa1416.html

1 голос
/ 05 февраля 2010

Есть некоторые причуды с масштабированием с помощью CIImage. Поможет ли этот пост Дана Вуда?

0 голосов
/ 05 февраля 2010

Это определенно ошибка CoreImage. Отправьте его на bugreport.apple.com

...