iOS_24_画画板

最终效果如下:

一、简单说明
 1、使用一个数组 strokesArr(笔画数组)记录所有笔画,数组中保存的是一个个的笔画字典,一个字典就是一个笔画,笔画字典中有三项:笔画的大小、颜色、pointsArrInOneStroke数组,(保存的是touch  begin时的落笔点和touch move过程中经过的点)

 2、绘制的时候,从strokesArr(笔画数组)里取出每一个字典(一个字典就是一个笔画),根据字典中笔画的大小、颜色、笔画所经过的点坐标(pointsArrInOneStroke数组),使用UIBezierPath类完成笔画绘制

 二、撤销和回撤
 一个笔画就是一个字典。
 撤销:
 使用abandonedStrokesArr (被丢弃的笔画数组)保存要撤销的笔画,即所有笔画数组中的最后一划,
 同时将 strokesArr 笔画数组中的最后一个元素删除。
 反之,重做:
 即将abandonedStrokesArr (被丢弃的笔画数组)中最后一个元素添加到所有笔画数组中,同时将(被丢弃的笔画数组)中的最后一个元素删除。

Main.storyboard

主控制器

Canvas类封装了画画的所有核心代码

方法列表

//
//  Canvas.h
//  24_Canvas画画板
//
//  Created by beyond on 14-8-26.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
/*
 一、简单说明
 1、使用一个数组 strokesArr(笔画数组)记录所有笔画,数组中保存的是一个个的笔画字典,一个字典就是一个笔画,笔画字典中有三项:笔画的大小、颜色、pointsArrInOneStroke数组,(保存的是touch  begin时的落笔点和touch move过程中经过的点)

 2、绘制的时候,从strokesArr(笔画数组)里取出每一个字典(一个字典就是一个笔画),根据字典中笔画的大小、颜色、笔画所经过的点坐标(pointsArrInOneStroke数组),使用UIBezierPath类完成笔画绘制

 二、撤销和回撤
 一个笔画就是一个字典。
 撤销:
 使用abandonedStrokesArr (被丢弃的笔画数组)保存要撤销的笔画,即所有笔画数组中的最后一划,
 同时将 strokesArr 笔画数组中的最后一个元素删除。
 反之,重做:
 即将abandonedStrokesArr (被丢弃的笔画数组)中最后一个元素添加到所有笔画数组中,同时将(被丢弃的笔画数组)中的最后一个元素删除。
 */

#import <UIKit/UIKit.h>
// 自定义的颜色选择控制器,点击之后,它会告诉代理,选中了什么颜色
@class ColorPickerController;

@interface Canvas : UIView
#pragma mark - 属性列表
// 标签,显示笔刷大小
@property (nonatomic,retain) IBOutlet UILabel *labelSize;
// 滑块 笔刷大小
@property (nonatomic,retain) IBOutlet UISlider *sliderSize;
// 三个按钮,分别是撤销、重做、清除
@property (nonatomic,retain) IBOutlet UIBarButtonItem *undoBtn;
@property (nonatomic,retain) IBOutlet UIBarButtonItem *redoBtn;
@property (nonatomic,retain) IBOutlet UIBarButtonItem *clearBtn;
// toolBar,目的是截图的时候,隐藏掉toolBar
@property (nonatomic,retain) IBOutlet UIToolbar *toolBar;

#pragma mark - 方法列表
// 初始化所有的准备工作
-(void) viewJustLoaded;
// 选择相册 被点击
-(IBAction) didClickChoosePhoto;
// 滑块滑动,设置笔刷大小
-(IBAction) setBrushSize:(UISlider*)sender;
// 撤销 被点击
-(IBAction) undo;
// 重做 被点击
-(IBAction) redo;
// 清除画布 被点击
-(IBAction) clearCanvas;
// 保存图片 被点击
-(IBAction) savePic;
// 颜色选择 被点击
- (IBAction) didClickColorButton;
// 重要~~开放给另一个控制器调用,它在调用代理时,会传入参数:即选择好的颜色
- (void) pickedColor:(UIColor*)color;
@end

核心代码

