Objective-C圖片處理

背景

1.在我們的實際開發(fā)工作中隨著項目的深入對于圖片得要求越來高,考慮的外在條件也越來越多

2.我們不在滿足于UI給我圖片我們直接加載顯示在視圖上谎碍,我們需要考慮資源包的大小,圖片的可擴(kuò)展性(機(jī)型的適配)

3.所以在這里給大家分享圖片一些關(guān)于圖片處理的技術(shù)

一且警、圖片截屏處理

1.獲取某個視圖的截屏

- (UIImage *)getScreenRecordingImageWithView:(UIView *)view
{
    // 1.設(shè)置獲取畫布大小
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(view.frame.size.width, view.frame.size.height), YES, [UIScreen mainScreen].scale);
    // [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:true];  
    UIImage *screenshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return screenshotImage;
}

二岂贩、視圖的顏色處理

1.設(shè)置視圖漸變色效果

- (void)setGradientLayerWithView:(UIView *)view {
    // 創(chuàng)建 CAGradientLayer 對象 
    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    // 設(shè)置 gradientLayer 的 Frame
    gradientLayer.frame = view.bounds;
    // 創(chuàng)建漸變色數(shù)組,需要轉(zhuǎn)換為CGColor顏色
    gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor, [UIColor yellowColor].CGColor, (__bridge id)[UIColor redColor].CGColor];
    // 設(shè)置三種顏色變化點(diǎn)娱局,取值范圍 0.0~1.0
    gradientLayer.locations = @[@(0.0f) ,@(0.2f) ,@(1.0f)];
    // 設(shè)置漸變顏色方向,左上點(diǎn)為(0,0), 右下點(diǎn)為(1,1)
    gradientLayer.startPoint = CGPointMake(0, 0);
    gradientLayer.endPoint = CGPointMake(0, 1);
    // 添加漸變色到創(chuàng)建的 UIView 上去
    [view.layer addSublayer:gradientLayer];
}

2.視圖漸隱效果設(shè)置

// 在很多時候我們?yōu)榱嗽鰪?qiáng)我們的視覺交互效果咧七,往往讓一些視圖在邊界位置有一個漸隱,效果衰齐,
// 例如:很多音樂播放器中歌詞滾出屏幕或者進(jìn)入屏幕時,文字會像切掉一樣很生硬继阻,如果能讓文字出現(xiàn)漸隱效果會更好一些
// 實現(xiàn)思慮:1.UIView的蒙版效果耻涛,蒙版視圖實體和視圖重疊位置顯示,蒙版視圖透明位置和視圖重疊位置隱藏瘟檩,蒙版視圖有透明效果位置和視圖重疊位置alpha = 1.0 - 蒙版視圖.alpha 
// 2.使用漸變視圖作為蒙版視圖
- (void)setBoundaryFadeWithView:(UIView *)view {
    // 1.獲取一個黑色到透明色漸變色蒙版
    UIView *maskView = [[UIView alloc] initWithFrame:view.bounds];
    // 創(chuàng)建 CAGradientLayer 對象 
    CAGradientLayer *gradientLayer = [CAGradientLayer layer]; 
    // 設(shè)置 gradientLayer 的 Frame gradientLayer.frame = view.bounds; 
    // 創(chuàng)建漸變色數(shù)組抹缕,需要轉(zhuǎn)換為CGColor顏色 
    gradientLayer.colors = @[[UIColor colorWithWhite:0 alpha:0].CGColor, [UIColor blackColor].CGColor, [UIColor blackColor].CGColor, [UIColor colorWithWhite:0 alpha:0].CGColor];
    // 設(shè)置三種顏色變化點(diǎn),取值范圍 0.0~1.0 
    gradientLayer.locations = @[@(0.0f) ,@(0.1f) ,@(0.9f) ,@(1.0f)]; 
    // 設(shè)置漸變顏色方向墨辛,左上點(diǎn)為(0,0), 右下點(diǎn)為(1,1) 
    gradientLayer.startPoint = CGPointMake(0, 0); 
    gradientLayer.endPoint = CGPointMake(0, 1); 
    // 添加漸變色到創(chuàng)建的 UIView 上去 
    [maskView.layer addSublayer:gradientLayer];

    // 2.把maskView作為view的蒙版視圖
    view.maskView = maskView;
}

3.獲取任意顏色色的png圖片視圖

- (void)setPNGColorView:(UIView *)view pngImage:(UIImage *)pngImage color:(UIColor *)color {
    // 1.設(shè)置視圖的顏色
    view.backgroundColor = color;
    // 2.創(chuàng)建蒙版
    UIImageView *maskView = [[UIImageView alloc] initWithFrame:view.bounds];
    maskView.image = pngImage;
    view.maskView = maskView;
}

