Search code examples
cocoansviewikimagebrowserviewnsprintoperation

Is it possible to print IKImageBrowserView In Cocoa programmatically?


I want to take print of IKImageBrowserView with (content) images. I tried the following code

if (code == NSOKButton) {
        NSPrintInfo *printInfo;
        NSPrintInfo *sharedInfo;
        NSPrintOperation *printOp;
        NSMutableDictionary *printInfoDict;
        NSMutableDictionary *sharedDict;

        sharedInfo = [NSPrintInfo sharedPrintInfo];
        sharedDict = [sharedInfo dictionary];
        printInfoDict = [NSMutableDictionary dictionaryWithDictionary: sharedDict];

        [printInfoDict setObject:NSPrintSaveJob
                          forKey:NSPrintJobDisposition];

        [printInfoDict setObject:[sheet filename] forKey:NSPrintSavePath];

        printInfo = [[NSPrintInfo alloc] initWithDictionary:printInfoDict];
        [printInfo setHorizontalPagination: NSAutoPagination];
        [printInfo setVerticalPagination: NSAutoPagination];
        [printInfo setVerticallyCentered:NO];

        printOp = [NSPrintOperation printOperationWithView:imageBrowser
                                                 printInfo:printInfo];

        [printOp setShowsProgressPanel:NO];
        [printOp runOperation];
    }

because IKImageBrowserView is Inherits from NSView but print preview is showing null image. Please help me to over come this problem. Thanks in advance.....


Solution

  • /*
        1) allocate a c buffer at the size of the  visible rect of the image
        browser
         */
        NSRect vRect = [imageBrowser visibleRect];
        NSSize size = vRect.size;
        NSLog(@"Size W = %f and H = %f", size.width, size.height);
        void *buffer = malloc(size.width * size.height * 4);
    
    //2) read the pixels using openGL
    [imageBrowser lockFocus];
    glReadPixels(0,
                 0,
                 size.width,
                 size.height,
                 GL_RGBA,
                 GL_UNSIGNED_BYTE,
                 buffer);
    [imageBrowser unlockFocus];
    
    //3) create a bitmap with those pixels
    unsigned char *planes[2];
    planes[0] = (unsigned char *) (buffer);
    
    NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc]
                                  initWithBitmapDataPlanes:planes pixelsWide:size.width
                                  pixelsHigh:size.height bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES
                                  isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace bitmapFormat:0
                                  bytesPerRow:size.width*4 bitsPerPixel:32];
    /*
    4) create a temporary image with this bitmap and set it flipped
    (because openGL and the AppKit don't have the same pixels coordinate
     system)
     */
    NSImage *img = [[NSImage alloc] initWithSize:size];
    [img addRepresentation:imageRep];
    [img setFlipped:YES];
    [imageRep release];
    /*
    5) draw this temporary image into another image so that we get an
    image without any reference to our "buffer" buffer so that we can
    release it after that
     */
    NSImage *finalImage = [[NSImage alloc] initWithSize:size];
    [finalImage lockFocus];
    [img drawAtPoint:NSZeroPoint
            fromRect:NSMakeRect(0,0,size.width,size.height)
           operation:NSCompositeCopy fraction:1.0];
    [finalImage unlockFocus];
    
    //[NSString stringWithFormat:@"/tmp/%@.tiff", marker]
    NSData *imageData = [finalImage TIFFRepresentation];
    NSString *writeToFileName = [NSString stringWithFormat:@"/Users/Desktop/%@.png", [NSDate date]];
    [imageData writeToFile:writeToFileName atomically:NO];
    
    //6) release intermediate objects
    [img release];
    free(buffer);
    

    After this I send imageData for print, which works great for me.