简体   繁体   English

Interior.Color属性反转颜色?

[英]Interior.Color Property inverts colors?

I have written a piece of code that allows me to retrieve the shading color of a specific cell inside a sheet of an excel workbook. 我编写了一段代码,允许我检索excel工作簿中的特定单元格的着色颜色。 I have successfully retrieved the RGB integer value by starting a COM server using MATLAB's actxserver , and then accessing the Color Property of the Interior Object of that particular Cell Object. 我已成功检索RGB整数值,方法是使用MATLAB的actxserver启动COM服务器,然后访问该特定Cell对象的Interior Object的Color属性 Then I obtain the equivalent RGB triplet of that integer, so I can use it later for plotting in MATLAB. 然后我获得该整数的等效RGB三元组,因此我可以稍后在MATLAB中使用它进行绘图。

In order to test that my code works properly I designed the following test: I created an Excel workbook called colorTest.xlsx with 8 different colors: 为了测试我的代码是否正常工作,我设计了以下测试:我创建了一个名为colorTest.xlsx的Excel工作簿, colorTest.xlsx有8种不同的颜色:

在此输入图像描述

Then I run my MATLAB code, which extracts the color information on each cell of the B column. 然后我运行我的MATLAB代码,它提取B列的每个单元格的颜色信息。 I should get a plot with the colors on the same vertical order and a table with the int value and the RGB triplet of each color. 我应该得到一个带有相同垂直顺序颜色的图和一个带有int值和每种颜色的RGB三元组的表。

However something unexpected happens! 然而出乎意料的事情! Look at the results: 看看结果:

在此输入图像描述

Notice that the integer value that is obtained from the Color Property does not always match the color of the original cell, for black, white, green and magenta the integer values are correct, but this is not true for all the other colors. 请注意,从Color属性获取的整数值并不总是与原始单元格的颜色匹配,对于黑色,白色,绿色和洋红色,整数值是正确的,但对于所有其他颜色则不然。 You can see, for example, that for red color on the Excel, the output int and RGB triplet correspond to blue color. 例如,您可以看到,对于Excel上的红色,输出int和RGB三元组对应于蓝色。

I have added the following table with the correct results I should get, for reference: 我已经添加了下表,我应该得到正确的结果,以供参考:

Color        Int         R G B
--------     --------    -----
Black               0    0 0 0
White        16777215    1 1 1
Red          16711680    1 0 0
Green           65280    0 1 0
Blue              255    0 0 1
Cyan            65535    0 1 1
Magenta      16711935    1 0 1
Yellow       16776960    1 1 0

I obtained the correct integer values for each color using this RGB Int Calculator . 我使用RGB Int计算器为每种颜色获得了正确的整数值。

If we compare the two tables, we can deduce that the Red and Blue channels are inverted . 如果我们比较两个表,我们可以推断红色和蓝色通道是反转的

The code: 代码:

The function that I execute to run the test is called getCellColor . 我执行以运行测试的函数称为getCellColor Have a look at the code: 看看代码:

function getCellColor()
clear all;
clc;

% Excel
filename = 'colorTest.xlsx';

% Start Excel as ActiveX server process on local host
Excel = actxserver('Excel.Application');

% Handle requested Excel workbook filename
path = validpath(filename);

% Cleanup tasks upon function completion
cleanUp = onCleanup(@()xlsCleanup(Excel, path));

% Open Excel workbook.
readOnly = true;
[~, workbookHandle] = openExcelWorkbook (Excel, path, readOnly);

% Initialise worksheets object
workSheets = workbookHandle.Worksheets;