三卓研、iOS繪制鏤空的圖片

// 獲取鏤空的背景圖片,例如我們在日常開發(fā)中添加的各種功能引導(dǎo)視圖背蟆,需要遮罩中漏出需要看到的按鈕或者圖片
- (UIImage*)drawHollowPicture
{
    // 01 創(chuàng)建畫布
    CGFloat width = [UIScreen mainScreen].bounds.size.width;
    CGFloat height = [UIScreen mainScreen].bounds.size.height;
    CGRect frame = CGRectMake(0, 0, width, height);
    UIGraphicsBeginImageContextWithOptions(frame.size, false, [UIScreen mainScreen].nativeScale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    // 02 繪制背景顏色
    UIColor *bgColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
    CGContextSetFillColorWithColor(context, bgColor.CGColor);
    CGContextAddRect(context, frame);
    CGContextDrawPath(context, kCGPathFill);
    // 03 裁剪圓形
    // 設(shè)置繪制模式
    CGContextSetBlendMode(context, kCGBlendModeClear);
    // 畫橢圓
    CGContextAddEllipseInRect(context, CGRectMake(10, 10, 60, 60)); //橢圓
    CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
    CGContextDrawPath(context, kCGPathFill);
    // 04 獲取繪制圖片
    UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return theImage;
}

四、iOS中對圖片進(jìn)行數(shù)字處理的方式

// 1.灰度處理

- (UIImage*)getNewImageWithOldImage:(UIImage*)image { 
    // 1.定義色值的索引位置
    const int RED =0;
    const int GREEN =1;
    const int BLUE =2;
    const int ALPHA =3;
    // 2.定義圖片的大小
    CGRect imageRect = CGRectMake(0,0, image.size.width* image.scale, image.size.height* image.scale);
    int width = imageRect.size.width;
    int height = imageRect.size.height;
    // 3.創(chuàng)建圖片像素數(shù)組的內(nèi)存大小
    uint32_t *pixels = (uint32_t*) malloc(width * height *sizeof(uint32_t));
    // 清空像素組里面的內(nèi)容
    memset(pixels,0, width * height *sizeof(uint32_t));
    // 4.創(chuàng)建色系對象
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    // 5.創(chuàng)建一個rgba像素的畫布對象哮幢,像素存放在pixels中
    // create a context with RGBA pixels
    CGContextRef context = CGBitmapContextCreate(pixels, width, height,8, width *sizeof(uint32_t), colorSpace,kCGImageAlphaPremultipliedLast);
    // 6.把圖片繪制到畫布上带膀,并且同步到存放像素內(nèi)容的數(shù)組中
    // paint the bitmap to our context which will fill in the pixels array
    CGContextDrawImage(context,CGRectMake(0,0, width, height), [image CGImage]);
    // 7.遍歷所有的像素點(diǎn)進(jìn)行處理
    for(int y = 0; y < height; y++) {
        for(int x = 0; x < width; x++) {
            // 01 每一個像素點(diǎn)的顏色數(shù)組
            uint8_t *rgbaPixel = (uint8_t*) &pixels[y * width + x];
            // 02 色彩灰度處理
            uint32_t gray = 0.3 * rgbaPixel[RED] +0.59 * rgbaPixel[GREEN] +0.11 * rgbaPixel[BLUE];
            // rgbaPixel[RED] = gray;    
            // rgbaPixel[GREEN] = gray;
            // rgbaPixel[BLUE] = gray;
            // 03 單一顏色替換成紅色
            if (rgbaPixel[RED] == 239 && rgbaPixel[GREEN] == 60 && rgbaPixel[BLUE] == 153) {
                rgbaPixel[RED] = 255;
                rgbaPixel[GREEN] = 0;
                rgbaPixel[BLUE] = 0;
            }
        }
    }
    // 8.獲取畫布中的圖片對象
    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    UIImage *resultImage = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:UIImageOrientationUp];
    // 9.釋放對象
    // we're done with the context, color space, and pixels
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    free(pixels);
    CGImageRelease(imageRef);
    return resultImage;
}

// 2.亮度和對比度處理

/*
 對比度:    contrast -1~1
 亮度:     brightness -1~1
 亮度公式:Gray = 0.3*R + 0.59*G + 0.11*B
 */
