CGImageCreateWithImageInRect неправильно обрезает - PullRequest
4 голосов
/ 09 ноября 2011

У меня чертовски много времени используется CGImageCreateWithImageInRect, чтобы обрезать фотографию.В моем приложении пользователь перемещает / увеличивает изображение до тех пор, пока оно не заполняет вид 316 x 316, а затем я хочу, чтобы оно обрезало любую область за пределами рамки и сохраняло изображение как UIImage.Я определяю источник обрезки, беря абсолютное значение источника изображения x и y, так как это возвращает меня к 0,0 из окна / вида, содержащего представление изображения.Ниже приведен код:

    CGRect croppedRect = CGRectMake(fabs(widthDistanceToOrigin), fabs(HeightDistanceToOrigin), 316, 316);
    CGImageRef croppedImageRef = CGImageCreateWithImageInRect(image.CGImage, croppedRect); 
    UIImage *croppedImage = [UIImage imageWithCGImage: croppedImageRef scale: 1 / (imageScale) orientation: image.imageOrientation];
    CGImageRelease(croppedImageRef); 

Это сводит меня с ума, я просто не могу заставить его обрезать нужную область.Я правильно настроил масштабирование, но проблема, похоже, в том, что X и Y имеют начало прямоугольника кадрирования, это совсем немного от области, которую он должен взять (и иногда я получаю странные результаты).

Кроме того, кажется, что для изображений, сделанных камерой телефона, мне нужно умножить все в моем кадрированном прямоугольнике на 2, чтобы он был правильного размера.Очень странно.

Поэтому мне интересно, кто-нибудь знает, как это исправить, или у кого-нибудь есть лучший способ обрезки (и имейте в виду, что мне нужно обрезать область на моей фотографии),Спасибо!

Ответы [ 3 ]

4 голосов
/ 11 февраля 2014

Есть так много сообщений на эту тему, все они имеют одинаковый точный ответ, использовать: CGImageCreateWithImageInRect но ни один из них полностью не решает проблему неправильного позиционирования того, что пытается обрезать.

Тем не менее, только одна нить (скрытая глубоко внутри), имеет незначительную деталь, которой не хватает всем остальным ... Как обрезать UIImageView для нового UIImage в режиме 'аспектной подгонки'?

параметр 'rect', который входит в CGImageCreateWithImageInRect (image.CGImage, croppedRect) должен представлять (взятый из) UIImage, а не UIImageView.

это должно решить проблему неправильного позиционирования в системе координат.

 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:   (NSDictionary *)info
 {
        oImage = [info valueForKey:UIImagePickerControllerOriginalImage];
        NSLog(@"Original Image size width: %f x height: %f", oImage.size.width, oImage.size.height);


        // crop image according to what the image picker view is displaying
        CGRect rect = CGRectMake(0, 40, 960.0f, 960.0f); // note: 960 x 1280 is what natively comes from capturing and image
        nImage = [BGViewModifiers cropImage:oImage inRect:rect];

        // scale image down for display and creating kombie
        CGSize size = CGSizeMake(320.0f, 320.0f);
        nImage = [BGViewModifiers imageFromImage:nImage scaledToSize:size];

        NSLog(@"New Image size width: %f x height: %f", [nImage size].width, [nImage size].height);
 }

 //ref: http://stackoverflow.com/a/25293588/2298002
 + (UIImage *)cropImage:(UIImage*)image inRect:(CGRect)rect
 {
    double (^rad)(double) = ^(double deg) {
       return deg / 180.0 * M_PI;
    };

    CGAffineTransform rectTransform;
    switch (image.imageOrientation) {
      case UIImageOrientationLeft:
          rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height);
          break;
      case UIImageOrientationRight:
          rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0);
          break;
      case UIImageOrientationDown:
          rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height);
          break;
      default:
          rectTransform = CGAffineTransformIdentity;
  };
  rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale);

  CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectApplyAffineTransform(rect, rectTransform));
  UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
  CGImageRelease(imageRef);

  return result;
 }

 + (UIImage*)imageFromImage:(UIImage*)image scaledToSize:(CGSize)newSize
 {
    UIGraphicsBeginImageContext( newSize );
    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
 }
1 голос
/ 15 июня 2015

Я хотел бы предоставить дополнительную информацию / ответ для этого на основе моего собственного опыта.

С точки зрения UIImage (и, следовательно, CGImageCreateWithImageInRect:), (0, 0) находится внизу слева. При определении квадрата обрезки вы можете просто рассчитать квадрат на основе стандартной портретной ориентации, а затем использовать метод в ответе @ теплица (снова опубликовано здесь для ясности и изменено на CGFloat для исправления ошибки приведения.

- (UIImage *)cropImage:(UIImage*)image toRect:(CGRect)rect {
    CGFloat (^rad)(CGFloat) = ^CGFloat(CGFloat deg) {
        return deg / 180.0f * (CGFloat) M_PI;
    };

    // determine the orientation of the image and apply a transformation to the crop rectangle to shift it to the correct position
    CGAffineTransform rectTransform;
    switch (image.imageOrientation) {
        case UIImageOrientationLeft:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height);
            break;
        case UIImageOrientationRight:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0);
            break;
        case UIImageOrientationDown:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height);
            break;
        default:
            rectTransform = CGAffineTransformIdentity;
    };

    // adjust the transformation scale based on the image scale
    rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale);

    // apply the transformation to the rect to create a new, shifted rect
    CGRect transformedCropSquare = CGRectApplyAffineTransform(rect, rectTransform);
    // use the rect to crop the image
    CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, transformedCropSquare);
    // create a new UIImage and set the scale and orientation appropriately
    UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
    // memory cleanup
    CGImageRelease(imageRef);

    return result;
}

Этот код смещает квадрат кадрирования так, чтобы он находился в правильном относительном положении.

0 голосов
/ 11 ноября 2011

Я нашел проблему.Я пытался захватить область обрезки, прежде чем масштабировать изображение.Теперь нужно выяснить, как уменьшить изображение, прежде чем я сделаю "CGImageCreateWithImageInRect".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...