iOS UImage 與 RGB 裸數據的相互轉換

来源:http://www.cnblogs.com/psklf/archive/2017/11/09/7810484.html
-Advertisement-
Play Games

iOS UImage 與 RGB 裸數據的相互轉換 Touch the data of image in iOS Get data from a image 較簡單,根據已有的 image 的屬性,創建 CGBitmapContext, 這個 context 是帶有直接訪問的指針的。然後將 Imag ...


iOS UImage 與 RGB 裸數據的相互轉換

Touch the data of image in iOS

Get data from a image

較簡單,根據已有的 image 的屬性,創建 CGBitmapContext, 這個 context 是帶有直接訪問的指針的。然後將 Image 繪製到這個 context, 得到裸數據。

Code:

    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(srcImg.CGImage);
    CGColorSpaceRef colorRef = CGColorSpaceCreateDeviceRGB();

    float width = srcImg.size.width;
    float height = srcImg.size.height;

    // Get source image data
    uint8_t *imageData = (uint8_t *) malloc(width * height * 4);

    CGContextRef imageContext = CGBitmapContextCreate(imageData,
            width, height,
            8, static_cast<size_t>(width * 4),
            colorRef, alphaInfo);

    CGContextDrawImage(imageContext, CGRectMake(0, 0, width, height), srcImg.CGImage);
    CGContextRelease(imageContext);
    CGColorSpaceRelease(colorRef);

拿到指針就可以操作數據了。

需要註意的地方:alphaInfo, 通常我處理的圖像都是帶有透明度的,但是 RGBA 和 ARGB 都有遇到過,所以需要看清楚這個信息是哪一種,列舉如下:

typedef CF_ENUM(uint32_t, CGImageAlphaInfo) {
    kCGImageAlphaNone,               /* For example, RGB. */
    kCGImageAlphaPremultipliedLast,  /* For example, premultiplied RGBA */
    kCGImageAlphaPremultipliedFirst, /* For example, premultiplied ARGB */
    kCGImageAlphaLast,               /* For example, non-premultiplied RGBA */
    kCGImageAlphaFirst,              /* For example, non-premultiplied ARGB */
    kCGImageAlphaNoneSkipLast,       /* For example, RBGX. */
    kCGImageAlphaNoneSkipFirst,      /* For example, XRGB. */
    kCGImageAlphaOnly                /* No color data, alpha data only */
};

一般來說我們的工程都會打開一個png圖片壓縮的選項,所以我們拿到的 image 一般來說是 premultiplied 的,也就是說,RGB的值已經是和alpha值相乘的結果了,在 OpenGL 紋理操作的時候要註意。

Create a image from raw data

1) Create BitmapContext and get image from it

    size_t bitsPerComponent = 8;
    size_t bitsPerPixel = 32;
    size_t bytesPerRow = static_cast<size_t>(4 * outWidth);
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();

    // set the alpha mode RGBA
    CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;

    ////
    // This method is much simple and without coordinate flip
    // You can use this method either
    // but the UIGraphicsBeginImageContext() is much more modern.
    ////

    CGContextRef cgBitmapCtx = CGBitmapContextCreate(outData,
            static_cast<size_t>(outWidth),
            static_cast<size_t>(outHeight),
            bitsPerComponent,
            bytesPerRow,
            colorSpaceRef,
            bitmapInfo);

    CGImageRef cgImg = CGBitmapContextCreateImage(cgBitmapCtx);

    UIImage *retImg = [UIImage imageWithCGImage:cgImg];

    CGContextRelease(cgBitmapCtx);
    CGColorSpaceRelease(colorSpaceRef);
    free(outData);

主要方法就是 CGBitmapContextCreate 直接將數據地址 outData 作為初始化參數提供,這樣這個 context 就是帶有正確數據的了,然後就直接獲得 CGImage 了。

2) CGDataProvider --> CGImage --> UIImage

這個方法的思路就是直接使用 CGImageCreate() 函數直接創建 CGImage.

    size_t bitsPerComponent = 8;
    size_t bitsPerPixel = 32;
    size_t bytesPerRow = static_cast<size_t>(4 * outWidth);
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();

    // set the alpha mode RGBA
    CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, outData, outDataLength, NULL);

    CGImageRef imageRef = CGImageCreate(outWidth, outHeight,
            bitsPerComponent, bitsPerPixel, bytesPerRow,
            colorSpaceRef, bitmapInfo, provider,
            NULL, NO, renderingIntent);
    
    UIImage *retImage1 = [UIImage imageWithCGImage:imageRef];

創建 provider 的時候無需回調函數,故直接提供 NULL.