- (UIImage*)getNewImageWithOldImage:(UIImage*)image
                           contrast:(CGFloat)contrast
                         brightness:(CGFloat)brightness {
    // 1.定義色值的索引位置
    const int RED =0;
    const int GREEN =1;
    const int BLUE =2;
    const int ALPHA =3;
    // 2.定義圖片的大小
    CGRect imageRect = CGRectMake(0,0, image.size.width* image.scale, image.size.height* image.scale);
    int width = imageRect.size.width;
    int height = imageRect.size.height;
    // 3.創(chuàng)建圖片像素數(shù)組的內(nèi)存大小
    uint32_t *pixels = (uint32_t*) malloc(width * height *sizeof(uint32_t));
    // 清空像素組里面的內(nèi)容
    memset(pixels,0, width * height *sizeof(uint32_t));
    // 4.創(chuàng)建色系對象
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    // 5.創(chuàng)建一個rgba像素的畫布對象,像素存放在pixels中
    // create a context with RGBA pixels
    CGContextRef context = CGBitmapContextCreate(pixels, width, height,8, width *sizeof(uint32_t), colorSpace,kCGImageAlphaPremultipliedLast);
    // 6.把圖片繪制到畫布上橙垢,并且同步到存放像素內(nèi)容的數(shù)組中
    // paint the bitmap to our context which will fill in the pixels array
    CGContextDrawImage(context,CGRectMake(0,0, width, height), [image CGImage]);

    // 7.設(shè)置亮度和對比度
    // 如果當(dāng)前亮度或者對比度發(fā)生變化時修改圖片參數(shù)
    if (contrast != 0 && brightness == 0) {
        // 01 當(dāng)前只修改了對比度
        float ta = 0, tr = 0, tg = 0, tb = 0;
        for(int y = 0; y < height; y++) {
            for(int x = 0; x < width; x++) {
                // 01 每一個像素點(diǎn)的顏色數(shù)組
                uint8_t *rgbaPixel = (uint8_t*) &pixels[y * width + x];
                ta = rgbaPixel[ALPHA];
                tr = rgbaPixel[RED];
                tg = rgbaPixel[GREEN];
                tb = rgbaPixel[BLUE];
                
                tr = (tr - 127.5) * arctan(contrast) + 127.5;
                tg = (tg - 127.5) * arctan(contrast) + 127.5;
                tb = (tb - 127.5) * arctan(contrast) + 127.5;
                
                rgbaPixel[RED] = clamp(tr);
                rgbaPixel[GREEN] = clamp(tg);
                rgbaPixel[BLUE] = clamp(tb);
            }
        }
    } else if (contrast == 0 && brightness != 0) {
        // 02 當(dāng)前只修改了亮度
        float ta = 0, tr = 0, tg = 0, tb = 0;
        for(int y = 0; y < height; y++) {
            for(int x = 0; x < width; x++) {
                // 01 每一個像素點(diǎn)的顏色數(shù)組
                uint8_t *rgbaPixel = (uint8_t*) &pixels[y * width + x];
                ta = rgbaPixel[ALPHA];
                tr = rgbaPixel[RED];
                tg = rgbaPixel[GREEN];
                tb = rgbaPixel[BLUE];
                
                tr = tr + 255 * brightness;
                tg = tg + 255 * brightness;
                tb = tb + 255 * brightness;
                
                rgbaPixel[RED] = clamp(tr);
                rgbaPixel[GREEN] = clamp(tg);
                rgbaPixel[BLUE] = clamp(tb);
            }
        }
    } else if (contrast != 0 && brightness != 0) {
        // 03 當(dāng)前對比度和亮度
        float ta = 0, tr = 0, tg = 0, tb = 0;
        for(int y = 0; y < height; y++) {
            for(int x = 0; x < width; x++) {
                // 01 每一個像素點(diǎn)的顏色數(shù)組
                uint8_t *rgbaPixel = (uint8_t*) &pixels[y * width + x];
                ta = rgbaPixel[ALPHA];
                tr = rgbaPixel[RED];
                tg = rgbaPixel[GREEN];
                tb = rgbaPixel[BLUE];
                
                tr = (tr - 127.5 * (1 - brightness)) * arctan(contrast) + 127.5 * (1 + brightness);
                tg = (tg - 127.5 * (1 - brightness)) * arctan(contrast) + 127.5 * (1 + brightness);
                tb = (tb - 127.5 * (1 - brightness)) * arctan(contrast) + 127.5 * (1 + brightness);
                rgbaPixel[RED] = clamp(tr);
                rgbaPixel[GREEN] = clamp(tg);
                rgbaPixel[BLUE] = clamp(tb);
            }
        }
    }
    
    
    // 8.獲取畫布中的圖片對象
    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    UIImage *resultImage = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:UIImageOrientationUp];
    // 9.釋放對象
    // we're done with the context, color space, and pixels
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    free(pixels);
    CGImageRelease(imageRef);
    return resultImage;
}