//
//  Canvas.h
//  24_Canvas画画板
//
//  Created by beyond on 14-8-26.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
/*

  这儿仅仅是做演示demo,直接让Canvas与控制器绑定,开始画画,监听事件

  如果,要更好的抽取出来,则需要创建一个模型类(model)来提供数据源(比如_strokesArr,_abandonedStrokesArr),供CanvasView显示

  UIView的setNeedsDisplay和setNeedsLayout方法
  首先两个方法都是异步执行的。而setNeedsDisplay会调用自动调用drawRect方法,这样可以拿到  UIGraphicsGetCurrentContext,就可以画画了。

  UIUserInterfaceIdiomPad   iPad上专用
 */

#import "Canvas.h"
#import "ColorPickerController.h"
#import "BeyondViewController.h"

@interface Canvas ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
{
    // 所有笔画
	NSMutableArray *_strokesArr;
    // 丢弃(撤销)的笔画
	NSMutableArray *_abandonedStrokesArr;
    // 当前笔刷颜色
	UIColor *_currentColor;
    // 当前的笔刷大小
	float currentSize;
    // 选中的图片
	UIImage *_pickedImg;
    // 截屏图片
	UIImage *_screenImg;
    // 自定义的 颜色选择控制器
	ColorPickerController *_colorPickerCtrl;
    // 相片选择器
	UIImagePickerController *_imagePickerCtrl;
}

@end

@implementation Canvas
#pragma mark - 生命周期方法
// 禁止多点触摸
-(BOOL)isMultipleTouchEnabled {
	return NO;
}
// 最重要的画图方法
- (void) drawRect: (CGRect) rect
{
    // 1.先把获取的图片,画到画布上
    [self drawPickedImgToCanvas];

    // 2.如果【笔画数组】有笔画字典,则按顺序将笔画取出,画到画布上
    [self drawStrokesArrToCanvas];

}

// 1.先把获取的图片,画到画布上
- (void)drawPickedImgToCanvas
{
	int width = _pickedImg.size.width;
	int height = _pickedImg.size.height;
	CGRect rectForImage = CGRectMake(0, 0, width, height);
	[_pickedImg drawInRect:rectForImage];
}
// 2.如果【笔画数组】有笔画字典,则按顺序将笔画取出,画到画布上
- (void)drawStrokesArrToCanvas
{
    // 如果【笔画数组】为空,则直接返回
	if (_strokesArr.count == 0) return;

    // 遍历【笔画数组】,取出每一个笔画字典,每一次迭代,画一个stroke
    for (NSDictionary *oneStrokeDict in _strokesArr)
    {
        // 取出点数组
        NSArray *pointsArr = [oneStrokeDict objectForKey:@"points"];
        // 取出颜色
        UIColor *color = [oneStrokeDict objectForKey:@"color"];
        // 取出笔刷尺寸
        float size = [[oneStrokeDict objectForKey:@"size"] floatValue];
        // 设置颜色
        [color set];
        // line segments within a single stroke (path) has the same color and line width
        // 画一个stroke, 一条接着一条,使用圆接头 round joint
        // 创建一个贝塞尔路径
        UIBezierPath* bezierPath = [UIBezierPath bezierPath];
        // 点数组 中的第一个,就是 起点
        CGPoint startPoint = CGPointFromString([pointsArr objectAtIndex:0]);
        // 将路径移动到 起点
        [bezierPath moveToPoint:startPoint];
        // 遍历点数组,将每一个点,依次添加到 bezierPath
        for (int i = 0; i < (pointsArr.count - 1); i++)
        {
            // 依次取出下一个点
            CGPoint pointNext = CGPointFromString([pointsArr objectAtIndex:i+1]);
            // 添加到路径
            [bezierPath addLineToPoint:pointNext];
        }
        // 设置线宽
        bezierPath.lineWidth = size;
        // 线连接处为 圆结头
        bezierPath.lineJoinStyle = kCGLineJoinRound;
        // 线两端为 圆角
        bezierPath.lineCapStyle = kCGLineCapRound;
        // 调用路径的方法 画出一条线
        [bezierPath stroke];
    }
}
// 重要~~~初始化所有东东
-(void) viewJustLoaded {
    // 1.初始化颜色选择控制器
    [self addColorPickerCtrl];

	// 2.初始化【相片选择器】
    [self addUIImagePickerCtrl];

    // 3.其他成员初始化
    // 【笔画数组】
	_strokesArr = [NSMutableArray array];
    // 【被丢弃的笔画数组】
	_abandonedStrokesArr = [NSMutableArray array];
    // 笔画大小
	currentSize = 5.0;
    // toolBar上笔画标签显示文字
	self.labelSize.text = @"Size: 5";
    // 设置笔刷 黑色
	[self setStrokeColor:[UIColor blackColor]];

    // 4.设置重做、撤销、清空三个按钮的状态
    [self updateToolBarBtnStatus];
}

