Drawing UIImage using CGBitmapContextCreate - Full Size Image for Texture - iOS

9.4k views Asked by At

I am using the below code to draw a UIImage. I am using some vertices to draw, in this case, a square :

- (UIImage *)drawTexture : (NSArray *)verticesPassed {

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();

    CGContextRef con = CGBitmapContextCreate(NULL,
                                                               1000,
                                                               1000,
                                                               8,
                                                               0,
                                                               rgbColorSpace,
                                                               kCGImageAlphaPremultipliedFirst);

    CGColorSpaceRelease(rgbColorSpace);

    CGContextSetLineWidth(con, 10);

    Line * start = [verticesPassed objectAtIndex:0];
    StandPoint * startPoint = start.origin;

    CGContextMoveToPoint(con, [startPoint.x floatValue], [startPoint.y floatValue]);

    for (Line * vertice in verticesPassed) {
        StandPoint * origin = vertice.origin;
        CGContextAddLineToPoint(con, [origin.x floatValue], [origin.y floatValue]);
        NSLog(@"Texutre point is %f %f", [origin.x floatValue], [origin.y floatValue]);
    }

    CGContextSetFillColorWithColor(con, [UIColor greenColor].CGColor);

    CGContextFillPath(con);

    [self drawText:con startX:250 startY:200 withText:standName];
    [self drawText:con startX:250 startY:150 withText:standNumber];


    CGImageRef cgImage = CGBitmapContextCreateImage(con);

    UIImage *newImage = [[UIImage alloc]initWithCGImage:cgImage];

    NSLog(@"Size is %f", newImage.size.height);

    return newImage;

}

The vertices for my square are :

Texutre point is 667.000000 379.000000
Texutre point is 731.000000 379.000000
Texutre point is 731.000000 424.000000
Texutre point is 667.000000 424.000000

The problem is that in a 1000x1000 context this obviously draws a very small shape in the top right of the context.

As I want to use this UIImage as a texture, my question is how can I create a shape of the correct size without any whitespace (i.e it starts at 0,0) ?

Code from Bugivore :

- (UIImage *)drawTexture : (NSArray *)verticesPassed {

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();

    //This function gets the bounds or smallest rectangle required to generate a shape which
    //will be used as pattern
    CGRect shp = [self boundFromFrame:verticesPassed];


    //Generate the shape as image so that we can make pattern out of it.
    CGContextRef conPattern = CGBitmapContextCreate(NULL,
                                                    shp.size.width,
                                                    shp.size.height,
                                                    8,
                                                    0,
                                                    rgbColorSpace,
                                                    (CGBitmapInfo)kCGImageAlphaPremultipliedFirst);

    CGColorSpaceRelease(rgbColorSpace);

    CGContextSetLineWidth(conPattern, 10);
    CGContextSetStrokeColorWithColor(conPattern, [UIColor blueColor].CGColor);

    Line * start = [verticesPassed objectAtIndex:0];
    StandPoint * startPoint = start.origin;
    CGContextMoveToPoint(conPattern, [startPoint.x floatValue]-shp.origin.x , [startPoint.y floatValue]-shp.origin.y);

    for (Line * vertice in verticesPassed) {
        StandPoint * standPoint = vertice.origin;
        CGContextAddLineToPoint(conPattern, [standPoint.x floatValue]-shp.origin.x, [standPoint.y floatValue]-shp.origin.y);
    }

    CGContextStrokePath(conPattern);

    //Make the main image and color it with pattern.
    CGImageRef cgImage = CGBitmapContextCreateImage(conPattern);

    UIImage *imgPattern = [[UIImage alloc]initWithCGImage:cgImage];
    //UIImageWriteToSavedPhotosAlbum(imgPattern, nil, nil, nil);


    UIColor *patternColor = [UIColor colorWithPatternImage:imgPattern];

    CGContextRef con = CGBitmapContextCreate(NULL,
                                             500,
                                             500,
                                             8,
                                             0,
                                             rgbColorSpace,
                                             (CGBitmapInfo)kCGImageAlphaPremultipliedFirst);

    CGColorSpaceRelease(rgbColorSpace);

    CGContextSetLineWidth(con, 10);

    CGContextMoveToPoint(con, 0 , 0);
    CGContextAddLineToPoint(con, 500 , 0 );
    CGContextAddLineToPoint(con, 500, 500 );
    CGContextAddLineToPoint(con, 0 , 500);


    CGContextSetFillColorWithColor(con, patternColor.CGColor);

    CGContextFillPath(con);


    CGImageRef cgImageFinal = CGBitmapContextCreateImage(con);

    UIImage *newImage = [[UIImage alloc]initWithCGImage:cgImageFinal];

    UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil);

    return newImage;


}
-(CGRect)boundFromFrame:(NSArray*)verticesPassed
{
    float top,left,right,bottom;
    bool bFirst = YES;

    for (Line * vertice in verticesPassed) {
        StandPoint * standPoint = vertice.origin;
        if(bFirst)
        {
            left = right = [standPoint.x floatValue];
            top = bottom = [standPoint.y floatValue];
            bFirst = NO;
        }
        else{
            if ([standPoint.x floatValue]<left) left = [standPoint.x floatValue];
            if ([standPoint.x floatValue]>right) right = [standPoint.x floatValue];
            if ([standPoint.x floatValue]<top) top = [standPoint.y floatValue];
            if ([standPoint.x floatValue]>bottom) bottom = [standPoint.y floatValue];
        }

    }

    return CGRectMake(left, top, right - left, bottom-top);

}

