首页 文章

有没有办法将NSView包含子视图转换为NSImage?

提问于
浏览
-1

有没有办法将NSView包含许多带有背景颜色的子视图转换为NSImage?示例代码非常棒

NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[_collageView bounds]];
        [_collageView unlockFocus];
    //    NSData *exportedData = [rep representationUsingType:NSJPEGFileType properties:nil];
          NSData *exportedData = [rep representationUsingType:NSPNGFileType properties:nil];


        NSSavePanel *savepanel = [NSSavePanel savePanel];
    savepanel.title = @"Save chart";
    [savepanel setAllowedFileTypes:[NSArray arrayWithObject:@"png"]];
    [savepanel beginSheetModalForWindow:self.view.window completionHandler:^(NSInteger result)
     {
         if (NSFileHandlingPanelOKButton == result)
         {
             NSURL* fileURL = [savepanel URL];
             if ([fileURL.pathExtension isEqualToString:@""])
                 fileURL = [fileURL URLByAppendingPathExtension:@"png"];

             [exportedData writeToURL:fileURL atomically:YES];
         }
     }];

我还使用以下代码

[_collageView lockFocus];
    NSBitmapImageRep *bits = [[NSBitmapImageRep alloc]initWithFocusedViewRect: [_collageView bounds]];
    [_collageView unlockFocus];
    NSImage *image1 = [[NSImage alloc] init];
    [image1 addRepresentation: bits];
    [self.ImageView setImage:image1];

但没有工作