// 1.初始化颜色选择控制器
- (void)addColorPickerCtrl
{
    // 1.添加【颜色选择控制器】ColorPickerController,因为要添加到主控制器中
    BeyondViewController *mainVC = [BeyondViewController sharedBeyondViewController];
	// 初始化自己封装的颜色选择控制器,并设置好代理,目的是颜色设置好了之后,回调告诉当前的canvas画布
	_colorPickerCtrl = [[ColorPickerController alloc] init];
	_colorPickerCtrl.pickedColorDelegate = self;
    // 控制器成为父子关系,视图也成为父子关系
    [mainVC addChildViewController:_colorPickerCtrl];
    [mainVC.view addSubview:_colorPickerCtrl.view];
    // 暂时隐藏【颜色选择控制器】,只有在点击了ToolBar上面的按钮时候,才显示出来
    _colorPickerCtrl.view.hidden = YES;
}
// 2.初始化【相片选择器】
- (void)addUIImagePickerCtrl
{
	if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
		_imagePickerCtrl = [[UIImagePickerController alloc] init];
		_imagePickerCtrl.delegate = self;
		_imagePickerCtrl.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        // 2) 设置允许修改
        // [_imagePickerCtrl setAllowsEditing:YES];
	}
}
// 3.自定义方法,设置 撤销、重做、清空三个按钮的可点击状态
- (void)updateToolBarBtnStatus
{

    _redoBtn.enabled = _abandonedStrokesArr.count > 0;
    _undoBtn.enabled = _strokesArr.count > 0;
    _clearBtn.enabled = _strokesArr.count > 0;

}
#pragma mark - 控件连线方法
// 滑块滑动
- (IBAction)setBrushSize:(UISlider*)sender
{
	currentSize = sender.value;
	self.labelSize.text = [NSString stringWithFormat:@"Size: %.0f",sender.value];
}
// 撤销按钮点击事件
-(IBAction) undo {
    // 如果笔画数组中有笔画字典
	if ([_strokesArr count]>0) {
        // 最后一个笔画字典,即,被丢弃的笔画字典
		NSMutableDictionary* abandonedStrokeDict = [_strokesArr lastObject];
        // 将最后一个笔画字典,添加到被丢弃的笔画字典数组里面保存,以供drawRect
		[_abandonedStrokesArr addObject:abandonedStrokeDict];
        // 从所有笔画数组中移除掉最后一笔
		[_strokesArr removeLastObject];
        // 重新调用drawRect进行绘制
		[self setNeedsDisplay];
	}

    // 2.设置重做、撤销、清空三个按钮的状态
    [self updateToolBarBtnStatus];
}
// 重做
-(IBAction) redo {
    // 如果 被丢弃的笔画数组,里面有值
	if ([_abandonedStrokesArr count]>0) {
        // 取出最后一个被仍进来的 笔画字典,(即最先书写的,而且是在撤销的操作里面,最后被添加到【被丢弃的笔画数组】)
		NSMutableDictionary* redoStrokeDict = [_abandonedStrokesArr lastObject];
        // 将需要重画的笔画字典,添加到【所有笔画数组】中
		[_strokesArr addObject:redoStrokeDict];
        // 并且,从【被丢弃的笔画数组】中移除,该笔画字典
		[_abandonedStrokesArr removeLastObject];
        // 重新调用drawRect进行绘制
		[self setNeedsDisplay];
	}

    // 2.设置重做、撤销、清空三个按钮的状态
    [self updateToolBarBtnStatus];
}
// 清空画布,只需清空【所有笔画数组】和【被丢弃的笔画数组】
-(IBAction) clearCanvas {
    // 建议不要将选择出来的背景图片清空,只清空没写好的笔画算了
	// _pickedImg = nil;
	[_strokesArr removeAllObjects];
	[_abandonedStrokesArr removeAllObjects];
    // 重新调用drawRect进行绘制
	[self setNeedsDisplay];

    // 2.设置重做、撤销、清空三个按钮的状态
    [self updateToolBarBtnStatus];
}
// 保存图片
-(IBAction) savePic {
	// 暂时移除 工具条
	//[_toolBar removeFromSuperview];

    // 截图代码
    // 1,开启上下文
	UIGraphicsBeginImageContext(self.bounds.size);
    // 2.将图层渲染到上下文
	[self.layer renderInContext:UIGraphicsGetCurrentContext()];
    // 开启上下文,使用参数之后,截出来的是原图(YES  0.0 质量高)
    //UIGraphicsBeginImageContextWithOptions(self.frame.size, YES, 0.0);
    // 3.从上下文中取出图片
	_screenImg = UIGraphicsGetImageFromCurrentImageContext();
    // 4.关闭上下文
	UIGraphicsEndImageContext();

	// 重新添加 工具条,并置最上方
	//[self addSubview:_toolBar];
	//[self bringSubviewToFront:self.labelSize];

	// 调用自定义方法,保存截屏到相册
	[self performSelector:@selector(saveToPhoto) withObject:nil afterDelay:0.0];
}
// 自定义方法,保存截屏到相册
-(void) saveToPhoto {
	// 一句话,写到相册
	UIImageWriteToSavedPhotosAlbum(_screenImg, nil, nil, nil);

	// UIAlertView 提示成功
	UIAlertView* alertView= [[UIAlertView alloc] initWithTitle:nil message:@"Image Saved" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
	[alertView show];

}

// 点击选择颜色按钮
- (IBAction) didClickColorButton {
    // 显示或隐藏 自己的【颜色选择控制器】
    _colorPickerCtrl.view.hidden = !_colorPickerCtrl.view.hidden;

}
// 当_colorPickerCtrl选择颜色完毕,会调用代理 的本方法
- (void) pickedColor:(UIColor*)color {
    // 将【颜色选择控制器】,回调的颜色,设置到控件上,并隐藏 【颜色选择控制器】
	[self setStrokeColor:color];
    _colorPickerCtrl.view.hidden = !_colorPickerCtrl.view.hidden;

}
// 重要,设置笔刷 新的颜色
-(void) setStrokeColor:(UIColor*)newColor
{
	_currentColor = newColor;
}

// 点击,选择相片按钮
-(IBAction) didClickChoosePhoto {
    // 展现,相片选择控制器
    [self addSubview:_imagePickerCtrl.view];
}
#pragma mark - imagePicker代理方法
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    // 必须手动,关闭照片选择器
    [picker.view removeFromSuperview];
    // 从info字典得到编辑后的照片【UIImagePickerControllerEditedImage】
    _pickedImg = [info valueForKey:@"UIImagePickerControllerOriginalImage"];
    // 将图片画到画板上去
    [self setNeedsDisplay];
}

