> On 24 Jun 2017, at 4:46 pm, Gerriet M. Denkmann <gerri...@icloud.com> wrote:
> 
>> By making the NSBitMapRepresentation yourself, creating a context for it, 
>> drawing to that.
>> —Graham
> 
> You severely underestimate the depth of my ignorance. It took me half a day 
> to fathom your (for me) cryptic remarks.
> But thanks a lot for pointing me in the right direction!


Ah, sorry about that. I erred on the side of sketching a solution - ‘not 
teaching my grandmother to suck eggs’ (though I’ve never understood why 
grandmothers are supposed to be so good at that).

> This is what I did come up with (all error handling removed)  (things I am 
> not quite sure are marked with “??”).
> If there is anything I am doing wrong (or could do better) please tell me:
> 
> 
> - (NSData *)subImagePngDataWithRect: (NSRect)subRect  useColour: 
> (BOOL)useColour
> {
>       //      1.      create newSubRep (NSBitmapImageRep)
>               
>       NSString *colorSpaceName = useColour ? NSDeviceRGBColorSpace : 
> NSDeviceWhiteColorSpace; //      ??

You could get the colorSpaceName from the source image and use that. If there’s 
no conversion needed between the images it’ll probably be faster (though seems 
you are giving yourself the option of creating a grayscale version here).



>       NSInteger samplesPerPixel = useColour ? 4 : 2;  
> 
>       NSInteger pixelsWide = (NSInteger)ceil(subRect.size.width);
>       NSInteger pixelsHigh = (NSInteger)ceil(subRect.size.height);
>       NSInteger bitsPerSample = 8;    
>       NSInteger bitsPerPixel = samplesPerPixel * bitsPerSample;       
>       NSInteger bytesPerRow = pixelsWide * bitsPerPixel / 8;  
>               

In fact you can pass 0 for these last two and the function will calculate them 
for you. It’s better to do that because if there’s the slightest thing wrong 
with the parameters it will give up with an exception.
The internal calculation can also round up bytesPerRow to something that will 
optimise copying performance.


>       //       there is another initializer with bitmapFormat - don't know 
> what to use 

Unless you need a specific bitmap format, don’t worry about the other one.


>       NSBitmapImageRep *newSubRep =   [ [NSBitmapImageRep alloc]      
> initWithBitmapDataPlanes:       NULL
>                                                                               
>                 pixelsWide:                             pixelsWide
>                                                                               
>                 pixelsHigh:                             pixelsHigh
>                                                                               
>                 bitsPerSample:                  bitsPerSample 
>                                                                               
>                 samplesPerPixel:                        samplesPerPixel
>                                                                               
>                 hasAlpha:                               YES 
>                                                                               
>                 isPlanar:                                       NO      //    
>                                                                               
>                                     colorSpaceName:                         
> colorSpaceName 
>                                                                               
>                 bytesPerRow:                            bytesPerRow
>                                                                               
>                 bitsPerPixel:                           bitsPerPixel
>                                                                       ];
> 
> 
>       //      2.      create context (NSGraphicsContext) from newSubRep and 
> make it current
>       
>       NSGraphicsContext *context = [ NSGraphicsContext 
> graphicsContextWithBitmapImageRep: newSubRep ];
>       [ NSGraphicsContext setCurrentContext: context ];


You may want to save and restore the current context around this, just to be 
sure your method isn’t going to have the unwanted side effect of changing the 
current context. It’s likely OK, but better safe than sorry.


>       
>       
>       //      3.      draw allRep (NSBitmapImageRep) to currentContext
>       
>       NSBitmapImageRep *allRep = (NSBitmapImageRep 
> *)self.image.representations.firstObject;  
>       NSRect destRect = NSZeroRect; destRect.size = subRect.size;

Just use NSZeroRect for destRect. This is interpreted to mean “the size of the 
destination image”, which is already <subRect>, rounded up. If you set the size 
here and it’s not a whole number for some reason, there is the potential for 
the very edge pixels not to get set, leaving a visible edge at the right and 
bottom of the result.


>       BOOL ok =       [ allRep        drawInRect:             destRect 
>                                               fromRect:               subRect 
>                                               operation:              
> NSCompositingOperationCopy 
>                                               fraction:                       
> 1
>                                               respectFlipped: NO      //      
> ?? 
>                                               hints:                  nil
>                               ];              
>                               
>                               
>       //      4. get pngData from newSubRep
>       
>       return [ newSubRep representationUsingType: NSPNGFileType  properties: 
> @{} ];
> }
> 
> Gerriet.

Otherwise, looks good. Does it do the job?

—Graham






_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to