Frage

I am developing photography app. In that i need to create frame for NSImage i have done using drawing like this

NSImage *fg_img = [[NSImage alloc]initWithData:[NSData dataWithContentsOfFile:filepath]];
        //NSData *imageData1 = [NSData dataWithContentsOfURL: [NSURL encryptedFileURLWithPath:str]] ;
        NSImage *bg_img = [[NSImage alloc]initWithContentsOfURL:[NSURL encryptedFileURLWithPath:str]];



    NSImage *newImage ;

    NSRect imageRect = NSMakeRect(0,0, fg_img.size.width+fg_img.size.width/5, fg_img.size.height+fg_img.size.height/5);
    newImage = [[NSImage alloc] initWithSize: NSMakeSize(imageRect.size.width,imageRect.size.height)];
    NSRect fgrect = NSMakeRect(imageRect.size.width*0.03,imageRect.size.height*0.04, imageRect.size.width-imageRect.size.width/15.5, imageRect.size.height-imageRect.size.height/12);

    [newImage lockFocus];

    [fg_img drawInRect:fgrect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
    [bg_img drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];

    [newImage unlockFocus];

but its not clear..

the original frame image

my original frame is

when I scaling it output is enter image description here

In above picture the width of the frame has changed when I resize frame image. I need without changing width of frame image when scaling.

updated:

but your code display like this

preview

if i give big picture the base image become very thin

War es hilfreich?

Lösung

I think you are looking for nine part image. The Nine part image resizes left and right side only vertically, top and bottom only horizontally, center is resized axes independently, and corners are not resized.

_____________ 
|c |  hor | c|  
|__|______|__|
|  |      |  |
|v | axes |v |
|e |indep.|e |
|r |      |r |
|__|______|__|
|c |  hor |c |
|__|______|__|

Apple hase a method that helps you to draw such images: NSDrawNinePartImage here But it needs images to be prepared.

The initialization code is like this:

    static NSImage *baseImage = NULL;
    static NSImage *topLeftCornerImage;
    static NSImage *topEdgeImage;
    static NSImage *topRightCornerImage;
    static NSImage *leftEdgeImage;
    static NSImage *centerImage;
    static NSImage *rightEdgeImage;
    static NSImage *bottomLeftCornerImage;
    static NSImage *bottomEdgeImage;
    static NSImage *bottomRightCornerImage;

    + (void)initialize;
    {
        if (baseImage) return;

        //46x46


        baseImage = [NSImage imageNamed:@"badge.png"];

        topLeftCornerImage = [[NSImage alloc] initWithSize:NSMakeSize(22, 22)];
        [topLeftCornerImage lockFocus];
        [baseImage drawInRect:NSMakeRect(0,0,22,22)
                     fromRect:NSMakeRect(0.0,24,22,22)
                    operation:NSCompositeCopy fraction:1.0];
        [topLeftCornerImage unlockFocus];

        topEdgeImage = [[NSImage alloc] initWithSize:NSMakeSize(2, 22)];
        [topEdgeImage lockFocus];
        [baseImage drawInRect:NSMakeRect(0,0,2,22)
                     fromRect:NSMakeRect(22,24,2,22)
                    operation:NSCompositeCopy fraction:1.0];
        [topEdgeImage unlockFocus];

        topRightCornerImage = [[NSImage alloc] initWithSize:NSMakeSize(22, 22)];
        [topRightCornerImage lockFocus];
        [baseImage drawInRect:NSMakeRect(0,0,22,22)
                     fromRect:NSMakeRect(24,24,22,22)
                    operation:NSCompositeCopy fraction:1.0];
        [topRightCornerImage unlockFocus];

        leftEdgeImage = [[NSImage alloc] initWithSize:NSMakeSize(22, 2)];
        [leftEdgeImage lockFocus];
        [baseImage drawInRect:NSMakeRect(0,0,22,2)
                     fromRect:NSMakeRect(0,22,22,2)
                    operation:NSCompositeCopy fraction:1.0];
        [leftEdgeImage unlockFocus];

        centerImage = [[NSImage alloc] initWithSize:NSMakeSize(2, 2)];
        [centerImage lockFocus];
        [baseImage drawInRect:NSMakeRect(0,0,2,2)
                     fromRect:NSMakeRect(22,22,2,2)
                    operation:NSCompositeCopy fraction:1.0];
        [centerImage unlockFocus];

        rightEdgeImage = [[NSImage alloc] initWithSize:NSMakeSize(22, 2)];
        [rightEdgeImage lockFocus];
        [baseImage drawInRect:NSMakeRect(0,0,22,2)
                     fromRect:NSMakeRect(24,24,22,2)
                    operation:NSCompositeCopy fraction:1.0];
        [rightEdgeImage unlockFocus];

        bottomLeftCornerImage = [[NSImage alloc] initWithSize:NSMakeSize(22, 22)];
        [bottomLeftCornerImage lockFocus];
        [baseImage drawInRect:NSMakeRect(0,0,22,22)
                     fromRect:NSMakeRect(0,0,22,22)
                    operation:NSCompositeCopy fraction:1.0];
        [bottomLeftCornerImage unlockFocus];

        bottomEdgeImage = [[NSImage alloc] initWithSize:NSMakeSize(2, 22)];
        [bottomEdgeImage lockFocus];
        [baseImage drawInRect:NSMakeRect(0, 0, 2, 22)
                     fromRect:NSMakeRect(22, 0, 2, 22)
                    operation:NSCompositeCopy fraction:1.0];
        [bottomEdgeImage unlockFocus];

        bottomRightCornerImage = [[NSImage alloc] initWithSize:NSMakeSize(22, 22)];
        [bottomRightCornerImage lockFocus];
        [baseImage drawInRect:NSMakeRect(0,0,22,22)
                     fromRect:NSMakeRect(24,0,22,22)
                    operation:NSCompositeCopy fraction:1.0];
        [bottomRightCornerImage unlockFocus];
    }

drawingCode:

NSDrawNinePartImage([self bounds],
                    topLeftCornerImage, topEdgeImage, topRightCornerImage,
                    leftEdgeImage, centerImage, rightEdgeImage,
                    bottomLeftCornerImage, bottomEdgeImage, bottomRightCornerImage,
                    NSCompositeSourceOver, 1.0, NO);

here is another example of my realization for CALayer based nine part image - NinePartLayer.

NinePartLayer.h

#import <Foundation/Foundation.h>


@interface NinePartLayer : CALayer {
@private
    NSSize _blockSize;
    NSMutableArray* layers;
    NSMutableArray* _images;
}

+ (NinePartLayer*) layerWithImage:(NSImage*)aImage;

@property (assign)NSSize blockSize;
- (void) setImage:(NSImage*)aImage;
@end

NinePartLayer.m

#import "NinePartLayer.h"

@interface NinePartLayer()

@property (retain)NSMutableArray* layers;
@property (retain)NSMutableArray* images;

@end

@implementation NinePartLayer
@synthesize images = _images;
@synthesize blockSize = _blockSize;
@synthesize layers;

+(NSImage*) imageFromImage:(NSImage *)anImage rect:(NSRect)aRect
{
    @try {
        NSPoint point = { -aRect.origin.x, -aRect.origin.y };
        NSImage *theImage = [[self alloc] initWithSize:aRect.size];
        [theImage lockFocus];
        [anImage compositeToPoint:point operation:NSCompositeCopy];
        [theImage unlockFocus];
        [theImage autorelease];
        return theImage;
    }
    @catch (NSException *exception) {
        NSLog(@"%@",[exception description]);
        return nil;
    }
}

+ (NinePartLayer*) layerWithImage:(NSImage*)aImage
{
    NinePartLayer* newLayer = [NinePartLayer layer];
    [newLayer setImage:aImage];
    return newLayer;
}

- (id)init {
    self = [super init];
    if (self) {
        self.layers = [NSMutableArray array];
        self.images = [NSMutableArray array];
    }
    return self;
}

- (void) updateLayers
{
    for (int i = 0; i < 3 && i < [self.images count]; ++i) {
        NSMutableArray* row = [self.images objectAtIndex:i];
        for (int j = 0; j < 3 && j < [row count]; ++j) {
            CALayer* item = [row objectAtIndex:j];
            float x,y,width,height;
            if(i == 0){
                y = 0;
                height = floorf(self.blockSize.height);
            } else if(i == 1){
                y = ceilf(self.blockSize.height);      
                height = self.frame.size.height - 2*self.blockSize.height;
            } else if(i == 2){
                y = self.frame.size.height - self.blockSize.height;
                height = self.blockSize.height;
            };
            if(j == 0){
                x = 0;
                width = self.blockSize.width;
            } else if(j == 1){
                x = self.blockSize.width;
                width = self.frame.size.width - 2*self.blockSize.width;
            } else if(j == 2){
                x = self.frame.size.width - self.blockSize.width;
                width = self.blockSize.width;
            };

            item.frame = CGRectMake(x, y, width, height);

            float delta=0;

            if((i==1)&&(j==0))
            {
                item.frame = CGRectMake(x, y-delta, width+delta, height+2*delta);
            }

            if((i==2)&&(j==1))
            {
                item.frame = CGRectMake(x-delta, y-delta, width+2*delta, height+delta);
            }

            if((i==1)&&(j==2))
            {
                item.frame = CGRectMake(x-delta, y-delta, width+delta, height+2*delta);
            }

            if((i==0)&&(j==1))
            {
                item.frame = CGRectMake(x-delta, y, width+2*delta, height+delta);
            }
        }
    } 
}

- (void) setImage:(NSImage*)aImage
{
   for(int i = 0; i < [self.layers count]; ++i)
        [[self.layers objectAtIndex:i] removeFromSuperlayer];

    [self.layers removeAllObjects];

    self.images = [NSMutableArray array];
    self.layers = [NSMutableArray array];
    if(!aImage)
        return;

    for (int i = 0; i < 3; ++i) {
        NSMutableArray* row = [NSMutableArray array];
        for (int j = 0; j < 3; ++j) {
            NSImage* img = [NSImage imageFromImage:aImage 
                                              rect:NSMakeRect((float)j/3.0*[aImage size].width, 
                                                              (float)i/3.0*[aImage size].height, 
                                                              1.0/3.0*[aImage size].width,
                                                              1.0/3.0*[aImage size].height)];
            self.blockSize = NSMakeSize(1.0/3.0*[aImage size].width, 1.0/3.0*[aImage size].height);

            CALayer* item = [CALayer layer];
            [item performSelectorOnMainThread:@selector(setContents:) withObject:img waitUntilDone:NO];
            [item performSelectorOnMainThread:@selector(setContentsGravity:) withObject:kCAGravityResize waitUntilDone:NO];
            [self performSelectorOnMainThread:@selector(addSublayer:) withObject:item waitUntilDone:NO];
            [row addObject:item];
            [self.layers addObject:item];
        }
        [self.images addObject:row];
    }
    [self performSelectorOnMainThread:@selector(updateLayers) withObject:nil waitUntilDone:NO];
}

- (void) setFrame:(CGRect)frame
{
    [super setFrame:frame];
    [self updateLayers];
}

- (void) setBounds:(CGRect)bounds
{
    [super setBounds:bounds];
    [self updateLayers];
}

- (void) setPosition:(CGPoint)position
{
    [super setPosition:position];
    [self updateLayers];
}

- (void)dealloc {
    self.layers = nil;
    self.images = nil;
    [super dealloc];
}
@end

usage:

    NinePartLayer * pageContainerShadowlayer=[NinePartLayer layerWithImage:[NSImage imageNamed:@"drop_shadow.png"]];
    pageContainerShadowlayer.frame=[mainView layer].bounds;
    pageContainerShadowlayer.autoresizingMask=kCALayerWidthSizable | kCALayerHeightSizable;
    [[rootView layer] insertSublayer:pageContainerShadowlayer atIndex:3];

Andere Tipps

In case anyone else stumbled on this question years later (like I did) – starting in macOS 10.10 (Yosemite), NSImage has a capInsets property which takes care of the nine-part image behaviour using a single source image. Yay!

Have you considered NSDrawNinePartImage? It's a function designed specifically for drawing nine images (four corners, four edges, and a center) in the arrangement you propose, without visible seams and without stretching the corner and edge images.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top