Nice programing

iPhone에서 투명한 PNG 이미지에 색조를 지정하는 방법은 무엇입니까?

nicepro 2020. 10. 22. 22:47
반응형

iPhone에서 투명한 PNG 이미지에 색조를 지정하는 방법은 무엇입니까?


직사각형 이미지 위에 CGContextFillRect를 그리고 블렌드 모드를 설정하여 색을 칠할 수 있다는 것을 알고 있습니다. 그러나 아이콘과 같은 투명한 이미지에 색조를 적용하는 방법을 알 수 없습니다. SDK가 탭바에서 자체적으로 수행하므로 가능해야합니다. 누구든지 스 니펫을 제공 할 수 있습니까?

최신 정보:

내가 원래 요청한 이후로이 문제에 대해 많은 훌륭한 제안이 주어졌습니다. 가장 적합한 것이 무엇인지 알아 내기 위해 모든 답을 읽어보십시오.

업데이트 (2015 년 4 월 30 일) :

iOS 7.0에서는 이제 다음 작업을 수행 할 수 있으므로 원래 질문의 요구 사항을 충족 할 수 있습니다. 그러나 더 복잡한 사례가있는 경우 모든 답변을 확인하십시오.

UIImage *iconImage = [[UIImage imageNamed:@"myImageName"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];    
UIImageView *icon = [[UIImageView alloc] initWithImage:iconImage];
icon.tintColor = [UIColor redColor];

업데이트 : 다음은 아래 코드를 사용하는 Swift UIColor 확장에 대한 요점 입니다.


당신이있는 경우 그레이 스케일 이미지를 하고 싶은 흰색이 농도 색상되고 , kCGBlendModeMultiply길을 가야하는 것입니다. 이 방법을 사용하면 틴팅 색상보다 밝은 하이라이트를 가질 수 없습니다.

반대로, 당신이 중 하나가있는 경우 비 그레이 스케일 이미지를 , 또는 당신이 가진 하이라이트 그림자 보존해야 블렌드 모드는 kCGBlendModeColor길을 가야하는 것입니다. 이미지의 밝기가 유지되므로 흰색은 흰색으로 유지되고 검은 색은 검은 색으로 유지됩니다. 이 모드는 색조를 위해 만들어졌습니다. Photoshop의 Color레이어 혼합 모드 와 동일 합니다 (면책 조항 : 약간 다른 결과가 발생할 수 있음).

알파 픽셀 색조는 iOS 나 Photoshop에서 제대로 작동하지 않습니다. 반투명 검은 색 픽셀은 검은 색으로 유지되지 않습니다. 이 문제를 해결하기 위해 아래 답변을 업데이트했는데 알아내는 데 꽤 오랜 시간이 걸렸습니다.

kCGBlendModeSourceIn/DestinationIn대신 블렌드 모드 중 하나를 사용할 수도 있습니다 CGContextClipToMask.

를 만들려면 UIImage다음 코드 섹션을 다음 코드로 묶을 수 있습니다.

UIGraphicsBeginImageContextWithOptions (myIconImage.size, NO, myIconImage.scale); // for correct resolution on retina, thanks @MobileVet
CGContextRef context = UIGraphicsGetCurrentContext();

CGContextTranslateCTM(context, 0, myIconImage.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGRect rect = CGRectMake(0, 0, myIconImage.size.width, myIconImage.size.height);

// image drawing code here

UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

다음은 투명한 이미지에 색을 입히는 코드입니다 kCGBlendModeColor.

// draw black background to preserve color of transparent pixels
CGContextSetBlendMode(context, kCGBlendModeNormal);
[[UIColor blackColor] setFill];
CGContextFillRect(context, rect);

// draw original image
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextDrawImage(context, rect, myIconImage.CGImage);

// tint image (loosing alpha) - the luminosity of the original image is preserved
CGContextSetBlendMode(context, kCGBlendModeColor);
[tintColor setFill];
CGContextFillRect(context, rect);

// mask by alpha values of original image
CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
CGContextDrawImage(context, rect, myIconImage.CGImage);

이미지에 반투명 픽셀이없는 경우 다음을 사용하여 다른 방법으로 수행 할 수도 있습니다 kCGBlendModeLuminosity.

// draw tint color
CGContextSetBlendMode(context, kCGBlendModeNormal);
[tintColor setFill];
CGContextFillRect(context, rect);

// replace luminosity of background (ignoring alpha)
CGContextSetBlendMode(context, kCGBlendModeLuminosity);
CGContextDrawImage(context, rect, myIconImage.CGImage);

// mask by alpha values of original image
CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
CGContextDrawImage(context, rect, myIconImage.CGImage);

광도에 신경 쓰지 않는다면, 색상으로 착색해야하는 알파 채널이있는 이미지를 방금 얻었으므로보다 효율적인 방법으로 수행 할 수 있습니다.

// draw tint color
CGContextSetBlendMode(context, kCGBlendModeNormal);
[tintColor setFill];
CGContextFillRect(context, rect);

// mask by alpha values of original image
CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
CGContextDrawImage(context, rect, myIconImage.CGImage);

또는 그 반대 :

// draw alpha-mask
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextDrawImage(context, rect, myIconImage.CGImage);

// draw tint color, preserving alpha values of original image
CGContextSetBlendMode(context, kCGBlendModeSourceIn);
[tintColor setFill];
CGContextFillRect(context, rect);

즐기세요!


내가 시도한 다른 방법은 특정 색상 조합에 대해 반투명 픽셀의 색상을 왜곡했기 때문에이 방법으로 가장 성공했습니다. 이것은 또한 성능 측면에서 조금 더 나아질 것입니다.

+ (UIImage *) imageNamed:(NSString *) name withTintColor: (UIColor *) tintColor {

    UIImage *baseImage = [UIImage imageNamed:name];

    CGRect drawRect = CGRectMake(0, 0, baseImage.size.width, baseImage.size.height);

    UIGraphicsBeginImageContextWithOptions(baseImage.size, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextTranslateCTM(context, 0, baseImage.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    // draw original image
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    CGContextDrawImage(context, drawRect, baseImage.CGImage);

    // draw color atop
    CGContextSetFillColorWithColor(context, tintColor.CGColor);
    CGContextSetBlendMode(context, kCGBlendModeSourceAtop);
    CGContextFillRect(context, drawRect);

    UIImage *tintedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return tintedImage;
}

주변을 검색 한 후 지금까지 찾은 최고의 솔루션은 블렌드 모드와 클리핑 마스크의 조합을 사용하여 투명한 PNG의 색상 / 색조를 달성하는 것입니다.

CGContextSetBlendMode (context, kCGBlendModeMultiply);

CGContextDrawImage(context, rect, myIconImage.CGImage);

CGContextClipToMask(context, rect, myIconImage.CGImage);

CGContextSetFillColorWithColor(context, tintColor);

CGContextFillRect(context, rect);

kCGBlendModeOverlay를 사용하여 Apple 탐색 막대의 색조에 매우 가까운 결과를 얻을 수 있습니다. excelent @fabb 응답 촬영이 게시물에 @omz 접근 방식을 결합 https://stackoverflow.com/a/4684876/229019 나는 헬드 결과 내가 기대 것을이 솔루션과 함께 제공 :

- (UIImage *)tintedImageUsingColor:(UIColor *)tintColor;
{
    UIGraphicsBeginImageContextWithOptions (self.size, NO, [[UIScreen mainScreen] scale]);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);

    // draw original image
    [self drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0f];

    // tint image (loosing alpha). 
    // kCGBlendModeOverlay is the closest I was able to match the 
    // actual process used by apple in navigation bar 
    CGContextSetBlendMode(context, kCGBlendModeOverlay);
    [tintColor setFill];
    CGContextFillRect(context, rect);

    // mask by alpha values of original image
    [self drawInRect:rect blendMode:kCGBlendModeDestinationIn alpha:1.0f];

    UIImage *tintedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return tintedImage;
}

다음은 투명도로 여러 회색조 이미지를 착색하는 예입니다.

렌더링 된 예:

  • 첫 번째 줄은 [UIColor orangeColor] 색조의 사과 도구 모음입니다.
  • 두 번째 선은 선명한 색상 (= 실제 그라디언트)으로 시작하여 동일한 주황색으로 끝나는 여러 색상의 동일한 그라디언트입니다.
  • 세 번째는 투명도가있는 단순한 원입니다 (린넨은 배경색입니다).
  • 네 번째 줄은 복잡한 어두운 노이즈 텍스처입니다.

UIImage 카테고리를 만들고 다음과 같이 할 수 있습니다.

- (instancetype)tintedImageWithColor:(UIColor *)tintColor {
    UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGRect rect = (CGRect){ CGPointZero, self.size };
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    [self drawInRect:rect];

    CGContextSetBlendMode(context, kCGBlendModeSourceIn);
    [tintColor setFill];
    CGContextFillRect(context, rect);

    UIImage *image  = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

iOS7에서는 UIImageView에 tintColor 속성을, UIImage에 renderingMode를 도입했습니다. https://stackoverflow.com/a/19125120/1570970 에서 내 예를 참조하십시오.


iOS 7.0에서는 다음과 같이 기본 UIImageView에 색조를 지정할 수도 있습니다.

UIImage *iconImage = [[UIImage imageNamed:@"myImageName"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];    
UIImageView *icon = [[UIImageView alloc] initWithImage:iconImage];
icon.tintColor = [UIColor redColor];

fabb의 대답에서 UIImage를 만드는 "주변"코드가 망막 화면에서 이미지의 잘못된 해상도를 제공했습니다. 수정하려면 다음을 변경하십시오.

UIGraphicsBeginImageContext(myIconImage.size);

에:

UIGraphicsBeginImageContextWithOptions(myIconImage.size, NO, 0.0);

0.0으로 설정된 마지막 매개 변수는 스케일이며 Apple 문서에 따르면 다음과 같습니다.

"값 0.0을 지정하면 배율이 장치의 기본 화면 배율로 설정됩니다."

댓글을 달 수있는 권한이없고 편집이 다소 무례 해 보이므로 답변에서 언급합니다. 누군가가 이와 같은 문제에 직면 할 경우를 대비하여.


UIImageView (또는 해당 문제에 대한 모든보기)에는 RGBA 인 배경색이 있습니다. 색상의 알파는 새로운 것을 발명하지 않고도 필요한 것을 할 수 있습니다.


내 작업은 아니지만 다음 접근 방식을 성공적으로 사용했습니다.

http://coffeeshopped.com/2010/09/iphone-how-to-dynamically-color-a-uiimage


사용자 지정 UIButton 하위 클래스에서 이미지 뷰를 음영 처리하고 싶었고 다른 솔루션은 내가 원하는 것을 수행하지 않았습니다. 이미지 색상을 "색조"를 어둡게해야했습니다. CoreImage를 사용하여 밝기를 변경하는 방법은 다음과 같습니다.

버튼 누를 때 음영 처리 된 이미지가있는 사용자 정의 버튼

  1. Make sure you add CoreImage.framework to your project's libraries. (Link Binary with Libraries)

  2. UIImage shade method

    - (UIImage *)shadeImage:(UIImage *)image {
     CIImage *inputImage = [CIImage imageWithCGImage:image.CGImage];
    
     CIContext *context = [CIContext contextWithOptions:nil];
    
     CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"
                                  keysAndValues:kCIInputImageKey, inputImage,
                        @"inputBrightness", [NSNumber numberWithFloat:-.5], nil];
     CIImage *outputImage = [filter outputImage];
    
     CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]];
     UIImage *newImage = [UIImage imageWithCGImage:cgImage scale:image.scale orientation:image.imageOrientation];
     CGImageRelease(cgImage);
    
     return newImage;
    }
    
  3. You'll want to store a copy of the context as an ivar, rather than recreate it.


No answers will help me on stack overflow: our designers draw UI elements with various forms, various alpha values (and "alpha-holes"). In most cases, this is 32-Bit PNG file with alpha channel, which comprises black & white pixels (of all possible intensities). After tinting such a picture I had to get this tinted result: white pixels - tinted over more, and dark pixels - less. And all this in view of alpha channel. And i wrote this method for my UIImage category. Maybe it not high efficient, but it work as clock:) Here it is:

- (UIImage *)imageTintedWithColor:(UIColor *)color {
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);

    CGContextSetBlendMode(context, kCGBlendModeCopy);
    [color setFill];
    CGContextFillRect(context, rect);

    [self drawInRect:rect blendMode:kCGBlendModeXOR alpha:1.0];

    CGContextSetBlendMode(context, kCGBlendModeXOR);
    CGContextFillRect(context, rect);

    [self drawInRect:rect blendMode:kCGBlendModeMultiply alpha:1.0];

    UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return coloredImage;
}

