Combine(merge) two images

Discussion in 'Mac Programming' started by Trisect Develop, Jun 28, 2013.

  1. macrumors newbie

    Joined:
    Jun 28, 2013
    Messages:
    13
    Location:
    Denmark
    #1
    I'm working on a Mac program that should combine two images and display them in an ImageView.

    The first image is dragged into XCode and the other one is loaded from disk.

    How do I combine(merge) those two images and put them into my ImageView?
     
  2. macrumors 6502a

    Joined:
    Mar 30, 2012
    Messages:
    752
    #2
    Could you not give the second image some transparency and print it over the first one?
     
  3. macrumors newbie

    Joined:
    Jun 28, 2013
    Messages:
    13
    Location:
    Denmark
    #3
    I'm fairly new to Mac programming have done a lot of iOS programming.

    But I don't think an ImageView can cotain two images!

    I need to combine them somehow.
     
  4. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #4
    Do you actually need the images combined in memory/on disk or do you just want to display the result? If the latter just use 2 image views with one slightly transparent.

    Otherwise:

    1) Load each image into an NSImage object
    2) Lock focus using lockFocus on the bottom "layer"
    3) Draw the top "layer" using drawInRect:fromRect:eek:peration:fraction: setting the operation and fraction to do what you want.
     
  5. macrumors newbie

    Joined:
    Jun 28, 2013
    Messages:
    13
    Location:
    Denmark
    #5
    I want to take one image and put another on on top of the first one and display it in an ImageView. Later I wan't the save the merged image form the ImageView.

    I have eight ImageViews and for each of the I have a button. When a button is clicked I choose an image from disk and combine it with an image already dragged into Xcode.

    Right now I have some code that actually merge two images and it works fine for the first ImageView but when I do the same for the second ImageView the first one changes to the exact same as the second one. If I then loads a new image into the first one the second changes automatically.

    So I'm thinking theres something wrong with my code and thats why I'm asking for an example on how to do it.

    Here the code from my m file.

    The load button ( it the same code for the second button)
    Code:
        
    NSOpenPanel* panel = [NSOpenPanel openPanel];
            
        [panel setCanChooseFiles:YES];
        [panel setCanChooseDirectories:NO];
        
        [panel beginWithCompletionHandler:^(NSInteger result){
            if (result == NSFileHandlingPanelOKButton) {
                NSURL *theDoc = [[panel URLs] objectAtIndex:0];
                    
                NSString *fileNameAndPath = [[theDoc path] stringByStandardizingPath];
    
                //** Vælg device
                switch ([[rbSelectDevice selectedCell] tag]) {
                    case 1: //** iPhone 5
                        screenShot1 = [self mergeImages:iPhone5 withImage:[[NSImage alloc]initWithContentsOfFile:fileNameAndPath]];
                        break;
                }
    
                [ivScreenshot1 setImage:screenShot1];
                
            }
                
        }];
    
    The merge method
    Code:
    //** Merge two images together
    -(NSImage *)mergeImages:(NSImage *)theTarget withImage:(NSImage *)theSource{
    
        //Get the source image from file
    	NSImage *source = theSource; //[[NSImage alloc]initWithContentsOfFile:@"/Users/JensThomsen/Library/Developer/Xcode/DerivedData/Smartphone_App_Store_Icons_and_Images_Tool-bsnfzaaviuzrqdcpuknipijqslci/Build/Products/Debug/icon512.png"];
    	
    	//Init target image
    	NSImage *target = theTarget; //[[NSImage alloc]initWithContentsOfFile:@"/Users/JensThomsen/Library/Developer/Xcode/DerivedData/Smartphone_App_Store_Icons_and_Images_Tool-bsnfzaaviuzrqdcpuknipijqslci/Build/Products/Debug/tempImage.png"];
        
    	//start drawing on target
    	[target lockFocus];
    	//draw the portion of the source image on target image
    	[source drawInRect:NSMakeRect(84,270,770,1365) fromRect:NSZeroRect operation: NSCompositeCopy fraction:1.0];
    	//end drawing
    	[target unlockFocus];
    	
    	//create a NSBitmapImageRep
    	NSBitmapImageRep *bmpImageRep = [[NSBitmapImageRep alloc]initWithData:[target TIFFRepresentation]];
    	//add the NSBitmapImage to the representation list of the target
    	[target addRepresentation:bmpImageRep];
    
    
        return target;
    }
    
     
  6. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #6
    Sounds like you are using the same NSImage instance for all the views then. But we don't have the code for that bit. Also you're merge code has hard-coded both images so it will always return the exact same thing...
     
  7. macrumors newbie

    Joined:
    Jun 28, 2013
    Messages:
    13
    Location:
    Denmark
    #7
    Maybe you are right but I cannot figure out where the problem is.


    I declare this variables in the top.
    Code:
    NSImage *iPhone5;
    
    NSImage *screenShot1;
    NSImage *screenShot2;
    
    I set the iPhone5 image in the initWithNibName method
    Code:
    iPhone5 = [NSImage imageNamed:@"IPhone_5.png"];
    
    Does this clear things so that you maybe can see what I'm doing wrong?
     
  8. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #8
    It matters not what variable names you declare. It matters what's loaded to them. I see I miss read your code: the fixed paths are commented out. But we still can't see all of the code: only the code for one case. If all cases use
    "iphone5" as their target then they are sharing a single instance so all will always be the same image.
     
  9. macrumors newbie

    Joined:
    Jun 28, 2013
    Messages:
    13
    Location:
    Denmark
    #9
    Ahh, so if I use

    NSImage *iPhone5_1;
    NSImage *iPhone5_2;
    NSImage *iPhone5_3;

    It will be better?
     
  10. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #10
    Assuming each of those points to a different instance, not the same then yes. I.e. don't do this:

    Code:
    NSImage *temp = [NSImage imageNamed:@"IPhone_5.png"];
    NSImage *iPhone5_1 = temp;
    NSImage *iPhone5_2 = temp;
    ...
    
    as the variable names completely and utterly don't matter: they would all point at the same instance.

    Also check that imageNamed is not caching the result and returning the same instance: I'd use alloc/init to ensure a new, clean instance each time.
     
  11. macrumors newbie

    Joined:
    Jun 28, 2013
    Messages:
    13
    Location:
    Denmark
    #11
    Okay I tried this
    Code:
            iPhone5_1 = [[NSImage alloc] init];
            iPhone5_2 = [[NSImage alloc] init];
            iPhone5_1 = [NSImage imageNamed:@"IPhone_5.png"];
            iPhone5_2 = [NSImage imageNamed:@"IPhone_5.png"];
    
    But I get the same result
     
  12. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #12
    I think you fundamentally don't understand objects, pointers and what this code does. The first two lines of code are completely and utterly pointless as they allocate new objects and point the variables at them to immediately afterwards have those pointers moved to other objects. You then use the method I warned you not to use as it would cache the object so it is most likely that _1 and _2 are now pointing at the same instance. When I suggested using alloc/init that was commonly used shorthand to indicate this style of code but not necessarily a plain init: in this case I expected you to use one of initWithContentsOfFile or initWithContentsOfURL.

    But I would suggest you need to take step back and consider learning some basic debugging techniques like using NSLog...
     
  13. macrumors newbie

    Joined:
    Jun 28, 2013
    Messages:
    13
    Location:
    Denmark
    #13
    Thanks!
    This did it.
    Code:
            NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"IPhone_5.png"];
            iPhone5_1 = [[NSImage alloc] initWithContentsOfFile:filePath];
            iPhone5_2 = [[NSImage alloc] initWithContentsOfFile:filePath];
    
    And YES I'm new to Mac programming. Never had this problems when programming for iOS.
     
  14. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #14
    Bear in mind imageNamed works the same way there too in case you want to do similar on iOS...
     
  15. macrumors 6502a

    Joined:
    Mar 30, 2012
    Messages:
    752
    #15
    If your CPU has the time, why not load both images into bitmap contexts,
    set the transparency of one of the images there,
    overlay one atop the other, and then load the final image into the view?
     

Share This Page