In photo album :

enter image description here

1

There are 1 answers

0
TorukMakto On BEST ANSWER

Note that I have modified your code a bit to test it. But this takes array coordinates and draws a shape based on line coordinates. The uses that shape to draw pattern over 1000x1000 image. Final image is saved in your photo album so that you can test out the code.. You can replace it with return of UIImage as per your original code.. However this primarily shows you the technique how you can use the drawing to create texture.

- (void)drawTexture : (NSArray *)verticesPassed {

CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();

//This function gets the bounds or smallest rectangle required to generate a shape which
//will be used as pattern
CGRect shp = [self boundFromFrame:verticesPassed];


//Generate the shape as image so that we can make pattern out of it.
CGContextRef conPattern = CGBitmapContextCreate(NULL,
                                         shp.size.width,
                                         shp.size.height,
                                         8,
                                         0,
                                         rgbColorSpace,
                                         kCGImageAlphaPremultipliedFirst);

CGColorSpaceRelease(rgbColorSpace);

CGContextSetLineWidth(conPattern, 10);
CGContextSetStrokeColorWithColor(conPattern, [UIColor blueColor].CGColor);

Line * start = [verticesPassed objectAtIndex:0];
CGContextMoveToPoint(conPattern, start.x-shp.origin.x , start.y-shp.origin.y);

for (Line * vertice in verticesPassed) {
    CGContextAddLineToPoint(conPattern, vertice.x-shp.origin.x , vertice.y-shp.origin.y );
}
CGContextStrokePath(conPattern);

//Make the main image and color it with pattern.
CGImageRef cgImage = CGBitmapContextCreateImage(conPattern);

UIImage *imgPattern = [[UIImage alloc]initWithCGImage:cgImage];
//UIImageWriteToSavedPhotosAlbum(imgPattern, nil, nil, nil);


UIColor *patternColor = [UIColor colorWithPatternImage:imgPattern];

CGContextRef con = CGBitmapContextCreate(NULL,
                                         1000,
                                         1000,
                                         8,
                                         0,
                                         rgbColorSpace,
                                         kCGImageAlphaPremultipliedFirst);

CGColorSpaceRelease(rgbColorSpace);

CGContextSetLineWidth(con, 10);



CGContextMoveToPoint(con, 0 , 0);
CGContextAddLineToPoint(con, 1000 , 0 );
CGContextAddLineToPoint(con, 1000 , 1000 );
CGContextAddLineToPoint(con, 0 , 10000 );


CGContextSetFillColorWithColor(con, patternColor.CGColor);

CGContextFillPath(con);


CGImageRef cgImageFinal = CGBitmapContextCreateImage(con);

UIImage *newImage = [[UIImage alloc]initWithCGImage:cgImageFinal];

UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil);


}
-(CGRect)boundFromFrame:(NSArray*)verticesPassed
{
float top,left,right,bottom;
bool bFirst = YES;

for (Line * vertice in verticesPassed) {
    if(bFirst)
    {
        left = right = vertice.x;
        top = bottom = vertice.y;
        bFirst = NO;
    }
    else{
        if (vertice.x<left) left = vertice.x;
        if (vertice.x>right) right = vertice.x;
        if (vertice.x<top) top = vertice.y;
        if (vertice.x>bottom) bottom = vertice.y;
    }

}

return CGRectMake(left, top, right - left, bottom-top);

}