3 回答

  • 0

    您的方法从Windows服务器复制位图 . 这是视图的渲染内容 . 通常你不想这样做 .

    这是将焦点锁定在 NSImage 上的更好方法,它可以构建图形上下文,然后使用 -drawRect: 或任何绘图方法绘制到该图像中 . 您可以通过简单地迭代它们来添加子视图 .

    // perhaps in a category of NSView
    - (void)drawRecursively
    {
        [self drawRect:self.bounds];
        for (NSView *subview in self.subviews)
        {
            [subview drawRecursively];
        }
    }
    

    开始吧

    NSImage *image = [[NSImage alloc] initWithSize:theView.bounds.size];
    [image lockFocus]; // Set-up the context for the image
    [theView drawRecursively];
    [image unlockFocus];
    

    在Safari中输入 .

    编辑:在转到子视图之前,您必须为它们执行转换 . 忘了 .

  • 0

    我实际上已经在屏幕外实现了一个视图层次结构的绘制 . 它非常简单,即使对于一个非常简单的视图层次结构,其中所有视图都是子类NSControl并且 - (BOOL)isFlipped {return YES; }

    这是该代码的一小部分,它将让您了解这样做的痛苦:

    - (void)drawRect:(NSRect)iDirtyBigRect
    {
    #ifdef DISABLE_PSEUDOVIEW
       debugRectsBeingDrawn();
       return;
    #endif
    
       if ( !drawableShape )
       {
          if ( [[[self window] contentView] wantsLayer] )
          {
             CGRect cgRect = NSRectToCGRect([self bounds]);
             drawableShape = HIShapeCreateMutableWithRect( &cgRect );
          }
          else
          {
             DUMP( @"our superview should have set up our drawableShape!" );
             [self setNeedsDisplay:YES];
             return;
          }
       }
       else if ( iDirtyBigRect.size.width <= 0 )
       {
          // Our drawable shape is empty.
          // This can happen for several valid reasons:
          // 1) dirtyShape is fully masked by opaqueShape
          // 2) for some reason, we were called to obey needsDisplay when not needed
          DLog( @"nothing to draw %@", self );
          return; // must return, otherwise we risk drawing outside our bounds
       }
    
       //NSArray *hardSubviews = [self subviews];
       for ( NSView *pseudoSubview in pseudoSubviews )
       {
          if ( ![pseudoSubview isHidden] && 
              [pseudoSubview window] == offscreenWindow ) // only draw pseudo view if it's in offscreen window
          {
             NSRect rectToDraw = [pseudoSubview frame];
    //         if ( rectToDraw.size.width == 0 )
    //         {
    //            DLog( @"clipped to superview %@", pseudoSubview );
    //         }
             CGRect cgRect = NSRectToCGRect(rectToDraw);
             if ( HIShapeIntersectsRect(drawableShape, &cgRect) )
             {         
                // the magic: transform to subview coordinates
                NSAffineTransform* xform = [NSAffineTransform transform];
    
                [xform translateXBy:rectToDraw.origin.x yBy:rectToDraw.origin.y];
                if ( [pseudoSubview isFlipped] != [self isFlipped] )
                {
                   if ( ![pseudoSubview isKindOfClass: [NSColorWell class]] )
                   {
                      DUMP( @"hmmm flippedness different %d %d", [pseudoSubview isFlipped], [self isFlipped] );
                   }
                   [xform translateXBy:0.0 yBy:rectToDraw.size.height];
                   [xform scaleXBy:1.0 yBy:-1.0];
                }
                [xform concat];
    
                HIMutableShapeRef newShape = HIShapeCreateMutableWithRect( &cgRect );
                HIShapeIntersect( newShape, drawableShape, newShape ); // clip to subview frame
                HIShapeOffset( newShape, -cgRect.origin.x, -cgRect.origin.y ); // translate to subview coords
                CGRect dirtyRect;
                HIShapeGetBounds(newShape, &dirtyRect);
    //            if ( dirtyRect.size.width <= 0 )
    //            {
    //               DUMP( @"why?" );
    //            }
    
                if ( [pseudoSubview isKindOfClass:[PseudoView class]] )
                {
                   //DLog( @"drawing Pseudo %@ dirtyRect %@ ", pseudoSubview, NSStringFromRect(NSRectFromCGRect(dirtyRect)));
    
                   PseudoView *pView = (PseudoView *)pseudoSubview;
                   if ( pView->drawableShape )
                   {
                      CFRelease( pView->drawableShape );
                      pView->drawableShape = NULL;
                   }
                   // create subview personal drawableShape from my drawable shape
                   pView->drawableShape = newShape;
                   if ( [pseudoSubview isOpaque] )
                      gDrawDirtyPixels += dirtyRect.size.width * dirtyRect.size.height;
    
                   if ( dirtyRect.size.width > 0 )
                      [pseudoSubview drawRect: NSRectFromCGRect(dirtyRect)];
    
                }
                else
                {
                   //DLog( @"drawing non-Pseudo %@ rectToDraw %@ ", pseudoSubview, NSStringFromRect( rectToDraw ));
    
                   UInt64 t1 = CpuCycles();
                   CFRelease( newShape );
                   // sacrifice efficiency to avoid bugs...
                   // always draw the entire view.
                   [pseudoSubview drawRect:[pseudoSubview bounds]]; // NSRectFromCGRect(dirtyRect)]; // [pseudoSubview bounds]];
                   UnitTestQuartz( [pseudoSubview bounds] );
                   // NSLog( @"drawRect %@ %@ sUnitTestQuartzToggle %f\n -- superv %@\n -- self %@", pseudoSubview, NSStringFromRect(rectToDraw), sUnitTestQuartzToggle*100, [pseudoSubview superview],  self );
                   UInt64 t2 = CpuCycles();
                   int diff = (int)(t2-t1);
                   gDrawControl += diff;
                }
    
    
                [xform invert]; // restore
                [xform concat];
             }
          }
       }
    
       //if ( [self isKindOfClass:[PseudoRootView class]] )
       //   [offscreenWindow setViewsNeedDisplay:NO];
    }
    
  • 2

    我可以使用以下代码解决我的问题

    // Setup the image to render
            NSRect imgRect = _collageView.frame;
            NSSize imgSize = imgRect.size;
    
            NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                                                            pixelsWide:imgSize.width
                                                                            pixelsHigh:imgSize.height
                                                                         bitsPerSample:8
                                                                       samplesPerPixel:4
                                                                              hasAlpha:YES
                                                                              isPlanar:NO
                                                                        colorSpaceName:NSDeviceRGBColorSpace
                                                                          bitmapFormat:NSAlphaFirstBitmapFormat
                                                                           bytesPerRow:0
                                                                          bitsPerPixel:0];
    
            NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep:rep];
            [NSGraphicsContext saveGraphicsState];
            [NSGraphicsContext setCurrentContext:context];
            // Render
            CGContextRef zCgContextRef = (CGContextRef) [context graphicsPort];
            [[_collageView layer] renderInContext:zCgContextRef];
    
            // Get the Data for the image
            NSData *exportedData = [rep representationUsingType:NSJPEGFileType properties:nil];
    
    
            // Start the savepanel
            NSSavePanel *savepanel = [NSSavePanel savePanel];
            savepanel.title = @"Save chart";
    
            [savepanel setAllowedFileTypes:[NSArray arrayWithObject:@"jpg"]];
            [savepanel beginSheetModalForWindow:self.view.window completionHandler:^(NSInteger result)
             {
                 if (NSFileHandlingPanelOKButton == result)
                 {
                     NSURL* fileURL = [savepanel URL];
    
                     if ([fileURL.pathExtension isEqualToString:@""])
                         fileURL = [fileURL URLByAppendingPathExtension:@"jpg"];
    
                     [exportedData writeToURL:fileURL atomically:YES];
                 }
             }];
    

相关问题