iOS 获取一张图片(Bitmap)的点阵数据

位图(Bitmap)   位图图像(bitmap), 亦称为点阵图像或绘制图像,是由称作像素(图片元素)的单个点组成的。

RGB      位图颜色的一种编码方法,用红、绿、蓝三原色的光学强度来表示一种颜色。这是最常见的位图编码方法,可以直接用于屏幕显示

CMYK     位图颜色的一种编码方法,用青、品红、黄、黑四种颜料含量来表示一种颜色。常用的位图编码方法之一,可以直接用于彩色印刷。

Alpha通道    在原有的图片编码方法基础上,增加像素的透明度信息。图形处理中,通常把RGB三种颜色信息称为红通道、绿通道和蓝通道,相应的把透明度称为Alpha通道。多数使用颜色表的位图格式都支持Alpha通道。

色彩深度    色彩深度又叫色彩位数,即位图中要用多少个二进制位来表示每个点的颜色,是分辨率的一个重要指标。常用有1位(单色),2位(4色,CGA),4位(16色,VGA),8位(256色),16位(增强色),24位(真彩色)和32位等。色深8位及以上的位图还可以根据其中分别表示RGB三原色或CMYK四原色(有的还包括Alpha通道)的位数进一步分类,如16位位图图片还可分为R5G6B5,R5G5B5X1(有1位不携带信息),R5G5B5A1,R4G4B4A4等等。

BMP是一种与硬件设备无关的图像文件格式,使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BblP文件所占用的空间很大。BMP文件的图像深度可选1bit、4bit、8bit及24bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。

典型的BMP图像文件由三部分组成:位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息;位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息。

在iOS开发中使用的位图大部分是32位RGBA模式,以下是这种模式的简单图像处理。

首先我们需要知道什么是32位RGBA模式的位图。32位就表示一个这种模式位图的一个像素所占内存为32位,也就是4个字节的长度。R、G、B、A分别代表red,green,blue和alpha,也就是颜色组成的三原色与透明度值。RGBA每一个占用一个字节的内存。

代码部分

1,CGImageRef

CGImageRef CGImageCreate {

size_t width,//图片的宽度

size_t height,//图片的高度

size_t bitsPerComponent,//图片每个颜色的bits

size_t bitsPerPixel,//每一个像素占用的buts,15 位24位 32位等等

size_t  bytesPerRow,//每一行占用多少bytes 注意是bytes不是bits 1byte = 8bit

CGColorSpaceRef colorspace,//颜色空间,比如rgb

CGBitmapInfo bitmapInfo,//layout ,像素中bit的布局, 是rgba还是 argb

CGDataProviderRef provider,//数据源提供者,url或者内存..

const CGFloat decode[],//一个解码数组

boo lshouldInterpolate,//抗锯齿参数

CGColorRenderingIntent intent//图片渲染相关参数

}

2, 要得到BMP每个点RGB值,首先要得到每个点的像素数据 ,这里得到的是每个点的R,G,B,A 值组合起来的一个unsigned char *pixels类型的数据,代码如下:

