summaryrefslogtreecommitdiff
path: root/SmartDeviceLink/CVPixelBufferRef+SDLUtil.m
blob: 1a62ece106cc7888d896af1f7241b8302fe1257a (plain)
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//
//  CVPixelBufferRef+SDLUtil.m
//  SmartDeviceLink-iOS
//
//  Created by Muller, Alexander (A.) on 3/16/17.
//  Copyright © 2017 smartdevicelink. All rights reserved.
//

#import "CVPixelBufferRef+SDLUtil.h"
#import "SDLLogMacros.h"

NS_ASSUME_NONNULL_BEGIN

// Video stream string message padding is 5% of the screen size. Padding is added to the message so the text is not flush with the edge of the screen.
CGFloat const SDLVideoStringMessagePadding = .05;

UIFont * _Nullable sdl_findFontSizeToFitText(CGSize size, NSString *text) {
    CGFloat fontSize = 300;

    do {
        CGFloat padding = SDLVideoStringMessagePadding * size.width * 2;
        CGSize textSize = [text boundingRectWithSize:CGSizeMake((size.width - padding), CGFLOAT_MAX)
                                             options:NSStringDrawingUsesLineFragmentOrigin
                                          attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:fontSize]}
                                             context:nil].size;

        if (textSize.height <= (size.height - padding)) {
            break;
        }
        
        fontSize -= (CGFloat)1.0;
    } while (fontSize > 0.0);

    return (fontSize > 0) ? [UIFont systemFontOfSize:fontSize] : nil;
}

UIImage * _Nullable sdl_createTextImage(NSString *text, CGSize size) {
    UIFont *font = sdl_findFontSizeToFitText(size, text);
    
    if (!font) {
        SDLLogW(@"Text cannot fit inside frame");
        return nil;
    }

    CGRect frame = CGRectMake(0, 0, size.width, size.height);
    UIGraphicsBeginImageContextWithOptions(frame.size, NO, 1.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
    CGContextFillRect(context, frame);
    CGContextSaveGState(context);
    
    NSMutableParagraphStyle* textStyle = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
    textStyle.alignment = NSTextAlignmentLeft;
    
    NSDictionary* textAttributes = @{
                                     NSFontAttributeName: font,
                                     NSForegroundColorAttributeName: [UIColor whiteColor],
                                     NSParagraphStyleAttributeName: textStyle
                                     };
    CGRect textFrame = [text boundingRectWithSize:size
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:textAttributes
                                          context:nil];

    CGFloat padding = SDLVideoStringMessagePadding * size.width;
    CGRect textInset = CGRectMake(0 + padding,
                                  (frame.size.height - CGRectGetHeight(textFrame)) / 2.0,
                                  frame.size.width - (padding * 2),
                                  frame.size.height - (padding * 2));
    
    [text drawInRect:textInset
      withAttributes:textAttributes];
    
    CGContextRestoreGState(context);
    UIImage* image = UIGraphicsGetImageFromCurrentImageContext();

    return image;
}

Boolean CVPixelBufferAddText(CVPixelBufferRef CV_NONNULL pixelBuffer, NSString *text) {
    size_t width = CVPixelBufferGetWidth(pixelBuffer);
    size_t height = CVPixelBufferGetHeight(pixelBuffer);
    
    UIImage *image = sdl_createTextImage(text, CGSizeMake(width, height));
    if (!image) {
        SDLLogE(@"Could not create text image.");
        return false;
    }
    
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);
    void *data = CVPixelBufferGetBaseAddress(pixelBuffer);
    
    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(data, width, height,
                                                 8, CVPixelBufferGetBytesPerRow(pixelBuffer), rgbColorSpace,
                                                 kCGBitmapByteOrder32Little |
                                                 kCGImageAlphaPremultipliedFirst);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage);
    CGColorSpaceRelease(rgbColorSpace);
    
    CGContextRelease(context);
    
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
    
    return true;
}

NS_ASSUME_NONNULL_END