// 【相片选择器】的代理方法,点击取消时,也要隐藏相片选择器
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [_imagePickerCtrl.view removeFromSuperview];
}

#pragma mark - 核心代码,重要~~~画布上手势处理
// 手势开始(画笔落下)
// 开始一个新的字典,为每一笔,包括点 和 颜色
// Start new dictionary for each touch, with points and color
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event
{

    // 一个笔画中的所有点,触摸开始时的【起点】
	NSMutableArray *pointsArrInOneStroke = [NSMutableArray array];
	NSMutableDictionary *strokeDict = [NSMutableDictionary dictionary];
	[strokeDict setObject:pointsArrInOneStroke forKey:@"points"];
    // 笔的颜色
	[strokeDict setObject:_currentColor forKey:@"color"];
    // 笔的大小
	[strokeDict setObject:[NSNumber numberWithFloat:currentSize] forKey:@"size"];

    // 落笔点
	CGPoint point = [[touches anyObject] locationInView:self];
	[pointsArrInOneStroke addObject:NSStringFromCGPoint(point)];

	[_strokesArr addObject:strokeDict];
}

// 将每一个点添加到 点数组
// Add each point to points array
- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event
{
    // 移动后的一个点
	CGPoint point = [[touches anyObject] locationInView:self];
    // 前一个点
	CGPoint prevPoint = [[touches anyObject] previousLocationInView:self];
    // 字典中先前的点数组
	NSMutableArray *pointsArrInOneStroke = [[_strokesArr lastObject] objectForKey:@"points"];
    // 在后面追加 新的点
	[pointsArrInOneStroke addObject:NSStringFromCGPoint(point)];

	CGRect rectToRedraw = CGRectMake(									 ((prevPoint.x>point.x)?point.x:prevPoint.x)-currentSize,									 ((prevPoint.y>point.y)?point.y:prevPoint.y)-currentSize,									 fabs(point.x-prevPoint.x)+2*currentSize,									 fabs(point.y-prevPoint.y)+2*currentSize									 );
	[self setNeedsDisplayInRect:rectToRedraw];
}

