Home > Blockchain >  Exporting a QR to vector NSImage & CGPDFContextCreate - macOS ObjC
Exporting a QR to vector NSImage & CGPDFContextCreate - macOS ObjC

Time:11-11

I've been trying to figure out how to export my QR codes on my little project as a vector.

I start from qrImageForString function which generates the image initially, and does so as a bitmap.

The main two lines in question are:

CGContextRef ctx = CGBitmapContextCreate(0, size, size, 8, size * 4, colorSpace,kCGImageAlphaPremultipliedLast);
CGImageRef qrCGImage = CGBitmapContextCreateImage(ctx);

For the first one I think this may be a replacement:

NSRect rect = CGRectMake(0.0, 0.0, 750.0, 750.0);
CGContextRef ctx = CGPDFContextCreate(dataConsumer, &rect, NULL);

However I'm not sure how to replace the second line to make it a vector.

Full function is:

  (NSImage *)qrImageForString:(NSString *)string imageSize:(CGFloat)size {
    if (![string length]) {
        return nil;
    }
    
    int str1;
      
    QRcode *code = QRcode_encodeString([string UTF8String], 0, str1, QR_MODE_8, 1);
    
    
    // create context
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(0, size, size, 8, size * 4, colorSpace, kCGImageAlphaPremultipliedLast);
    
    NSRect rect = CGRectMake(0.0, 0.0, 750.0, 750.0);

    
    NSMutableData* outputData = [[NSMutableData alloc] init];
    CGDataConsumerRef dataConsumer = CGDataConsumerCreateWithCFData((CFMutableDataRef)outputData);
      
    CGAffineTransform translateTransform = CGAffineTransformMakeTranslation(0, -size);
    CGAffineTransform scaleTransform = CGAffineTransformMakeScale(1, -1);
    CGContextConcatCTM(ctx, CGAffineTransformConcat(translateTransform, scaleTransform));
    
    // draw QR on this context
    [MainClass drawQRCode:code context:ctx size:size];
    
    // get image
    CGImageRef qrCGImage = CGBitmapContextCreateImage(ctx);

    
    
    NSImage *qrImage = [[NSImage alloc] initWithCGImage:qrCGImage size:NSZeroSize];
  
    
    // some releases
    CGContextRelease(ctx);
    CGImageRelease(qrCGImage);
    CGColorSpaceRelease(colorSpace);
    QRcode_free(code);
    
    return qrImage;
}

CodePudding user response:

Copied from How to make dataWithEPSInsideRect vector rather than bitmap in vector format?: Create an offscreen view, set up the draw method of the view to include your graphic and then use NSView's dataWithEPSInsideRect: method.

I made mdDrawQRCode:context:size:fillColor: an instance method of the view but it can be a method of different class. The view:

@interface MyView : NSView

@property (strong) NSString *qrString;

@end


@implementation MyView

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    if (!self.qrString)
        return;

    CGContextRef cgContext = [[NSGraphicsContext currentContext] CGContext];
    CGContextSaveGState(cgContext);

    QRcode *code = QRcode_encodeString([self.qrString UTF8String], 0, QR_ECLEVEL_L, QR_MODE_8, 1);
    [self mdDrawQRCode:code context:cgContext size:self.bounds.size.width fillColor:[NSColor blackColor]];
    QRcode_free(code);

    CGContextRestoreGState(cgContext);
}

@end

Use the view like:

MyView *myView = [[MyView alloc] initWithFrame:NSMakeRect(0, 0, 100.0, 100.0)];
myView.qrString = @"Hello World!";
NSData *data = [myView dataWithEPSInsideRect:myView.bounds];
  • Related