// 獲取對比度系數(shù)
float arctan(float value) {
    return  tan( (45 + 44 * value) / 180 * M_PI);
}

float clamp(float value) {
    return value > 255 ? 255 :(value < 0 ? 0 : value);
}

五垛叨、多張圖片合成視頻文件

1.有多張UIImage對象合成視頻文件

- (void)getVideoWithImages:(NSArray *)images 
{
    // 1.視頻輸出設(shè)置 
    NSError *error = nil;
    AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:kMoviePath] fileType:AVFileTypeMPEG4 error:&error];
    NSParameterAssert(videoWriter);
    // 2.視頻寫入設(shè)置
    NSDictionary *videoSettings = @{AVVideoCodecKey: AVVideoCodecH264, AVVideoWidthKey: [NSNumber numberWithInt:inRect.size.width], AVVideoHeightKey: [NSNumber numberWithInt:inRect.size.height]};
    AVAssetWriterInput* writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];        
    AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
    sourcePixelBufferAttributes:nil];
    NSParameterAssert(writerInput);
    NSParameterAssert([videoWriter canAddInput:writerInput]);
    [videoWriter addInput:writerInput];
    // 3.允許開始寫入視頻
    [videoWriter startWriting];
    [videoWriter startSessionAtSourceTime:kCMTimeZero];
    // 4.多張圖片寫入視頻文件
    int __block frame = 0;
    [writerInput requestMediaDataWhenReadyOnQueue:dispatch_queue_create("mediaInputQueue", NULL) usingBlock:^{
        @autoreleasepool {
            while ([writerInput isReadyForMoreMediaData]) {
                @autoreleasepool {
                    if ([self isRecording] == NO) {
                        [writerInput markAsFinished];
                        [videoWriter finishWritingWithCompletionHandler:^{
                            NSLog(@"Successfully closed video writer");
                            if (videoWriter.status == AVAssetWriterStatusCompleted) {
                                NSLog(@"成功");
                            } else {
                                NSLog(@"失敗");
                            }
                        }];
                        CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
                        break;
                    }
                    CGImageRef imageRef = [self getScreenRecordingImage];
                    CVPixelBufferRef buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:imageRef size:inRect.size];
                    dispatch_async(dispatch_get_global_queue(0, 0), ^{
                        if (buffer) {
                            if(![adaptor appendPixelBuffer:buffer withPresentationTime:CMTimeMake(frame, 20)])
                                NSLog(@"FAIL");
                            else
                                CFRelease(buffer);
                        }
                    });
                    frame++;
                    NSLog(@"%d",frame);
                }
            }
        }
    }];
}

更多分享:

Github:https://github.com/zhusiming/
GitBook:https://zhusiming.gitbooks.io/smbook/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嗽元,更是在濱河造成了極大的恐慌敛纲,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剂癌,死亡現(xiàn)場離奇詭異淤翔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)佩谷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門旁壮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谐檀,你說我怎么就攤上這事抡谐。” “怎么了桐猬?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵麦撵,是天一觀的道長。 經(jīng)常有香客問我溃肪,道長免胃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任乍惊,我火速辦了婚禮杜秸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘润绎。我一直安慰自己撬碟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布莉撇。 她就那樣靜靜地躺著呢蛤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪棍郎。 梳的紋絲不亂的頭發(fā)上其障,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機(jī)與錄音涂佃,去河邊找鬼励翼。 笑死,一個胖子當(dāng)著我的面吹牛辜荠,可吹牛的內(nèi)容都是我干的汽抚。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼伯病,長吁一口氣:“原來是場噩夢啊……” “哼造烁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤惭蟋,失蹤者是張志新(化名)和其女友劉穎苗桂,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體告组,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡煤伟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了惹谐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片持偏。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖氨肌,靈堂內(nèi)的尸體忽然破棺而出鸿秆,到底是詐尸還是另有隱情,我是刑警寧澤怎囚,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布卿叽,位于F島的核電站,受9級特大地震影響恳守,放射性物質(zhì)發(fā)生泄漏考婴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一催烘、第九天 我趴在偏房一處隱蔽的房頂上張望沥阱。 院中可真熱鬧,春花似錦伊群、人聲如沸考杉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽崇棠。三九已至,卻和暖如春丸卷,著一層夾襖步出監(jiān)牢的瞬間枕稀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工谜嫉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萎坷,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓沐兰,卻偏偏與公主長得像哆档,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子僧鲁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容