// 手势结束(画笔抬起)
// Send over new trace when the touch ends
- (void) touchesEnded:(NSSet *) touches withEvent:(UIEvent *) event
{
	[_abandonedStrokesArr removeAllObjects];

    // 2.设置重做、撤销、清空三个按钮的状态
    [self updateToolBarBtnStatus];

}

@end

颜色选择控制器

ColorPickerController

//
//  ColorPickerController.h
//  24_Canvas画画板
//
//  Created by beyond on 14-8-26.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ColorPickerController : UIViewController 

#pragma mark - 属性列表
// xib上的imgView
@property (nonatomic,retain) IBOutlet UIImageView *imgView;
// 代理用weak
@property (weak) id pickedColorDelegate;

#pragma mark - 方法列表
// 核心,根据位图引用 创建基于该位图的上下文对象
- (CGContextRef) createARGBBitmapContextFromImage:(CGImageRef)inImage;
// 核心,根据触摸点,从上下文中取出对应位置像素点的颜色值
- (UIColor*) getPixelColorAtLocation:(CGPoint)point;

@end

核心代码

//
//  ColorPickerController.m
//  24_Canvas画画板
//
//  Created by beyond on 14-8-26.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "ColorPickerController.h"
#import "Canvas.h"
@implementation ColorPickerController

#pragma mark - 点击结束
- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {

	UITouch* touch = [touches anyObject];
    // tap点击的位置
	CGPoint point = [touch locationInView:self.imgView];

    // 1.调用自定义方法,从【点】中取颜色
	UIColor *selectedColor = [self getPixelColorAtLocation:point];
    // 2.告诉代理,解析出来的颜色
	[_pickedColorDelegate pickedColor:selectedColor];
}

