Social Icons

.

воскресенье, 13 марта 2011 г.

Наложить маску на UIImage

Есть UIScrollView, в который уже добавлен какой-то subview. Требуется заменить его новым, с новым изображением. Причем изображение следует построить из нескольких, путем их комбинирования. Есть три изображения. «Серое» изображение - оно является общим фоном. Черное изображение на белом фоне - маска. Цветное изображение. Требуется по маске вырезать цветное изображение и наложить его на серое. Итоговое изображение следует вывести на экран вместо старого.



Изображения: Цветное, Маска, Серое.



Пример использования функций наложения изображения

Итоговое изображение следует вывести на экран вместо старого. Результатам должно стать серое изображение с цветным пятном в центре (практически). Делается это следующим образом:
reloadView

-(void) reloadView:(CGPoint )theTouchPoint
{
 UIImage *imageMask = [UIImage imageNamed:@"Europe_Germany_mask.png"];
 UIImage *imageFull = [UIImage imageNamed:@"Europe_Full.png"];
 UIImage *imageGermany = [self maskImage:imageFull withMask:imageMask];
 
 UIImage *imageGray = [UIImage imageNamed:@"Europe_Gray.png"]; 
 UIImage *imageCombine = [self concatImage: imageGray withMask:imageGermany]; 
 
 if(imageView != nil){
  [imageView removeFromSuperview];
  [imageView release];
 }
 imageView = [[UIImageView alloc] initWithImage:imageCombine];
 [scrollView addSubview:imageView];
}

Обратить внимание, на тот факт, что у UIView есть метод AddSubview, но нет аналогичного метода для удаления этого subview. Зато тому UIView, который был добавле в качестве subview можно сказать removeFromSuperview. И он благополучно поудаляет себя из мест где им владеют. Я не проверял, как он себя поведет если он принадлежит нескольким владельцам. 

Функции наложения изображения

Наложение маски дает возможность динамически создавать изображения нестандартной формы.
 Например: 

  Пример наложения маски на изображение, используя Quartz2d:

-(CGImageRef) CopyImageAndAddAlphaChannel:(CGImageRef) sourceImage {
 CGImageRef retVal = NULL;
 
 size_t width = CGImageGetWidth(sourceImage);
 size_t height = CGImageGetHeight(sourceImage);
 
 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
 
 CGContextRef offscreenContext = CGBitmapContextCreate(NULL, width, height,
                8, 0, colorSpace, kCGImageAlphaPremultipliedFirst);
 
 if (offscreenContext != NULL) {
  CGContextDrawImage(offscreenContext, CGRectMake(0, 0, width, height), sourceImage);
 
  retVal = CGBitmapContextCreateImage(offscreenContext);
  CGContextRelease(offscreenContext);
 }
 
 CGColorSpaceRelease(colorSpace);
 
 return retVal;
}
 
- (UIImage *)maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
 CGImageRef maskRef = maskImage.CGImage;
 CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
          CGImageGetHeight(maskRef),
          CGImageGetBitsPerComponent(maskRef),
          CGImageGetBitsPerPixel(maskRef),
          CGImageGetBytesPerRow(maskRef),
          CGImageGetDataProvider(maskRef), NULL, false);
 
 CGImageRef sourceImage = [image CGImage];
 CGImageRef imageWithAlpha = sourceImage;
 //add alpha channel for images that don't have one (ie GIF, JPEG, etc...)
 //this however has a computational cost
 if (CGImageGetAlphaInfo(sourceImage) == kCGImageAlphaNone) {
  imageWithAlpha = [self CopyImageAndAddAlphaChannel:sourceImage];
 }
 
 CGImageRef masked = CGImageCreateWithMask(imageWithAlpha, mask);
 CGImageRelease(mask);
 
 //release imageWithAlpha if it was created by CopyImageAndAddAlphaChannel
 if (sourceImage != imageWithAlpha) {
  CGImageRelease(imageWithAlpha);
 }
 
 UIImage* retImage = [UIImage imageWithCGImage:masked];
 CGImageRelease(masked);
 
 return retImage;

Пример использования
orgImage = [UIImage imageNamed:@"picture.png"];
if(orgImage==nil){
 NSLog(@"Error! Image not found!");
 return;
}
UIImage *mask = [UIImage imageNamed:@"mask.png"];
if(mask==nil){
 NSLog(@"Error! Image not found!");
 return;
}
 
orgImage=[[self maskImage:orgImage withMask:mask] retain];
Для того, чтобы просто наложить одно изображение поверх другого:

- (UIImage *)concatImage:(UIImage *)image withMask:(UIImage *)maskImage {
 CGImageRef sourceImage = [image CGImage];
 CGImageRef maskedImage = [maskImage CGImage];
 CGImageRef retVal = NULL;
 
 size_t width = CGImageGetWidth(sourceImage);
 size_t height = CGImageGetHeight(sourceImage);
 
 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
 
 CGContextRef offscreenContext = CGBitmapContextCreate(NULL, width, height,
                8, 0, colorSpace, kCGImageAlphaPremultipliedFirst);
 
 if (offscreenContext != NULL) {
  CGContextDrawImage(offscreenContext, CGRectMake(0, 0, width, height), sourceImage);
  CGContextDrawImage(offscreenContext, CGRectMake(0, 0, width, height), maskedImage);
  //CGContextSetBlendMode(offscreenContext, kCGBlendModeMultiply);
 
  retVal = CGBitmapContextCreateImage(offscreenContext);
  CGContextRelease(offscreenContext);
 }
 
 CGColorSpaceRelease(colorSpace);
 
 UIImage* retImage = [UIImage imageWithCGImage:retVal];
 CGImageRelease(retVal);
 
 return retImage;
}

Архив с исходниками

Комментариев нет:

Отправить комментарий

 

Так говорил Учитель:

У хорошо написанной программы есть свой собственный рай, у плохо написанной — свой собственный ад.

Russian Developer

Взгляд его светел, усилия праведны, старания бесплодны, дело безнадежно ...