NSColorPanel to hex issue? - nscolor

I have an NSColorPanel that I am inputting RGV values:
NSColorPanel * sharedPanel = [NSColorPanel sharedColorPanel];
[sharedPanel setTarget: self];
[sharedPanel setAction: updateColor:];
[sharedPanel orderFront: self];
The color panel display and I set this value: r66, g114, b170
By my calculations, this should be #4272AA. I use the following code to convert to hex:
- (void) updateColor: (NSColorPanel*) panel
{
NSString * hexString = [panel.color hexadecimalValueOfAnNSColor];
NSLog(#"%#", hexString);
}
Which logs out #345d9a (not what I would expect).
I'm using the following method from directly from developer.apple.com to convert the color to hex:
#import <Cocoa/Cocoa.h>
#interface NSColor(NSColorHexadecimalValue)
-(NSString *)hexadecimalValueOfAnNSColor;
#end
#implementation NSColor(NSColorHexadecimalValue)
-(NSString *)hexadecimalValueOfAnNSColor
{
float redFloatValue, greenFloatValue, blueFloatValue;
int redIntValue, greenIntValue, blueIntValue;
NSString *redHexValue, *greenHexValue, *blueHexValue;
//Convert the NSColor to the RGB color space before we can access its components
NSColor *convertedColor=[self colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
if(convertedColor)
{
// Get the red, green, and blue components of the color
[convertedColor getRed:&redFloatValue green:&greenFloatValue blue:&blueFloatValue alpha:NULL];
// Convert the components to numbers (unsigned decimal integer) between 0 and 255
redIntValue=redFloatValue*255.99999f;
greenIntValue=greenFloatValue*255.99999f;
blueIntValue=blueFloatValue*255.99999f;
// Convert the numbers to hex strings
redHexValue=[NSString stringWithFormat:#"%02x", redIntValue];
greenHexValue=[NSString stringWithFormat:#"%02x", greenIntValue];
blueHexValue=[NSString stringWithFormat:#"%02x", blueIntValue];
// Concatenate the red, green, and blue components' hex strings together with a "#"
return [NSString stringWithFormat:#"#%#%#%#", redHexValue, greenHexValue, blueHexValue];
}
return nil;
}
#end
Any suggestions as to what I'm doing wrong?

You must have entered coordinates in different color space (probably device's, since on my Mac, #4272AA in color space of my display when converted to calibrated color space produces almost the same result, #345C9A).
To change color space in NSColorPanel, click tiny rainbow button. NSCalibratedRGBColorSpace corresponds to "Generic RGB" selection — since your get-hex method uses calibrated, you need to use the same if you want to get the same numbers back.
A tiny bit of warning: this piece of code from developer.apple.com is harmful.
When people say hex codes to each other, it is almost universally assumed to mean the same color as HTML/CSS would produce. This means hex codes must be in sRGB color space, since web standards dictate to use sRGB whenever color space information is omitted/missing.
Apple's "Generic RGB" (NSCalibratedRGBColorSpace) is very different from sRGB and native color spaces of most modern displays. Your problem just demonstrates how huge that difference is.
Most of displays in the world are manufactured to match sRGB as best as possible, and high quality displays of modern Apple's devices are particularly good at that.
This leads to somewhat surprising conclusion: if need those hex codes to produce same colors as in HTML, using NSDeviceRGBColorSpace, however wrong that is, instead of NSCalibratedRGBColorSpace gives much better results. You can easily verify that fact by entering the same color coordinates in Device, Generic and sRGB color spaces and comparing to what HTML page in Safari produces.
If you need correct and guaranteed match with hex codes used in Web, you will have to do color conversion to sRGB manually, since NSColor does not support reading components for any color profiles other than Device RGB and Calibrated RGB.

Related

Load and Save opaque 8 bit PNG Files using ImageSharp

I am trying to Load -> Manipulate byte array directly -> Save an 8 bit png image.
I would like to use ImageSharp to compare its speeds to my current library, however in their code example they require the pixel type to be defined (they use Rgba32):
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
// Image.Load(string path) is a shortcut for our default type.
// Other pixel formats use Image.Load<TPixel>(string path))
using (Image<Rgba32> image = Image.Load("foo.jpg"))
{
image.Mutate(x => x
.Resize(image.Width / 2, image.Height / 2)
.Grayscale());
image.Save("bar.jpg"); // Automatic encoder selected based on extension.
}
I looked through the pixel types: https://github.com/SixLabors/ImageSharp/tree/master/src/ImageSharp/PixelFormats
But there is no grayscale 8 bit pixel type.
As of 1.0.0-beta0005 There's no Gray8 pixel format because we couldn't decide what color model to use when converting from Rgb (We need that internally). ITU-R Recommendation BT.709 seems like the sensible solution because that is what png supports and what we use when saving an image as an 8bit grayscale png so it's on my TODO list.
https://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
So... currently you need to use either Rgb24 or Rgba32 when decoding the images.
Update.
As of 1.0.0-dev002094 this is now possible! We have two new pixel formats. Gray8 and Gray16 that carry only the luminance component of a pixel.
using (Image<Gray8> image = Image.Load<Gray8>("foo.png"))
{
image.Mutate(x => x
.Resize(image.Width / 2, image.Height / 2));
image.Save("bar.png");
}
Note. The png encoder by default will save the image in the input color type and bit depth. If you want to encode the image in a different color type you will need to new up an PngEncoder instance with the ColorType and BitDepth properties set.

Windows Small System Icon Height Incorrect

I'm running on Windows 10, but using Delphi 7 (yes, I know it's quite old).
I want to use the system icons in Windows and have gone about this by defining a TImageList called SystemIcons which I initialize as follows:
var
fileInfo: TSHFileInfo;
begin
SystemIcons.Handle := ShGetFileInfo('', 0, fileInfo, SizeOf(fileInfo),
SHGFI_ICON or SHGFI_SMALLICON or SHGFI_SYSICONINDEX);
...
I have SystemIcons properties set statically as a TImageList component with width and height set to 16.
Elsewhere, I wish to retrieve an icon from this image list given a valid shell object's image index. Because these are "small system icons", I expect them to be 16x16. The result of calling GetSystemMetrics(SM_CYSMICON) yields 16. Oddly, the dimensions depend upon whether I retrieve them as a bitmap or an icon.
...
var
icon: TIcon;
bm: TBitmap;
begin
...
icon := TIcon.Create;
SystemIcons.GetIcon(imgIndex, icon);
bm := TBitmap.Create;
SystemIcons.GetBitmap(imgIndex, bm);
The imgIndex is correct and the same in both cases. The image retrieved is the same in each case, as expected. The dimensions of the bitmap (bm.Width and bm.Height) are also as expected: 16x16. However, the dimensions of the icon (icon.Width and icon.Height) are not. They are 32x32.
When I paint the icon on a canvas it appears as 16x16. So it's only its Height and Width values that appear incorrect. Very odd.
Why are these different?
The images are likely actually 32x32 to begin with.
Internally, TImageList.GetIcon() simply retrieves an HICON for the chosen image directly from the underlying Win32 ImageList API, using ImageList_GetIcon(), and assigns that to the TIcon.Handle property.
TImageList.GetBitmap(), on the other hand, is a bit different. It sizes the TBitmap to the dimensions of the TImageList (16x16), and then stretch draws the chosen image onto the TBitmap.Canvas using TImageList.Draw(), which in turn uses ImageList_DrawEx().

make the middle letter blink

I've already solved this by not displaying the last letter of the word then locating the last letter and making it blink then I displayed the word inversely minus the last letter of course.
#include<string.h>
#include<conio.h>
#include<iostream.h>
#include<stdio.h>
char text[255];
int txtposition,txtlength;
void main()
{
clrscr();
gets(text);
txtlength=strlen(text);
char lastchar=text[txtlength-1];
cout<<"Your text is: ";
for(txtposition=0;txtposition<txtlength-1;txtposition++)
{
cout<<text[txtposition];
}
textcolor(WHITE+128);
cprintf("%c", lastchar);
for(txtposition=txtlength-2;txtposition>=0;txtposition--)
{
cout<<text[txtposition];
}
getch();
}
Thank you for all your help!
To make the middle character blink, either your output terminal needs to be capable to present blinking characters using a special terminal control code as described here, or use the gotoxy() function from a separate thread, that displays a ' ' or the actual character, alternating for a specific blink frequency.
The standard C++ library does not provide any facility for making characters blink.
You can do that in platform-specific ways, but it's worth noting that Windows console windows do not (as far as I know) directly support text blinking, like the original IBM PC's text screen mode did. On the original IBM PC one bit of the color specification could be configured to either yield high intensity or blinking, with blinking control as the default. I always reconfigured it to high intensity in my programs, and in the corresponding mechanism for Windows console windows the bits always determine color.
So, it would be complicated to do even in Windows, unless you're running in a DOSBox, which emulates the old PC. I don't know what functionality it offers. Maybe it even does blinking.
But you can easily mark the relevant letters in other ways.
For example, you could use
uppercase versus lowercase,
underlining characters placed on the next line,
parentheses (as you did in your example here),
colors (platform specific),
a different font, boldness, whatever.
I recommend updating to a modern compiler, if you have an ordinary modern PC. Compilers are free. Also you need better learning material, e.g. void main is non-standard and is only accepted by a few compilers.
Looks like for Turbo C/C++ you can you use the Graphics library and/or builtin conio functions. ( https://answers.yahoo.com/question/index?qid=20080813072809AAEguz0 )
But the above is not portable as the graphics library is specific to Turbo and conio is specific to some dos based compilers/libraries.
If you move to the a complier like gcc/g++ then you might want to look at curses library: http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/

Qt-Application is killing characters accidentally (drawText produces bug)

I've got a really simple application for adding watermarks to pictures. So you can drop your pictures in a QListWidget which shows you a thumbnail and the path, adjust some things like the text, the transparency, the output format and so on.. and after pressing start it saves the copyrighted picture in a destination of your choice. This works with a QPainter which paints the logo and text on the picture.
Everything is able to work fine. But here's the misterious bug:
The application kills random letters. It's really strange, because I can't reproduce it. With every execution and combination of options it's different. For example:
Sometimes I can't write some letters in the QLineEdit of my interface (like E, 4 and 0 doesnt exist, or he changes the letters so some special signs).
The text of the items in the QListWidget aren't completly displayed, sometimes completley missing. But I can extract the text normally and use the path.
While execution I have a QTextBrowser as a log to display some interesting things like the font size. Although, the font is shown normaly on the resulting picture, it says " 4" or "6" instead of much higher and correct sizes. Betimes strange white blocks appear between some letters
When drawing text on the picture with a QPainter, there also letters missing. Sometimes, all the letters are printed over each other. It seems like this bug appears more often when using small pixelsizes (like 12):
//Text//
int fontSize = (watermarkHeight-(4*frame));
int fontX = 2*frame;
int fontY = (result.height()-(watermarkHeight-2*frame));
int fontWidth = watermarkWidth;
QRect place(fontX,fontY,fontWidth,fontSize);
QFont font("Helvetica Neue", QFont::Light);
font.setPixelSize(fontSize);
emit log(QString::number(fontSize));
pixPaint.setFont(font);
pixPaint.setPen(QColor(255,255,255,textOpacity));
pixPaint.drawText(place,text);
Not all of these bugs appear at once! Sometimes I haven't got any bugs...
Perhaps someone had a similar bug before. Unfortunately I didn't found something like this in the internet. I didn't post a lot of code snippets because I think (and hope) that this is a gerneral problem. If you need something specific to help me, please let me know =)
I've added a example picture:
In the lineEdit I simply wrote ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 (look what he has done with the 7 and 9)
This small square in the lower corner of the picture should be the "ABC..." thing
The "62" looks very strange in the textBrowser
I'm using Qt 5.0.1 on a Windows 7 64Bit computer.
EDIT: Everytime after adding the first picture to the list, he's finding these warnings:
QFontEngine::loadEngine: GetTextMetrics failed ()
QWindowsFontEngine: GetTextMetrics failed ()
But when I change the height (and with it the pointSize of the font) its not emitted anymore, even with the start-parameters.
EDIT 2: Thank you for your help! I corrected my code so that he only uses correct fonts and correct sizes, but it still doesn't work. When I remove the QPainter::drawText() function it works fine (without the text). But as soon as I am adding text everything is bugged. I have something like this now:
//Text//
QList<int> smoothSizes = fontDatabase->smoothSizes("Verdana","Standard");
int fontSize = (watermarkHeight-(4*frame))*0.75;
emit log("Requested: "+QString::number(fontSize));
if(!smoothSizes.contains(fontSize)){
for(int i = 0; i<smoothSizes.length(); i++){
if(smoothSizes.at(i) > fontSize && i>0){
fontSize = smoothSizes.at(i-1);
break;
}
}
}
int fontX = 2*frame;
int fontY = (result.height()-(watermarkHeight/2)+frame);
QFont font = fontDatabase->font("Verdana","Standard",fontSize);
QFontInfo info(font);
emit log("Corrected: "+QString::number(fontSize));
emit log("Okay?: "+QString::number(info.exactMatch()));
pixPaint.setFont(font);
const QFontMetrics fontMetrics = pixPaint.fontMetrics();
if(info.exactMatch()){
pixPaint.setPen(QColor(255,255,255,textOpacity));
pixPaint.drawText(fontX,fontY+(fontMetrics.height()-fontMetrics.ascent()),text);
}
It almost sounds like you are corrupting random memory in your process, or you have a badly broken Windows install. Possibly your font request is matched by a very poorly chosen system font.
Whatever is set on a QFont is merely a request. To obtain the parameters of the actual font that was selected, you must create a QFontInfo, and get your information from there.
Imagine that you request a QFont that doesn't exist on a system, or that can't be scaled to a particular size. At some point the font object would need to morph to reflect what really happened - this would be very confusing. Thus, the QFontInfo provides the information about the font that was actually used. Think of QFontInfo as a response, and QFont as a request.
I finally found a solution: I simply updated Qt from 5.0.1 to 5.2.1, now it works. Perhaps someone has a similar bug and this post helps him. Thank you for your help!

Strange problem about conversion between GDI+ to GDI: Bitmap and HBitmap

I want to convert gdi+ Bitmap into gdi object HBitmap.
I am using the following method:
Bitmap* img = new Bitmap(XXX);
// lots of codes...
HBITMAP temp;
Color color;
img->GetHBITMAP(color, &temp);
the img object is drawing on a dialog.
when this part of method is called, strange thing happens!
the img displaying in the window changed!
It become a bit clearer or sharper.
My question is what happens?
The bitmap pixel format may be the reason. Do you specify it explicitly in the Bitmap constructor?
Gdiplus::Bitmap bmp(WIDTH, HEIGHT, PixelFormat24bppRGB);
Try making sure that all the pixel formats you use are the same.
Another reason may be the differences in Gdiplus::Graphics interpolation modes in your code. That attribute determines how the images are resized, how the lines are drawn, etc.
m_pViewPortImage = new Gdiplus::Bitmap(
observedWidth,
observedHeight,
PixelFormat24bppRGB
);
Gdiplus::Graphics gr(m_pViewPortImage);
gr.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);

Resources