unsigned char *pixels = calloc(picWidth * picHeight * 4, sizeof(unsigned char)); // 取图片首地址,准备用来存储数据的数组

    size_t bitsPerComponent = 8; // 每个像素元素位数为 8 bit,即 rgba 每位各 1 个字节

    size_t bytesPerRow = picWidth *4; //一个像素 4 个字节,则一行共 4 * width 个字节

    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); // 创建rgb颜色空间 这决定了输出颜色的编码是 RGB 还是其他(比如 YUV)

    CGContextRef context =

    CGBitmapContextCreate(pixels,

                          picWidth,

                          picHeight,

                          bitsPerComponent,

                          bytesPerRow,

                          space,

                          kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGContextDrawImage(context, CGRectMake(0, 0, picWidth, picHeight), image.CGImage);//将图片的数据写入上下文

//释放

    CGColorSpaceRelease(space);

    CGContextRelease(context);

3,项目中有几个因素:

一,数据极性为正极性时r,g,b值不变,为负极性时 r,g,b 值要取反。

二,因为项目中特技为连续左、右移时,左补点为0,其他特技需要左补点数为 X坐标对8取余。

三,获取的R,G,B数据拼接起来便是所要的数据,此数据与颜色和所需的红绿顺序有关,比如需要的是单色的,那 么只需要取 R即红的值即可,双色的可以使R+B,也可以是B+R等等......


代码:

//文字转图片生成的点阵数据

- (Byte *) getByteDataWithImage:(UIImage *)image {

    BOOL pol = self.dataPolarIndex == 1;

    NSInteger bit = 0 ;

    NSInteger addLeft = 0;

    NSInteger picWidth = image.size.width,picHeight = image.size.height;

    //  NSLog(@"图片款高---%ld----%ld",picWidth,picHeight);

    NSInteger shiftBit = 0;

    Byte r;

    Byte g;

    Byte b;

    NSMutableData *lastData = [[NSMutableData alloc]init];

    Byte          *lastByte;

    NSInteger x = _subtitleX;

    if (effectsRow2 == 1 || effectsRow2 == 2) {

        addLeft = 0;

    }else{

        addLeft = x % 8;

    }

    unsigned char *pixels = calloc(picWidth * picHeight * 4, sizeof(unsigned char)); // 取图片首地址//准备用来存储数据的数组

    size_t bitsPerComponent = 8; // 每个像素元素位数为 8 bit,即 rgba 每位各 1 个字节

    size_t bytesPerRow = picWidth *4; //一个像素 4 个字节,则一行共 4 * width 个字节

    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); // 创建rgb颜色空间 这决定了输出颜色的编码是 RGB 还是其他(比如 YUV)

    CGContextRef context =

    CGBitmapContextCreate(pixels,

                          picWidth,

                          picHeight,

                          bitsPerComponent,

                          bytesPerRow,

                          space,

                          kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGContextDrawImage(context, CGRectMake(0, 0, picWidth, picHeight), image.CGImage);//将图片的数据写入上下文


    CGColorSpaceRelease(space);

    CGContextRelease(context);


    NSInteger rgbSpace = ((picWidth + addLeft + 7)/8)  * picHeight;

    NSInteger grayLevel = 0;

    if ([[NSUserDefaults standardUserDefaults]integerForKey:@"selectGLRow"]) {

        grayLevel = [[NSUserDefaults standardUserDefaults]integerForKey:@"selectGLRow"];

    }else {

        grayLevel = 1;

    }

    for (NSInteger gray = 1; gray <= grayLevel; gray ++) {

        bit = 7 - (grayLevel - gray);

        unsigned char *rBytes = malloc(rgbSpace);

        unsigned char *gBytes = malloc(rgbSpace);

        unsigned char *bBytes = malloc(rgbSpace);

        NSInteger rgbStep = 0;

        for (NSInteger i = 0; i < picHeight; i ++) {

            r = 0;

            g = 0;

            b = 0;

            shiftBit = 8 - addLeft;

            for (NSInteger j = 0; j < picWidth; j ++) {

                r |= (((pixels[i*picWidth *4 +j*4 + 0] >> bit)&0x01) << (shiftBit -1));

                g |= (((pixels[i*picWidth *4 +j*4 + 1] >> bit)&0x01) << (shiftBit -1));

                b |= (((pixels[i*picWidth *4 +j*4 + 2] >> bit)&0x01) << (shiftBit -1));

                shiftBit --;

                if (shiftBit == 0 || (j==picWidth -1)) {

                    if (!pol) {

                        r = ~r;

                        g = ~g;

                        b = ~b;

                    }

                    rBytes[rgbStep] = r;

                    gBytes[rgbStep] = g;

                    bBytes[rgbStep] = b;


                    rgbStep++;

                    shiftBit = 8;

                    r = 0;

                    g = 0;

                    b = 0;

                }

            }

        }

        switch (self.colorIndex) {

            case 0:

                [lastData appendBytes:rBytes length:rgbSpace];

                break;

            case 1:

                switch (self.RGBOrder) {

                    case 0:

                        [lastData appendBytes:rBytes length:rgbSpace];

                        [lastData appendBytes:gBytes length:rgbSpace];

                        break;

                    case 1:

                        [lastData appendBytes:gBytes length:rgbSpace];

                        [lastData appendBytes:rBytes length:rgbSpace];

                        break;

                    default:

                        [lastData appendBytes:rBytes length:rgbSpace];

                        [lastData appendBytes:gBytes length:rgbSpace];

                        break;

                }

                break;

            case 2:

                switch (self.RGBOrder) {

                    case 2:

                        [lastData appendBytes:rBytes length:rgbSpace];

                        [lastData appendBytes:gBytes length:rgbSpace];

                        [lastData appendBytes:bBytes length:rgbSpace];

                        break;

                    case 3:

                        [lastData appendBytes:rBytes length:rgbSpace];

                        [lastData appendBytes:bBytes length:rgbSpace];

                        [lastData appendBytes:gBytes length:rgbSpace];

                        break;

                    case 4:

                        [lastData appendBytes:gBytes length:rgbSpace];

                        [lastData appendBytes:rBytes length:rgbSpace];

                        [lastData appendBytes:bBytes length:rgbSpace];

                        break;

                    case 5:

                        [lastData appendBytes:gBytes length:rgbSpace];

                        [lastData appendBytes:bBytes length:rgbSpace];

                        [lastData appendBytes:rBytes length:rgbSpace];

                        break;

                    case 6:

                        [lastData appendBytes:bBytes length:rgbSpace];

                        [lastData appendBytes:rBytes length:rgbSpace];

                        [lastData appendBytes:gBytes length:rgbSpace];

                        break;

                    case 7:

                        [lastData appendBytes:bBytes length:rgbSpace];

                        [lastData appendBytes:gBytes length:rgbSpace];

                        [lastData appendBytes:rBytes length:rgbSpace];

                        break;

                    default:

                        [lastData appendBytes:rBytes length:rgbSpace];

                        [lastData appendBytes:gBytes length:rgbSpace];

                        [lastData appendBytes:bBytes length:rgbSpace];

                        break;

                }

                break;

            default:

                [lastData appendBytes:rBytes length:rgbSpace];

                break;

        }

        free(rBytes);

        free(gBytes);

        free(bBytes);

        rBytes = NULL;

        bBytes = NULL;

        bBytes = NULL;

    }

    free(pixels);

    pixels = NULL;

    [[NSUserDefaults  standardUserDefaults] setInteger:lastData.length forKey:@"subTitleDataLength"];

    [[NSUserDefaults standardUserDefaults] synchronize];

    lastByte = (Byte *)[lastData bytes];

    return lastByte;

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,248评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,681评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,443评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,475评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,458评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,185评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,451评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,112评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,609评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,083评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,163评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,803评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,357评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,357评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,590评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,636评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,925评论 2 344

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,118评论 0 13
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,028评论 0 2
  • 前一阵子在梳理以前文章的时候,发现自己虽然总结了各种视音频应用程序,却还缺少一个适合无视音频背景人员学习的“最基础...
    视频音频小白阅读 1,993评论 1 3
  • 人老了,真的很孤单,怕失去,怕迷离,总是为一点芝麻点大的事吵闹哭泣,我看到真的很无能为力,就只能劝诉你,有我在,别...
    希雨啾阅读 225评论 0 1
  • (原为在知乎发布答案)原问题:郑渊洁让郑亚旗在家上学的教育方式,是否有可取之处? 一最近在帮我妹妹准备中考,偶尔会...
    如山清阅读 283评论 0 0