Brett
Brett

Reputation: 21

Drawing Pixels - Objective-C/Cocoa

I am trying to draw individual pixels in xcode to be outputted to the iphone. I do not know any OpenGL or Quartz coding but I do know a bit about Core Graphics. I was thinking about drawing small rectangles with width and height of one, but do not know how to implement this into code and how to get this to show in the view. Any help is greatly appreciated.

Upvotes: 0

Views: 6016

Answers (3)

hotpaw2
hotpaw2

Reputation: 70693

If you want to be able to draw pixels that are cumulatively added to some previously drawn pixels, then you will need to create your own bitmap graphics context, backed by your own bitmap memory. You can then set individual pixels in the bitmap memory, or draw short lines or small rectangles in your graphics context. To display your drawing context, first convert it to an CGImageRef. Then you can either draw this image to a subclassed UIView in the view's drawRect, or assign the image to the contents of the UIView's CALayer.

Look up: CGBitmapContextCreate and CGBitmapContextCreateImage in Apple's documentation.

ADDED:

I wrote up a longer explanation of why you might need to do this when drawing pixels in an iOS app, plus some source code snippets, on my blog: http://www.musingpaw.com/2012/04/drawing-in-ios-apps.html

Upvotes: 1

willc2
willc2

Reputation: 39671

For a custom UIView subclass that allows plotting dots of a fixed size and color:

// Make a UIView subclass  
@interface PlotView : UIView  

@property (nonatomic) CGContextRef context;  
@property (nonatomic) CGLayerRef drawingLayer; // this is the drawing surface

- (void) plotPoint:(CGPoint) point; //public method for plotting  
- (void) clear; // erases drawing surface

@end  

// implementation  
#define kDrawingColor ([UIColor yellowColor].CGColor)
#define kLineWeight (1.5)

@implementation PlotView  
@synthesize context = _context, drawingLayer = _drawingLayer;

- (id) initPlotViewWithFrame:(CGRect) frame; {  

    self = [super initWithFrame:frame];
    if (self) {
        // this is total boilerplate, it rarely needs to change
        self.backgroundColor = [UIColor clearColor];
        CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
        CGFloat width = frame.size.width;
        CGFloat height = frame.size.height;
        size_t bitsPerComponent = 8;
        size_t bytesPerRow = (4 * width);
        self.context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorspace, kCGImageAlphaPremultipliedFirst);
        CGColorSpaceRelease(colorspace);
        CGSize size = frame.size;
        self.drawingLayer = CGLayerCreateWithContext(self.context, size, NULL);
    }
    return self;  
}  

// override drawRect to put drawing surface onto screen
// you don't actually call this directly, the system will call it
- (void) drawRect:(CGRect) rect; {

    // this creates a new blank image, then gets the surface you've drawn on, and stamps it down
    // at some point, the hardware will render this onto the screen
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGImageRef image = CGBitmapContextCreateImage(self.context);
    CGRect bounds = [self bounds];
    CGContextDrawImage(currentContext, bounds, image);
    CGImageRelease(image);
    CGContextDrawLayerInRect(currentContext, bounds, self.drawingLayer);
}

// simulate plotting dots by drawing a very short line with rounded ends
// if you need to draw some other kind of shape, study this part, along with the docs
- (void) plotPoint:(CGPoint) point; {

    CGContextRef layerContext = CGLayerGetContext(self.drawingLayer); // get ready to draw on your drawing surface

    // prepare to draw
    CGContextSetLineWidth(layerContext, kLineWeight);
    CGContextSetLineCap(layerContext, kCGLineCapRound);
    CGContextSetStrokeColorWithColor(layerContext, kDrawingColor);

    // draw onto surface by building a path, then stroking it
    CGContextBeginPath(layerContext); // start

    CGFloat x = point.x;
    CGFloat y = point.y;
    CGContextMoveToPoint(layerContext, x, y);
    CGContextAddLineToPoint(layerContext, x, y);

    CGContextStrokePath(layerContext); // finish

    [self setNeedsDisplay]; // this tells system to call drawRect at a time of it's choosing
}

- (void) clear; {

CGContextClearRect(CGLayerGetContext(self.drawingLayer), [self bounds]);
[self setNeedsDisplay];
}

// teardown
- (void) dealloc; {  

    CGContextRelease(_context);  
    CGLayerRelease(_drawingLayer);  
    [super dealloc];
}

Upvotes: 3

Gordon
Gordon

Reputation: 1

All drawing needs to go into the - (void)drawRect:(CGRect)rect method. [self setNeedsDisplay] flags the code for a redraw. Problem is your redrawing nothing.

Upvotes: 0

Related Questions