創建 CGImage 時需要提供詳細的配置參數,其中部分參數和創建 CGBitmapContext 相同,額外需要提供的就是預設參數以及不需要使用的特性比如 decode array 等等。得到 CGImageRef 後可以直接得到 UIImage 對象,但是我發現我的同事寫瞭如下一段代碼:

    UIGraphicsBeginImageContext(outSize);
    // the same: UIGraphicsBeginImageContextWithOptions(outSize, NO, 1.0f);

    CGContextRef cgCtx = UIGraphicsGetCurrentContext();
    CGContextSetBlendMode(cgCtx, kCGBlendModeCopy);

    CGContextDrawImage(cgCtx, CGRectMake(0.0, 0.0, outWidth, outHeight), imageRef);

    UIImage *retImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

這段代碼的功能是:創建CGContext 然後將 CGimage 繪製到當前的 Context 上面,再得到 UIImage.

基本可以認為是 [UIImage imageWithCGImage:imageRef] 我的不知道為什麼同事這樣寫,可能是這個方法是有什麼坑的,我暫時沒有遇到。所以我將這段代碼先記下來,留著以後用。

關於 UIGraphicsBeginImageContext() 方法,apple 的介紹如下:

iOS Note: iOS applications should use the function UIGraphicsBeginImageContextWithOptions instead of using the low-level Quartz functions described here. If your application creates an offscreen bitmap using Quartz, the coordinate system used by bitmap graphics context is the default Quartz coordinate system. In contrast, if your application creates an image context by calling the function UIGraphicsBeginImageContextWithOptions, UIKit applies the same transformation to the context’s coordinate system as it does to a UIView object’s graphics context. This allows your application to use the same drawing code for either without having to worry about different coordinate systems. Although your application can manually adjust the coordinate transformation matrix to achieve the correct results, in practice, there is no performance benefit to doing so.

上面所述的 low-level Quartz function 就是我們上面用的 CGBitmapContextCreate 這一類方法。所以用這個新的方法直接就將 創建好的 bitmapContext 綁定到當前狀態。仍然調用 CGContextDrawImage() 函數,將 CGImage 繪製到指定的 context 上面。然後再獲取 UIImage. 總的來說,這個和我們之前的那一套原理是一樣的,應該說這樣是更新式的做法,推薦的做法。

參考

Quartz 2D Programming Guide

How do I create a CGImage with RGB data?

Converting RGB data into a bitmap in Objective-C++ Cocoa

CGImage to UIImage doesn't work


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • relative/static: 包含塊為最近的塊級框,表單元格或行內塊祖先框的內容邊界構成 absolute: 包含塊為最近的最近的、position不是static的祖先元素 fixed: 包含塊為視窗,結合top | left | right | bottom,left等初始值為auto ...
  • 個人博客記錄:2017-11-09 png 32位無損壓縮演算法形成的圖片,主要用於logo小圖標和一些點綴的小圖像。放大縮小不會失真,質量好 jpeg,jpg 壓縮比例較高(可達到100:1,即壓縮一百倍),放大縮小失真。適用於比較大的圖片,省流量 gif 動態圖,(你懂得),適用於動畫效果。 ...
  • 效果圖展示: 原理很簡單,主要運用transform這個樣式,通過斜切和旋轉達成 html: css: 怎樣,是不是很簡單 ...
  • 在Web前端頁面實現圓角效果,CSS3幫你輕鬆實現,一個人人皆知的屬性 圓角邊框的繪製是Web頁面和Web應用程式中經常用來美化頁面效果的手法之一。今天,小編為大家介紹CSS3提供的可以將矩形變為圓角矩形的一個屬性 技術等級:中級 | 適合有一定的CSS基礎的人士閱讀。 希望收藏了這篇文章的你同時也 ...
  • 前言 需要用到圖形繪製,沒有找到完整的圖形繪製實現,所以自己實現了一個 - - 一、實現的功能 1、基於oop思想構建,支持坐標點、線條(由坐標點組成,包含方向)、多邊形(由多個坐標點組成)、圓形(包含圓心坐標點和半徑)等實體 2、原生JavaScript實現,不依賴任何第三方js庫和插件 3、多圖 ...
  • 我們平時在同域中請求頁面什麼的時候不會有這種情況,這種情況大多發生在移動端的跨域請求中發生的。 解決方法就是在服務端中加一層過濾HTTP請求的類型,把OPTION等不用的類型過濾掉。就是當請求為非 HTTP中的 GET 和 POST的時候就不執行下麵的代碼,這樣就可以只執行一次請求了。 在ASP.N ...
  • vue.js 一個簡單快捷的JS框架 vue.js 一個簡單快捷的JS框架 vue.js擁有簡單小巧的核心,漸進式技術棧,代碼簡單易學。 雙向綁定 什麼是雙向綁定? 雙向綁定 什麼是雙向綁定? Vue框架 很核心的功能就是雙向的數據綁定 ,雙向是指 HTML標簽數據綁定到Vue對象,另外反方向的數據 ...
  • 在Activity 的啟動過程中,調用ActivityThread 的handleResumeActivity 方法時,先得到一個與Activity 關聯的PhoneWindow 對象,然後通過PhoneWindow 來獲取DecorView。 PhoneWindow.java DecorView ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...