// 核心代码:关于下面两个方法更多的详细资料,敬请查阅【iOS Developer Library 】
#pragma mark - 核心代码,将图片写入内存,再依据【点】中取颜色
- (UIColor *) getPixelColorAtLocation:(CGPoint)point
{
	UIColor *color = nil;
    // 得到取色图片的引用
	CGImageRef colorImage = _imgView.image.CGImage;

	// Create off screen bitmap context to draw the image into. Format ARGB is 4 bytes for each pixel: Alpa, Red, Green, Blue

    // 调用自定义方法:从_imgView里面的image的引用,创建并返回对应的上下文
	CGContextRef contexRef = [self createARGBBitmapContextFromImage:colorImage];
    // 如果创建该图片对应的上下文失败
	if (contexRef == NULL){
        NSLog(@"取色图片--创建对应的上下文失败~");
        return nil;
    }
	// 准备将【取色图片】写入刚才创建出来的上下文
    size_t w = CGImageGetWidth(colorImage);		// problem!
	size_t h = CGImageGetHeight(colorImage);
	CGRect rect = {{0,0},{w,h}};
    log_rect(rect)
    // 调试输出rect:--{{0, 0}, {225, 250}}

    int bytesPerRow = CGBitmapContextGetBytesPerRow(contexRef);
    log_int(bytesPerRow) //调试输出int:--900

	// Draw the image to the bitmap context. Once we draw, the memory
	// allocated for the context for rendering will then contain the
	// raw image data in the specified color space.
    // 将位图写入(渲染)已经分配好的内存区域
	CGContextDrawImage(contexRef, rect, colorImage);

    // 得到位图上下文 内存数据块的首地址,用指针记住,作为基地址
	unsigned char* dataPoint = CGBitmapContextGetData (contexRef);
    NSLog(@"----首地址,指针%p",dataPoint);
    // ----首地址,指针0x8b3f000

	if (dataPoint != NULL) {
		//offset 即:根据触摸点的xy,定位到位图内存空间中的一个特定像素
		//4 的意思是每一个像素点,占4个字节
        // w是每一行所有点的总数
        // 根据所在行,所在列,算出在内存块中的偏移地址,然后乘以4,因为每一个点在内存中占四个字节
		int offset = 4*((w*round(point.y))+round(point.x));
        // alpha 为内存基地址+偏移地址
		int alpha =  dataPoint[offset];
        // red 为内存基地址+偏移地址+1   其他类似
		int red = dataPoint[offset+1];
		int green = dataPoint[offset+2];
		int blue = dataPoint[offset+3];

		NSLog(@"偏移地址: %i colors: RGBA %i %i %i  %i",offset,red,green,blue,alpha);
        // offset: 150908 colors: RGB A 255 0 254  255

        // 根据RGBA 生成颜色对象
		color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)];
	}

	// 操作完成后,释放上下文对象
	CGContextRelease(contexRef);
	// 从内存中释放掉 加载到内存的图像数据
	if (dataPoint) {
        free(dataPoint);
    }

	return color;
}
// 自定义方法2:通过_imgView里面的image的引用,创建并返回对应的上下文
- (CGContextRef) createARGBBitmapContextFromImage:(CGImageRef) inImage
{

    // 要创建的上下文
	CGContextRef    context = NULL;
    // 色彩空间
	CGColorSpaceRef colorSpace;
    // 位图数据在内存空间的首地址
	void *          bitmapData;
    // 每一行的字节数
	int             bitmapBytesPerRow;
    // 图片总的占的字节数
	int             bitmapByteCount;

	// 得到图片的宽度和高度,将要使用整个图片,创建上下文
	size_t pixelsWide = CGImageGetWidth(inImage);
	size_t pixelsHigh = CGImageGetHeight(inImage);

	// 每一行占多少字节. 本取色图片中的每一个像素点占4个字节;
    // 红 绿 蓝 透明度 各占一个字节(8位  取值范围0~255)
    // 每一行的字节数,因为每一个像素点占4个字节(包含RGBA)(其中一个R就是一个字节,占8位,取值是2的8次方 0~255)
	bitmapBytesPerRow   = (pixelsWide * 4);
    // 图片总的占的字节数
	bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);

	// 使用指定的 色彩空间(RGB)
	colorSpace = CGColorSpaceCreateDeviceRGB();
	if (colorSpace == NULL)
	{
		fprintf(stderr, "创建并分配色彩空间 出错\n");
		return NULL;
	}

	// This is the destination in memory
	// where any drawing to the bitmap context will be rendered.
    // 为取色图片数据  分配所有的内存空间
    // 所有画到取色图片上下文的操作,都将被渲染到此内存空间
	bitmapData = malloc( bitmapByteCount );
	if (bitmapData == NULL)
	{
		fprintf (stderr, "内存空间分配失败~");
		CGColorSpaceRelease( colorSpace );
		return NULL;
	}

	// 创建位图上下文. 使用 pre-multiplied ARGB, ARGB中的每一个成员都占8个bit位,即一字节,一个像素共占4个字节
	// 无论原取色图片的格式是什么(CMYK或Grayscale),都将通过CGBitmapContextCreate方法,转成指定的ARGB格式
	context = CGBitmapContextCreate (bitmapData,
									 pixelsWide,
									 pixelsHigh,
									 8,      // bits per component
									 bitmapBytesPerRow,
									 colorSpace,
                                    kCGImageAlphaPremultipliedFirst);
	if (context == NULL)
	{
		free (bitmapData);
		fprintf (stderr, "位图上下文创建失败~");
	}

	// 在返回上下文之前 必须记得释放 色彩空间
	CGColorSpaceRelease( colorSpace );

	return context;
}

