NSImage *outImage;
NSImage *inputImage = [NSImage imageNamed:@"zhangsan.jpg"];
int m_nWidth = inputImage.size.width;
int m_nHeight = inputImage.size.height;
//NSImage转cv图
cv::Mat mat_pt = cv::Mat(m_nHeight, m_nWidth, CV_8UC4);
memcpy(mat_pt.data, [inputImage RGBAData],
sizeof(unsigned char) * m_nWidth * m_nHeight * 4);
//写在cv图上
cv::Point point(10.0,10.0);
float texSize = m_nWidth * m_nHeight *0.0000004;
cv::putText(mat_pt, std::to_string(10), point,
cv::FONT_HERSHEY_DUPLEX, texSize, cv::Scalar(255, 0, 255), 2,
cv::LINE_AA);
//cv图转NSImage
unsigned char* tempData = new unsigned char[m_nWidth * m_nHeight * 4];
memcpy(tempData, mat_pt.data,
sizeof(unsigned char) * m_nWidth * m_nHeight * 4);
mat_pt.release();
outImage = [NSImage imageWithRGBAData:tempData withWidth:m_nWidth withHeight:m_nHeight];
[ self.m_imageView setImage:outImage];
其中,RGBAData
-(unsigned char*)RGBAData{
//【1】NSImage创建CGImageRef
struct CGImageSource *source=CGImageSourceCreateWithData((__bridge CFDataRef)[self TIFFRepresentation],NULL);//创建从Core Foundation数据对象读取的图像源
NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanFalse, (id)kCGImageSourceShouldCache,
(id)kCFBooleanTrue, (id)kCGImageSourceShouldAllowFloat,
nil];//创建字典
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, 0, (CFDictionaryRef)options);//为与图像源中指定索引关联的图像数据创建CGImage对象
//【2】由CGImageRef创建CGContextRef
CGContextRef context = NULL;//Quartz 2D绘图环境,图形上下文
CGColorSpaceRef colorSpace;//指定如何解释显示的颜色值
uint32_t *bitmapData1;//图像数据
size_t bitsPerPixel = 32;//32位图
size_t bitsPerComponent = 8;//8位,0-255
size_t bytesPerPixel = bitsPerPixel / bitsPerComponent;//4通道
size_t width = CGImageGetWidth(imageRef);//以像素为单位,位图图像(或蒙版)的宽度
size_t height = CGImageGetHeight(imageRef);//高度
size_t bytesperRow = width * bytesPerPixel;
size_t bufferLength = bytesperRow * height;
//(1)分配设备颜色空间
colorSpace = CGColorSpaceCreateDeviceRGB();
if(!colorSpace) {
NSLog(@"Error allocating color space RGB\n");//颜色空间没有分配成功
return NULL;
}
//(2)为image data分配内存
bitmapData1 = (uint32_t *)malloc(bufferLength);
if(!bitmapData1) {
NSLog(@"Error allocating memory for bitmap\n");
CGColorSpaceRelease(colorSpace);
return NULL;
}
//(3)创建bitmap 的上下文context
context=CGBitmapContextCreate(bitmapData1,
width,
height,
bitsPerComponent,
bytesperRow,
colorSpace,
kCGImageAlphaPremultipliedLast);//RGBA
if(!context) {
free(bitmapData1);
NSLog(@"picProcessing::newBitmapRGBA8ContextFromImage:Bitmap context not created");
}
CGColorSpaceRelease(colorSpace);//释放颜色空间
//(4)获取CGImageRef的宽高,并将CGImageRef画到CGContextRef中,以获取rawdata
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);//将当前的填充颜色设置为DeviceRGB颜色空间中的值
CGContextFillRect(context, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height));//使用当前图形状态下的填充颜色绘制提供的矩形中包含的区域
unsigned long imageWidth = CGImageGetWidth(imageRef);
unsigned long imageHeight = CGImageGetHeight(imageRef);
CGRect imgRect = CGRectMake(0, 0, imageWidth, imageHeight);
CGContextDrawImage(context, imgRect, imageRef);//将图像绘制到图形上下文中。
unsigned char * bitmapData = (unsigned char * )CGBitmapContextGetData(context);//(5)获取CGContextRef中的rawdata的指针
unsigned char array[256][256] = {0};
for (int j=1; j<256; j++)
{
for (int i=0; i<256; i++)
{
array[j][i] = fmin(fmax(0.0f,(j+i-255)*255.0/i+0.5),255.0f);
}
}
GLubyte* alphaData = (GLubyte*) calloc(width * height, sizeof(GLubyte));
CGContextRef alphaContext = CGBitmapContextCreate(alphaData, width, height, 8, width, NULL, kCGImageAlphaOnly);
CGContextDrawImage(alphaContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), imageRef);
//(5)将image的数据绘制进bitmap context
CGContextRelease(alphaContext);
GLubyte* pDest = bitmapData;
GLubyte* alphaTemp = alphaData;
for (int j=0; j<height; j++)
{
for (int i=0; i<width; i++)
{
//自己反计算回原来的alpha值
pDest[0] = array[pDest[0]][alphaTemp[0]];
pDest[1] = array[pDest[1]][alphaTemp[0]];
pDest[2] = array[pDest[2]][alphaTemp[0]];
pDest[3] = alphaTemp[0];
pDest += 4;
alphaTemp++;
}
}
free(alphaData);
return bitmapData;
}
其中,imageWithRGBAData
+ (NSImage*) imageWithRGBAData:(unsigned char*)data withWidth:(int) width withHeight:(int) height{
//根据bitmap指针创建CGContextRef
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, width * height * 4, NULL);
size_t bitsPerComponent = 8;
size_t bitsPerPixel = 32;
//size_t bytesPerRow = 4 * imageWidth;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
if(colorSpaceRef == NULL) {
NSLog(@"Error allocating color space");
CGDataProviderRelease(provider);
}
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef iref = CGImageCreate(width,
height,
bitsPerComponent,
bitsPerPixel,
width * 4,
colorSpaceRef,
bitmapInfo,
provider, // data provider
NULL, // decode
YES, // should interpolate
renderingIntent);
uint32_t* pixels = (uint32_t*)malloc(width * height * 4);
if(pixels == NULL) {
NSLog(@"Error: Memory not allocated for bitmap");
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpaceRef);
CGImageRelease(iref);
}
CGContextRef context = CGBitmapContextCreate(pixels,
width,
height,
bitsPerComponent,
width * 4,
colorSpaceRef,
bitmapInfo);
if(context == NULL) {
NSLog(@"Error context not created");
free(pixels);
}
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), iref);
// 根据这个位图context中的像素数据创建一个Quartz image对象
CGImageRef quartzImage = CGBitmapContextCreateImage(context);
// 用Quartz image创建一个NSImage对象image
CGSize size = CGSizeMake(width, height);
NSImage *image = [[NSImage alloc] initWithCGImage:quartzImage size:size];
return image;
}