天天看点

位图上下文 bitmap graphics context

这次我们要来学习如何为一张图片添加水印,为图片添加水印是现在很多社交软件都有实现的一个功能,我们在微博上面查看好友的图片的时候,图片的右下方经常附带有发表该微博的作者的名字,这就是我们今天要实现的效果。在示例的最后还会用到在学OC的时候学得NSData方法将处理后的位图保存为png或者jpg的图片文件。

有朋友也许会问,我们创建两个对象,一个是图片对象,一个是水印对象,水印对象的背景色设置为透明色,将两个对象进行重叠不就可以实现了水印的效果了嘛?
对,这样也可以达到目标,那是在图层上下文(layer graphics context)中实现的,这次我们来使用位图上下文(bitmap graphics context)来实现,顺便来了解一下位图上下文。什么是位图上下文呢?将绘制的东西输入到一张图片上,我们就称之为位图上下文。

PS:在UIView的drawRect获取的是图层上下文。

首先为项目添加两张图片,一张是主图,一张是水印图,然后为UIImage类创建分类,该分类实现的效果是合成一张水印图。
           
//创建分类:.h头文件
#import <UIKit/UIKit.h>
@interface UIImage (WaterMakerImage)

+ (instancetype)waterMakeImage:(NSString*)imageName underImage:(NSString*)underImageName;

@end
           
//.m源文件
#import "UIImage+WaterMakerImage.h"
@implementation UIImage (WaterMakerImage)
+ (instancetype)waterMakeImage:(NSString*)imageName underImage:(NSString*)underImageName
{
    if(self){

    }
    //根据传进来的数据创建图片-主图
    UIImage* underImage = [UIImage imageNamed:underImageName];

    //创建位图上下文,在创建的时候已经是开启了位图上下文了。
    /*
     第一个参数是传入原始图片的的尺寸
     第二个参数是alpha通道,yes是不透明,no是透明,选择no生成的图片会比较清晰
     第三个参数是生成图片与原始图片的比例,这里如果传入0.0的话,表示默认是系统的比例
     */
    UIGraphicsBeginImageContextWithOptions(underImage.size, NO, );

    //绘制主图
    UIScreen* screen = [UIScreen mainScreen];
    float underImageW = underImage.size.width > screen.bounds.size.width ? screen.bounds.size.width:underImage.size.width;
    float underImageH = underImageW/underImage.size.width*underImage.size.height;
    [underImage drawInRect:CGRectMake(, , underImageW, underImageH)];

    //根据传进来的数据创建图片-水印
    UIImage* waterMakeImage = [UIImage imageNamed:imageName];
    //绘制水印
    float waterMakeImageH = waterMakeImage.size.height>underImage.size.height*0?underImage.size.height*0:waterMakeImage.size.height;
    float waterMakeImageW = waterMakeImage.size.width*(waterMakeImageH/waterMakeImage.size.height);
    float waterMakeImageX = underImageW-waterMakeImageW;
    float waterMakeImageY = underImageH-waterMakeImageH;

    [waterMakeImage drawInRect:CGRectMake(waterMakeImageX, waterMakeImageY, waterMakeImageW, waterMakeImageH)];
    //    NSLog(@"%.2f,%.2f,%.2f,%.2f",waterMakeImageX,waterMakeImageY,waterMakeImageW,waterMakeImageH);

    //用UIImage创建对象接受位图上下文绘制好的图片
    UIImage* bitmapImage = UIGraphicsGetImageFromCurrentImageContext();

    //结束位图编辑
    UIGraphicsEndImageContext();

    return bitmapImage;
}
@end
           

这样子,就已经创建好水印图片的实现了,现在只要在ViewController里面进行一些小设置就可以了。

- (void)viewDidLoad {
    [super viewDidLoad];
    UIImage* image = [UIImage waterMakeImage:@"xglog_wi" underImage:@"img"];
    UIImageView* imageView = [[UIImageView alloc]initWithImage:image];

    [self.view addSubview:imageView];

}
           

运行效果:

位图上下文 bitmap graphics context
现在虽然可以看到生成水印图了,但是还没有做生成png格式图片的功能。现在就在Viewcontroller里面重写touch的一个方法,只要点击屏幕就会执行touch方法。
           

//该方法只要点击屏幕一次,就会把水印图按照程序所写的路径生成一张图片

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSData* PNGimage = UIImagePNGRepresentation(self.image);
    //下面的这个方法是生成jpg图片的,后面的参数是图片的压缩质量
//    NSData* pngImage = UIImageJPEGRepresentation(self.image, 0.7);
    [PNGimage writeToFile:@"/Users/housn-k/Desktop/WaterMakeImage.png" atomically:YES];
}
           

效果图片:

位图上下文 bitmap graphics context

博客代码