% Get the sheet object (sheet #1)
sheet = get(workSheets,'item',1);

% Print table headers
fprintf('Color   \t Int     \t R G B\n');
fprintf('--------\t --------\t -----\n');

% Create figure
figure;
hold on;

% Loop through every color on the Excel file
for row = 1:8
    % Get the cell object with name of color
    cell = get(sheet, 'Cells', row, 1);
    cName = cell.value;

    % Get the cell object with colored background
    cell = get(sheet, 'Cells', row, 2);

    % Get the interior object
    interior = cell.Interior;

    % Get the color integer property
    cInt = get(interior, 'Color');  % <-- Pay special attention here(*)

    % Get the RGB triplet from its integer value
    cRGB = int2rgb(cInt);

    % Plot the color
    patch([0 0 1 1], [8-row 9-row 9-row 8-row], cRGB);

    % Print row with color data
    fprintf('%-8s\t %8d\t %d %d %d\n', cName, cInt, cRGB);
end

% Turn off axes
set(findobj(gcf, 'type','axes'), 'Visible','off')

end

(*) This instruction is responsible of recovering the color integer. (*)该指令负责恢复颜色整数。


Note: The functions described next, do not cause the problem since they do not take part in the obtaining of the color integer (they are only used for secondary tasks). 注意: 下面描述的功能不会导致问题,因为它们不参与获取颜色整数 (它们仅用于辅助任务)。 I have included this information only for completeness. 我仅包含此信息是为了完整性。

During this process I use three private functions from the MATLAB's iofun folder, which are: validpath , xlsCleanup and openExcelWorkbook . 在这个过程中,我使用MATLAB的iofun文件夹中的三个私有函数,它们是: validpathxlsCleanupopenExcelWorkbook I simply copied them into a folder called private inside the project folder. 我只是将它们复制到项目文件夹中名为private的文件夹中。

Finally, to obtain the RGB triplet from the color integer, I use a function which I adapted from this other function that I found on the net. 最后,为了从颜色整数中获取RGB三元组,我使用了一个函数,我从网上找到的其他函数改编而来。

Here is the code for my int2rgb function: 这是我的int2rgb函数的代码:

function[RGB] = int2rgb(colorInt)
% Returns RGB triplet of an RGB integer.

if colorInt > 16777215 || colorInt < 0
    error ('Invalid int value. Valid range: 0 <= value <= 16777215')
end
R = floor(colorInt / (256*256));
G = floor((colorInt - R*256*256)/256);
B = colorInt - R*256*256 - G*256;

RGB = [R, G, B]/255;
end

I am trying to make some sense out of this, but I really have no idea of what is happening. 我试图弄清楚这一点,但我真的不知道发生了什么。 I have done some research, without much luck, but this post and this other post caught my attention. 我做了一些研究,没有太多运气,但这篇文章另一篇文章引起了我的注意。 Maybe it has something to do with my problem. 也许它与我的问题有关。

So does the Interior.Color Property really inverts colors? 那么Interior.Color属性是否真的颠倒了颜色?

If this is the case, should I consider this as normal behavior or is this a bug? 如果是这种情况,我应该将此视为正常行为还是这是一个错误?


Link to download: 链接下载:

I have packed the entire project on a .zip file and uploaded it, so you can run this test on your machine straight away. 我已将整个项目打包到.zip文件上并上传,因此您可以立即在您的计算机上运行此测试。 Download the file and unpack. 下载文件并解压缩。

getCellColor.zip getCellColor.zip

There is no "right" or "wrong" here, Matlab and Excel just encode color differently. 这里没有“正确”或“错误”,Matlab和Excel只是对颜色进行不同的编码。 You need to account for that in your code. 您需要在代码中考虑到这一点。

The closest I can find to an official source is this MSDN article, about half way down see the example of encoding of "blue" 我能找到的最接近官方来源的是这篇MSDN文章,大约一半下来看到“蓝色”编码的例子

MSDN article MSDN文章

The following examples set the interior of a selection of cells to the color blue. 以下示例将选定单元格的内部设置为蓝色。 Selection.Interior.Color = 16711680 Selection.Interior.Color = 16711680
Selection.Interior.Color = &HFF0000 Selection.Interior.Color =&HFF0000
Selection.Interior.Color = &O77600000 Selection.Interior.Color =&O77600000
Selection.Interior.Color = RGB(0, 0, 255) Selection.Interior.Color = RGB(0,0,255)

My first thought is check the channels order RGB vs. BGR. 我的第一个想法是检查频道顺序RGB与BGR。

You could probably simplify that int2rgb function by using typecast instead. 您可以通过使用typecast来简化int2rgb函数。 Here's an example using the values you posted: 以下是使用您发布的值的示例:

clrs = [0; 16777215; 16711680; 65280; 255; 65535; 16711935; 16776960]
for i=1:numel(clrs)
    bgra = typecast(int32(clrs(i)), 'uint8')
end

The output: 输出:

clrs =
           0
    16777215
    16711680
       65280
         255
       65535
    16711935
    16776960

bgra =
    0    0    0    0
bgra =
  255  255  255    0
bgra =
    0    0  255    0
bgra =
    0  255    0    0
bgra =
  255    0    0    0
bgra =
  255  255    0    0
bgra =
  255    0  255    0
bgra =
    0  255  255    0

Your int2rgb method inverts R and B. Replace them and you'll get the right conversion. 你的int2rgb方法反转了R和B.替换它们,你将得到正确的转换。 The Interior.Color property uses the convention where R is the least significant, while the FileExchange function you used uses the opposite convention. Interior.Color属性使用R是最不重要的约定,而您使用的FileExchange函数使用相反的约定。

To convert from int to RGB: 要从int转换为RGB:

B = floor(colorInt / (256*256));
G = floor((colorInt - B*256*256)/256);
R = colorInt - B*256*256 - G*256;
colorRGB = [R G B];

To convert from RGB to int: 要从RGB转换为int:

colorInt = colorRGB * [1 256 256*256]';

From the MSDN article on RGB Color Model: 从关于RGB颜色模型的MSDN文章

The RGB color model is used for specifying colors. RGB颜色模型用于指定颜色。 This model specifies the intensity of red, green, and blue on a scale of 0 to 255, with 0 (zero) indicating the minimum intensity. 此模型以0到255的等级指定红色,绿色和蓝色的强度,0(零)表示最小强度。 The settings of the three colors are converted to a single integer value by using this formula: 使用以下公式将三种颜色的设置转换为单个整数值:

RGB value = Red + (Green*256) + (Blue*256*256) RGB值=红色+(绿色* 256)+(蓝色* 256 * 256)

As it was suggested in chris neilsen answer , there is no "right" or "wrong" in terms of color encoding. 正如在chris neilsen的回答中所建议的那样 ,在颜色编码方面没有“正确”或“错误”。 Microsoft has chosen this particular way to encode colors for reasons only they know, and I should stick to it. 微软选择这种特殊的方式来编码颜色只是因为他们知道的原因,我应该坚持下去。

So the RGB values that I get are totally correct. 所以我得到的RGB值是完全正确的。

In the following table, I have included the RGB values provided in the MSDN article next to the ones that I get in MATLAB, and they are a perfect match. 在下表中,我已经在MSDN文章中提供了我在MATLAB中获得的RGB值,它们是完美的匹配。

Color        Int         RGB values from MSDN
--------     --------    --------
Black               0           0
White        16777215    16777215
Red               255         255
Green           65280       65280
Blue         16711680    16711680
Cyan         16776960    16776960
Magenta      16711935    16711935
Yellow          65535       65535

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM