Transparency

Discussion in 'Mac Programming' started by MrFusion, Mar 1, 2007.

  1. macrumors 6502a

    Joined:
    Jun 8, 2005
    Messages:
    583
    Location:
    West-Europe
    #1
    After some searching the net, I came up with/to this code. It reads an img file, goes through it pixel by pixel and makes a new image pixel by pixel and saves that.
    White pixels are made transparant and non-whites are made black.
    But the problem is that the image gets destorted. The only thing I need it for is to make a few images transparant, so the code doesn't have to be that good.

    Any idea?

    Code:
    int i, j, cell_width, cell_height;
    	
    	//old image
    	NSImage *image =[[NSImage alloc] initWithContentsOfFile:@"testIN.pdf"];
           NSBitmapImageRep *bitmap = [[[NSBitmapImageRep alloc] initWithData: [image TIFFRepresentation]] autorelease];
    	unsigned char *bytes = [bitmap bitmapData];
    	//new image
    	[view1 setImage:image];
    	cell_width = [bitmap pixelsWide];
    	cell_height = [bitmap pixelsHigh];
    	NSImage *newImage = [[NSImage alloc] initWithSize:NSMakeSize(cell_width,cell_height)];
    		
    	NSBitmapImageRep *new_bitmap = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
    											pixelsWide: cell_width
    											pixelsHigh: cell_height
    										 bitsPerSample: 8
    									   samplesPerPixel: 4
    										  hasAlpha: YES
    										  isPlanar: NO
    								    colorSpaceName: NSCalibratedRGBColorSpace
    									   bytesPerRow: 0
    									    bitsPerPixel: 0] autorelease];
    	unsigned char *newbytes = [new_bitmap bitmapData];
           j = 0;
        for (i = 0; i < cell_width * cell_height * 3; i += 3) {
                 unsigned char r, g, b;
    		r = *(bytes + i);
                  g = *(bytes + i + 1);
                  b = *(bytes + i + 2);
    		
            if(r == 255 && g == 255 && b == 255){
                *(newbytes + j + 0) = 0;
                *(newbytes + j + 1) = 0;
                *(newbytes + j + 2) = 0;
                *(newbytes + j + 3) = 0;
            } else {
                *(newbytes + j + 0) = 0;
                *(newbytes + j + 1) = 0;
                *(newbytes + j + 2) = 0;
                *(newbytes + j + 3) = 255;			
            }
            j += 4;
        }
        [newImage lockFocus];
        [new_bitmap draw];
        [newImage unlockFocus];
    
        NSData *data = [newImage TIFFRepresentation];
        [data writeToFile: @"testOut.tiff" atomically: NO]
    
     
  2. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #2
    You've made some unsafe assumptions about the number of bytes in a row (I did this when I first started using these classes too).

    The number of bytes in a row is not guaranteed to be pixels wide * samples per pixel. It's often padded for efficiency in reads a writes. You should use the methods in NSBitmapImageRep to read this. Also you should assuming RGB without Alpha may work but it's not always true!

    Use this method to find the actual bytes per row instead of calculating it...
     
  3. macrumors 6502a

    Joined:
    Jun 8, 2005
    Messages:
    583
    Location:
    West-Europe
    #3
    So, I should replace
    Code:
    cell_width * cell_height * 3
    
    by
    Code:
    [bitmap bytesPerRow]
    
    ?

    That doesn't work, I am afraid. Sorry, I am not familiar with these classes and how they behave. And unfortunately I don't have much time to find out, in contrast to the other simple cocoa things I am working on.
     
  4. Moderator

    robbieduncan

    Staff Member

    Joined:
    Jul 24, 2002
    Messages:
    24,480
    Location:
    London
    #4
    Nope.

    Your assumption is the cell_width * 3 is the number of bytes in a row. This is not the case.

    Your loop is over simplistic. You need two loops something like this:

    Code:
    int i, j, base;
    
    for (i=0; i<cell_height;i++)
    {
      for (j=0; j<cell_width; j++)
      {
        base = ([bitmap bytesPerRow] * i) + // This gets us onto the correct row
    ([bitmap samplesPerPixel] *j) // This moves us the correct number of pixels along the row
    
    // So no r = bytes+base, g = bytes+base+1, b = bytes+base+2
      }
    }
    
    Note this is types straight into here: it might have bugs but this is the correct general idea...
     
  5. macrumors 6502a

    Joined:
    Jun 8, 2005
    Messages:
    583
    Location:
    West-Europe
    #5
    Code:
    	
    	int cell_width, cell_height;
    	
    	//old image
    	NSImage *image =[[NSImage alloc] initWithContentsOfFile:@"testIn.pdf"];
        NSBitmapImageRep *bitmap = [[[NSBitmapImageRep alloc] initWithData: [image TIFFRepresentation]] autorelease];
    	unsigned char *bytes = [bitmap bitmapData];
    	//new image
    	[view1 setImage:image];
    	cell_width = [bitmap pixelsWide];
    	cell_height = [bitmap pixelsHigh];
    	NSImage *newImage = [[NSImage alloc] initWithSize:NSMakeSize(cell_width,cell_height)];
    		
    	NSBitmapImageRep *new_bitmap = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL									pixelsWide: cell_width
    				pixelsHigh: cell_height
    			 bitsPerSample: 8
    		   samplesPerPixel: 4
    				  hasAlpha: YES
    				  isPlanar: NO
    		colorSpaceName: NSCalibratedRGBColorSpace
    		   bytesPerRow: [bitmap bytesPerRow]
    			  bitsPerPixel: 0] autorelease];
    	unsigned char *newbytes = [new_bitmap bitmapData];
        
    	int i,j, base,k=0;
    		for (i=0;i< cell_height; i++) {
    			for (j=0;j < cell_width; j++) { 
    				unsigned char r, g, b;
    				base =  ([bitmap bytesPerRow] * i) + ([bitmap samplesPerPixel] *j);
    				r = *(bytes + base);
    				g = *(bytes + base +1);
    				b = *(bytes + base +2);
    				if(r == 255 && g == 255 && b == 255){
    					*(newbytes + k + 0) = 0;
    					*(newbytes + k + 1) = 0;
    					*(newbytes + k + 2) = 0;
    					*(newbytes + k + 3) = 0;
    				} else {
    					*(newbytes + k + 0) = 0;
    					*(newbytes + k + 1) = 0;
    					*(newbytes + k + 2) = 0;
    					*(newbytes + k + 3) = 255;			
    				}
    				k +=4;
    			}
    	}
        [newImage lockFocus];
        [new_bitmap draw];
       [newImage unlockFocus];
    
    	NSData *data = [newImage TIFFRepresentation];
    	[data writeToFile: @"testout.tiff"
    		   atomically: NO];
    		[view2 setImage:newImage];
    
    This works!
    Thanks.
     

Share This Page