2016-02-06 2 views
5

Я написал фрагмент кода, который позволяет мне получить цвет затенения определенной ячейки внутри листа книги Excel. Я успешно получил значение целочисленного значения RGB, запустив COM-сервер, используя MATLAB's actxserver, а затем обратился к Color Property внутреннего объекта этого конкретного объекта ячейки. Затем я получаю эквивалентный триплет RGB этого целого числа, поэтому я могу использовать его позже для построения в MATLAB.Interior.Color Property инвертирует цвета?

Для того, чтобы проверить, что мой код работает правильно, я разработал следующий тест: Я создал книгу Excel под названием colorTest.xlsx с 8 различных цветов:

enter image description here

Затем я запускаю мой код MATLAB, который извлекает цветную информацию о каждой ячейке столбца B. Я должен получить сюжет с цветами в том же вертикальном порядке и таблицу со значением int и триплет RGB каждого цвета.

Однако случается что-то неожиданное! Посмотрите на результаты:

enter image description here

Обратите внимание, что целое значение, которое получается из цвета собственности не всегда совпадает с цветом исходной клетки, для черного, белого, зеленого и пурпурного целые значения являются правильно, но это не относится ко всем другим цветам. Например, вы можете видеть, что для красного цвета в Excel выходные тэп и триггер RGB соответствуют синему цвету.

я добавил следующую таблицу с правильными результатами я должен получить, для справки:

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 

я получил правильные значения целых чисел, для каждого цвета, используя this RGB Int Calculator.

Если мы сравним две таблицы, мы можем сделать вывод, что обратные и красные каналы инвертированы.

Код:

Функция, которую я выполняю, чтобы запустить тест называется getCellColor. Посмотрите на код:

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 

(*) Эта инструкция отвечает за восстановление целочисленного цвета.


Примечание: Функция, описанная в следующем, не вызывает проблемы, так какони не принимают участие в получении цветного целого числа (они используются только для вторичных задач). Я включил эту информацию только для полноты.

В ходе этого процесса я использую три частные функции из iofun папку MATLAB, которая является: validpath, xlsCleanup и openExcelWorkbook. Я просто скопировал их в папку с именем private внутри папки проекта.

Наконец, чтобы получить триплет RGB из целочисленного цвета, я использую функцию, которую я адаптировал из this other 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 

Я пытаюсь сделать какой-то смысл из этого, но я действительно не имеют ни малейшего представления о том, что происходит. Я провел некоторое исследование, но не очень повезло, но this post и this other post привлекло мое внимание. Может быть, это имеет какое-то отношение к моей проблеме.

Значит, свойство Interior.Color действительно инвертирует цвета?

Если это так, следует ли считать это нормальным поведением или это ошибка?


Ссылка для скачивания файла:

Я заполнила весь проект на файл .zip и загрузил его, так что вы можете запустить этот тест на вашей машине сразу. Загрузите файл и распакуйте его.

getCellColor.zip

+0

Теперь вы можете вносить изменения в палитру Excel? Я нашел это полезным. К сожалению, у меня нет Matlab, чтобы решить это самостоятельно: [link] (http://www.cpearson.com/excel/colors.aspx) --- Вы изменяете значения в палитре по умолчанию, изменяя массив цветов Объект рабочей книги. Например, чтобы изменить цвет, на который ссылается значение ColorIndex 3 на синий, используйте ==> 'Workbooks (« SomeBook.xls »). Цвета (3) = RGB (0,0,255)' –

+0

Я никогда не видел эту проблему с Interior.Color. Я предполагаю, что ваше преобразование RGB-int обратное. Вот как я конвертирую RGB в int, когда я устанавливаю Interior.Color: 'longColor = rgbColor * [1 256 256 * 256] ';'. Работает для любого цвета, который вам нравится. – buzjwa

+0

Теперь я проверил ваш метод 'int2rgb'. Он действительно инвертирует R и B. – buzjwa

ответ

2

Из MSDN article на RGB Color Model:

Цветовая модель RGB используется для указания цветов. Эта модель определяет интенсивность красного, зеленого и синего цветов по шкале от 0 до 255, при этом 0 (ноль) указывает минимальную интенсивность. Установки трех цветов преобразуются в одно целое число, используя эту формулу:

значение RGB = Красный + (зеленый * 256) + (синий * 256 * 256)

В этом было предложено в chris neilsen answer, нет «правильного» или «неправильного» с точки зрения цветового кодирования. Microsoft выбрала именно этот способ кодирования цветов по причинам, которые только они знают, и я должен придерживаться этого.

Таким образом, значения RGB, которые я получаю, полностью верны.

В следующей таблице я включил значения RGB, представленные в статье MSDN, рядом с теми, которые я получаю в MATLAB, и они идеально подходят.

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 
3

Ваш метод int2rgb инвертирует R и B. Замените их, и вы получите правильное преобразование. Свойство Interior.Color использует соглашение, где R является наименее значимым, а используемая вами функция FileExchange использует противоположное соглашение.

Для преобразования из RGB в ИНТ:

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

Для преобразования из RGB в целое:

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

Моя первая мысль проверить порядок каналов RGB против BGR.

Возможно, вы, возможно, упростите функцию int2rgb, используя вместо этого typecast. Вот пример, используя значения, размещенные:

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

Выход:

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 
5

Там нет «правильных» или «неправильно» здесь, Matlab и Excel просто кодировать цвет по-разному. Вы должны учитывать это в своем коде.

Ближайший я могу найти официальный источник в этой статье MSDN, примерно на полпути вниз увидеть пример кодирования «голубых»

MSDN article

Следующие примеры задают внутренность выбор ячеек в синий цвет. Selection.Interior.Color = 16711680
Selection.Interior.Color = & HFF0000
Selection.Interior.Color = & O77600000
Selection.Interior.Color = RGB (0, 0, 255)

+0

Это удивительно. Я думал, что цветовая кодировка для всех одинакова, как своего рода стандарт. – codeaviator