Re: Doubled Pixels

2017-06-25 Thread Quincey Morris
On Jun 25, 2017, at 21:28 , Gerriet M. Denkmann  wrote:
> 
>> On 26 Jun 2017, at 08:03, Graham Cox > > wrote:
>> 
>> Well, it depends on what you want to do with the image. If it’s content that 
>> gets displayed or printed, then calibrated ensures that it will look the 
>> same across a range of devices.
> 
> As my pixels are either white or black, this “Calibrated” seems not to be 
> important.
> Also: it bloats my images:
>   //  Device  subPngData  337 bytes b
>   //  Calibrated  subPngData 1434 bytes b
> So I’ll stick with “Device”.

You should pay more attention to what Graham said. It depends on what you want 
to do with the image. If you specify a device space, the images may not appear 
black, but light gray and dark gray with a color cast, with different 
distorted grays on different devices. (Colorspaces are about calibrating white 
and black as much as they are colors.)

It also depends where the pixel values are coming from. If you’re arbitrarily 
setting the pixel values to 0 or 1.0 (or 0 or 255), that doesn’t mean you’ll 
get blacks and white with *either* of those color spaces.

— If you specify “device”, the Mac will pass those raw values to the display, 
which will interpret them according to whatever colorspace it’s calibrated for.

— If you specify “calibrated”, the Mac will interpret those values in the 
standard Calibrated color space, then do a color conversion to whatever 
colorspace the display is calibrated for.

Either way, you get something that isn’t likely to be exactly white or black. 
The difference is that using Calibrated will give the same “wrong” color on all 
displays, but Device will give different “wrong” colors on different displays.

To get actual blacks and whites, you need to set the pixel values to whatever 
represents proper black and white in whatever colorspace you intend to attach 
to the image. Getting those pixel values to begin with is the tricky part.

Having said all that, I have to admit that the difference between using 
uncalibrated/misconverted whites and blacks is likely to be minor. Again, it 
depends on what you’re doing whether that’s acceptable or not.
___

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


Re: Doubled Pixels

2017-06-25 Thread Gerriet M. Denkmann

> On 26 Jun 2017, at 08:03, Graham Cox  wrote:
> 
>> On 25 Jun 2017, at 7:39 pm, Gerriet M. Denkmann  wrote:
>> 
>> Which of these two lines is preferable:
>>  NSString *colorSpaceName = useColour ? NSDeviceRGBColorSpace : 
>> NSDeviceWhiteColorSpace; 
>>  NSString *colorSpaceName = useColour ? NSCalibratedRGBColorSpace : 
>> NSCalibratedWhiteColorSpace;
>> ?
> 
> Well, it depends on what you want to do with the image. If it’s content that 
> gets displayed or printed, then calibrated ensures that it will look the same 
> across a range of devices.

As my pixels are either white or black, this “Calibrated” seems not to be 
important.
Also: it bloats my images:
//  Device  subPngData  337 bytes b
//  Calibrated  subPngData 1434 bytes b
So I’ll stick with “Device”.


>>> 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.
>> 
>> I just did. Turns out that the oldContext seems to be nil. But as you 
>> rightly said: “better safe than sorry”.
> 
> You just needs to use +[NSGraphicsContext saveGraphicsState]; and 
> +[NSGraphicsContext restoreGraphicsState]; if you know currentContext is nil, 
> it suggests you aren’t doing it that way.

Thanks. I have just updated my code.

Thanks again for your help!


Kind regards,

Gerriet.

___

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


Re: Doubled Pixels

2017-06-25 Thread Graham Cox

> On 25 Jun 2017, at 7:39 pm, Gerriet M. Denkmann  wrote:
> 
> Which of these two lines is preferable:
>   NSString *colorSpaceName = useColour ? NSDeviceRGBColorSpace : 
> NSDeviceWhiteColorSpace; 
>   NSString *colorSpaceName = useColour ? NSCalibratedRGBColorSpace : 
> NSCalibratedWhiteColorSpace;
> ?

Well, it depends on what you want to do with the image. If it’s content that 
gets displayed or printed, then calibrated ensures that it will look the same 
across a range of devices.

>> 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.
> 
> I just did. Turns out that the oldContext seems to be nil. But as you rightly 
> said: “better safe than sorry”.

You just needs to use +[NSGraphicsContext saveGraphicsState]; and 
+[NSGraphicsContext restoreGraphicsState]; if you know currentContext is nil, 
it suggests you aren’t doing it that way.

>> 
>> Just use NSZeroRect for destRect. This is interpreted to mean “the size of 
>> the destination image”, which is already , 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.
> 
> I tried this. But got a rather small image (just 88 bytes - usually 337 
> bytes) and the resulting image looks rather empty. It has the right size, but 
> not a single pixel is set - all are transparent.

OK, that’s weird. I’m not sure why that’s happening.

> But heading your warning about non-whole numbers, I added at the very start:
> 
> - (NSData *)subImagePngDataWithRect: (NSRect)suxRect  useColour: 
> (BOOL)useColour
> {
>   NSRect subRect = NSIntegralRect(suxRect);
>   …
> }

Good idea.

—G.
___

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


Re: Doubled Pixels

2017-06-25 Thread Gerriet M. Denkmann

> On 25 Jun 2017, at 09:29, Graham Cox  wrote:
> 
> 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).

The images are really b, but the source image claims to be 
NSCalibratedRGBColorSpace.
So I prefer to control the colour here and not rely on the source image.