@end
时间: 2024-10-09 05:20:47

iOS_24_画画板的相关文章

iOS_24_画画板(含取色板)

终于效果例如以下: 一.简单说明 1.使用一个数组 strokesArr(笔画数组)记录全部笔画.数组中保存的是一个个的笔画字典,一个字典就是一个笔画.笔画字典中有三项:笔画的大小.颜色.pointsArrInOneStroke数组,(保存的是touch begin时的落笔点和touch move过程中经过的点) 2.绘制的时候,从strokesArr(笔画数组)里取出每个字典(一个字典就是一个笔画).依据字典中笔画的大小.颜色.笔画所经过的点坐标(pointsArrInOneStroke数组)

android96 内存创建图片副本,画画板

package com.itheima.copy; import android.os.Bundle; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; imp

2015年第一篇:Android 画画板

其实画画板这个东西,很多地方都用的到,比如:在qq里面有一个随手涂鸦的画画板,电脑里面画图工具,ps等,这些都是用到的画画板,今天我实现了一个小小的画画板,分享给大家,希望能对你们有所帮助. 1.原理分析:(很简单) 1.当用户触摸到屏幕的时候,开始画画 2.当用户移动的时候,画画的开始位置和结束位置用线连接起来 3.当用户手离开屏幕的时候,也就完成了画画 2.先上效果图: 3.示例源码 package com.zengtao.demo; import java.io.File; import

画画板

#画画板(掌握) >记录用户触摸事件的XY坐标,绘制直线 * 给ImageView设置触摸侦听,得到用户的触摸事件,并获知用户触摸ImageView的坐标 iv.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub switch (event.getAction()) {

iOS 使用UIBezierPath类实现随手画画板

这篇文章介绍一下如何通过这个类实现一个简单的随手画画板的简单程序demo,功能包括:划线(可以调整线条粗细,颜色),撤销笔画,回撤笔画,清除画布,橡皮擦.当然也可以扩展其他的功能. 一.首先看看实现划线部分的关键代码吧! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 - (void) drawRect: (CGRect) rect {

Android小应用-----画画板

public class MainActivity extends Activity { private ImageView iv; float startX = 0; float startY = 0; //获得一个可以被bitmap Bitmap bitmap = Bitmap.createBitmap(400, 400,Bitmap.Config.ARGB_8888); //创建画布 Canvas canvas = new Canvas(bitmap); //创建画笔 Paint pain

iOS开发-高级UI-小应用画画板

画画板1.搭建界面(3个按钮,1个View) 2.为重写touchesBegan:等方法,需要自定义一个View,新建一个View,名为NJView,然后在故事板将这个View的Class设置为NJView 3.在NJView.m中重写方法 //开始触摸-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ //1.获取手指对应UITouch对象 UITouch *touch = [touches anyObject]:

(素材源码)猫猫学IOS(三十四)UI之Quartz2D画画板的实现

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 源码:http://download.csdn.net/detail/u013357243/8666923 效果: 代码: NYView NYView.h // // NYView.h // 画画板 // // Created by apple on 15-5-6. // Copyright (c) 2015年 znycat.

canvas画画板

制作一个画画板,有清屏有橡皮擦有画笔可以换颜色 style样式 <head> <meta charset="UTF-8"> <title>画画板</title> <style> body{ background-color:#ccc; } .control-bar{ vertical-align:top; display:inline-block; } </style> </head> html结构 &