먼저 반투명 아이콘에 색을 입히는 작업을 수행하는 데 도움이 된 그의 탁월한 솔루션에 대해 fabb에게 감사드립니다. C # (Monotouch) 솔루션이 필요했기 때문에 그의 코드를 번역해야했습니다. 여기에 내가 생각 해낸 것이 있습니다. 이것을 코드에 복사하여 붙여넣고 반투명 이미지를 추가하면됩니다.

다시 모든 크레딧은 fabb로 이동합니다. 이것은 C # 사용자를 시작하는 것입니다. :)

//TINT COLOR IMAGE
UIImageView iImage = new UIImageView(new RectangleF(12, 14, 24,24));
iImage.ContentMode = UIViewContentMode.ScaleAspectFit;
iImage.Image = _dataItem.Image[0] as UIImage;

UIGraphics.BeginImageContextWithOptions(iImage.Bounds.Size, false, UIScreen.MainScreen.Scale);
CGContext context = UIGraphics.GetCurrentContext();

context.TranslateCTM(0, iImage.Bounds.Size.Height);
context.ScaleCTM(1.0f, -1.0f);

RectangleF rect = new RectangleF(0,0, iImage.Bounds.Width, iImage.Bounds.Height);

// draw black background to preserve color of transparent pixels
context.SetBlendMode(CGBlendMode.Normal);
UIColor.Black.SetFill();
context.FillRect(rect);

// draw original image
context.SetBlendMode(CGBlendMode.Normal);
context.DrawImage(rect, iImage.Image.CGImage);

// tint image (loosing alpha) - the luminosity of the original image is preserved
context.SetBlendMode(CGBlendMode.Color);
UIColor.Orange.SetFill();
context.FillRect(rect);

// mask by alpha values of original image
context.SetBlendMode(CGBlendMode.DestinationIn);
context.DrawImage(rect, iImage.Image.CGImage);

UIImage coloredImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();

iImage = new UIImageView(coloredImage);
iImage.Frame = new RectangleF(12, 14, 24,24);
//END TINT COLOR IMAGE

cell.Add(iImage);

참고 URL : https://stackoverflow.com/questions/3514066/how-to-tint-a-transparent-png-image-in-iphone

반응형