Which of these two lines is preferable:
NSString *colorSpaceName = useColour ? NSDeviceRGBColorSpace : 
NSDeviceWhiteColorSpace; 
NSString *colorSpaceName = useColour ? NSCalibratedRGBColorSpace : 
NSCalibratedWhiteColorSpace;
?


>>  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.

I changed my code following your suggestion.


>>  [ 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.

I just did. Turns out that the oldContext seems to be nil. But as you rightly 
said: “better safe than sorry”.


>>  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 , 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.

I tried this. But got a rather small image (just 88 bytes - usually 337 bytes) 
and the resulting image looks rather empty. It has the right size, but not a 
single pixel is set - all are transparent.

But heading your warning about non-whole numbers, I added at the very start:

- (NSData *)subImagePngDataWithRect: (NSRect)suxRect  useColour: (BOOL)useColour
{
NSRect subRect = NSIntegralRect(suxRect);
…
}


> Otherwise, looks good. Does it do the job?

It did. And now it does even better.

Thanks a lot for your help. Very much appreciated!


Kind regards,

Gerriet.

___

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


Re: Doubled Pixels

2017-06-24 Thread Graham Cox

> On 24 Jun 2017, at 4:46 pm, Gerriet M. Denkmann  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 , 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 =   [ allRepdrawInRect: destRect 
>   fromRect:  

Re: Doubled Pixels

2017-06-24 Thread Gerriet M. Denkmann

> On 23 Jun 2017, at 23:37, Jens Alfke  wrote:
> 
> 
>> On Jun 23, 2017, at 8:45 AM, Gerriet M. Denkmann  wrote:
>> 
>> the image looks fine, but when I write subData to disk, it has 64 x 64 
>> pixels.
> 
> You’re probably running this on a computer with a Retina display, so NSImage 
> creates a 2x-resolution backing store by default.
Yes, you are right; I should have mentioned this.

> 
> Try creating an NSBitmapImageRep directly, then focus on it and draw.
> —Jens

> 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!

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; //  ??
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;  

//   there is another initializer with bitmapFormat - don't know 
what to use 
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 ];


//  3.  draw allRep (NSBitmapImageRep) to currentContext

NSBitmapImageRep *allRep = (NSBitmapImageRep 
*)self.image.representations.firstObject;  
NSRect destRect = NSZeroRect; destRect.size = subRect.size;
BOOL ok =   [ allRepdrawInRect: destRect 
fromRect:   subRect 
operation:  
NSCompositingOperationCopy 
fraction:   
1
respectFlipped: NO  //  
?? 
hints:  nil
];  


//  4. get pngData from newSubRep

return [ newSubRep representationUsingType: NSPNGFileType  properties: 
@{} ];
}

Gerriet.


___

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


Re: Doubled Pixels

2017-06-23 Thread Jeff Szuhay
For a different reason, I’ve posted the most complete CGBitmapContext example
I’ve seen anywhere (which is why I posted it). You can see it here

http://www.blinddogsoftware.com/goodies/#DontSpillTheBits

and customize to your needs.

You can ignore the CGLayers, CGImage, and CIImage effects. The bitmap context
creation is what you want to look at.


> On Jun 23, 2017, at 5:11 PM, Graham Cox  wrote:
> 
> 
>> On 24 Jun 2017, at 1:45 am, Gerriet M. Denkmann  wrote:
>> 
>> the image looks fine, but when I write subData to disk, it has 64 x 64 
>> pixels.
> 
> 
> By making the NSBitMapRepresentation yourself, creating a context for it, 
> drawing to that.
> 
> If you make it yourself using the long-winded but complete initializer, you 
> have total control. Any of the other ‘convenience’ methods do various things 
> that you can’t see, are poorly documented, and give unexpected results. Even 
> when they work today their implementations change and one day might do 
> something else, suddenly breaking your code. I’ve certainly had that happen 
> when Retina screen came out for example, and had to go back and do it using 
> the long initializer so I got what I asked for.
> 
> —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/jeff%40szuhay.org
> 
> This email sent to j...@szuhay.org

___

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


Re: Doubled Pixels

2017-06-23 Thread Graham Cox

> On 24 Jun 2017, at 1:45 am, Gerriet M. Denkmann  wrote:
> 
> the image looks fine, but when I write subData to disk, it has 64 x 64 pixels.


By making the NSBitMapRepresentation yourself, creating a context for it, 
drawing to that.

If you make it yourself using the long-winded but complete initializer, you 
have total control. Any of the other ‘convenience’ methods do various things 
that you can’t see, are poorly documented, and give unexpected results. Even 
when they work today their implementations change and one day might do 
something else, suddenly breaking your code. I’ve certainly had that happen 
when Retina screen came out for example, and had to go back and do it using the 
long initializer so I got what I asked for.

—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


Doubled Pixels

2017-06-23 Thread Gerriet M. Denkmann
macOS 12.5

I try to make a sub image (subRect has size 32 x 32) like:

NSRect pubRect = NSZeroRect; pubRect.size = subRect.size;
NSImage *subImage = [ [NSImage alloc] initWithSize: subRect.size ];

[ subImage lockFocus ];
[ self.imagedrawAtPoint:NSMakePoint(0, 0)  
fromRect:   subRect  
operation:  
NSCompositingOperationCopy  
fraction:   1 
];
NSBitmapImageRep *oneRep = [ [ NSBitmapImageRep alloc ] 
initWithFocusedViewRect: pubRect ];
[ subImage unlockFocus ];

NSData *subData = [ oneRep representationUsingType: NSPNGFileType  properties: 
@{} ];

the image looks fine, but when I write subData to disk, it has 64 x 64 pixels.

How can this doubling of pixels be avoided?

Gerriet.

___

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