2016-02-06 21 views
5

Napisałem fragment kodu, który pozwala mi pobrać kolor cieniowania określonej komórki wewnątrz arkusza skoroszytu programu Excel. Pomyślnie pobrałem wartość całkowitą RGB, uruchamiając serwer COM, używając MATLAB-a actxserver, a następnie uzyskując dostęp do obiektu Color Property obiektu wewnętrznego tego konkretnego obiektu komórki. Następnie otrzymuję równoważny triplet RGB tej liczby całkowitej, więc mogę go później użyć do kreślenia w MATLAB.Interior.Color Property odwraca kolory?

W celu sprawdzenia, że ​​mój kod działa poprawnie Zaprojektowałem następujący test: Założyłem skoroszytu programu Excel o nazwie colorTest.xlsx z 8 różnych kolorach:

enter image description here

Potem biegnę mój kod Matlab, który wydobywa informacje o kolorze w każdej komórce kolumny B. Powinienem uzyskać wykres z kolorami w tej samej kolejności pionowej i tabelą z wartością int i trójką RGB dla każdego koloru.

Coś jednak nieoczekiwanego! Spojrzeć na wyniki:

enter image description here

Zauważ, że wartość całkowita, która jest uzyskiwana z własności kolor nie zawsze pasuje do koloru oryginalnego ogniwa, na czarnym, białym, zielonym i purpurowym wartości całkowite są poprawne, ale nie dotyczy to wszystkich pozostałych kolorów. Możesz zobaczyć, na przykład, że dla koloru czerwonego w Excelu, wyjście tri i tryplet RGB odpowiadają kolorowi niebieskim.

I dodaje się w poniższej tabeli do odpowiednich wyników należy uzyskać, dla odniesienia:

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 

że uzyskuje się odpowiednie wartości całkowite dla każdej barwy z wykorzystaniem this RGB Int Calculator.

Jeśli porównamy dwie tabele, możemy wywnioskować, że kanały Red i Blue są odwrócone.

Kod:

Funkcja że wykonać, aby uruchomić test nazywa getCellColor. Spójrz na kod:

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 

(*) Ta instrukcja jest odpowiedzialna za odzyskanie liczby całkowitej.


Uwaga: Funkcje opisane dalej, nie powodują problemu od nie biorą udziału w uzyskaniem całkowitej koloru (są one stosowane tylko dla zadań wtórna). Zawarłem te informacje tylko dla kompletności.

Podczas tego procesu używam trzy prywatne funkcji z iofun folderze MATLAB za, którymi są: validpath, xlsCleanup i openExcelWorkbook. Po prostu skopiowałem je do folderu o nazwie private w folderze projektu.

Wreszcie, aby uzyskać triplet RGB z kolorowej liczby całkowitej, używam funkcji, którą dostosowałem z this other function, którą znalazłem w Internecie.

Oto kod dla mojego int2rgb funkcji:

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 

Staram się zrobić coś sensownego z tego, ale naprawdę nie mam pojęcia, co się dzieje. Zrobiłem kilka badań, bez powodzenia, ale moją uwagę zwróciły this post i this other post. Może ma to coś wspólnego z moim problemem.

A więc właściwość Interior.Color naprawdę odwraca kolory?

Jeśli tak, czy powinienem uważać to za normalne zachowanie lub czy jest to błąd?


Link do pobrania:

mam zapakowane cały projekt na plik .zipi wysłał go, aby można było uruchomić ten test na komputerze od razu. Pobierz plik i rozpakuj.

getCellColor.zip

+0

Czy teraz możesz zmieniać paletę programu Excel? Znalazłem to, co może być przydatne. Niestety, nie mam Matlaba, aby rozwiązać to samodzielnie: [link] (http://www.cpearson.com/excel/colors.aspx) --- Zmieniasz wartości w domyślnej palecie modyfikując tablicę kolorów Obiekt skoroszytu. Na przykład, aby zmienić kolor, do którego odwołuje się wartość ColorIndex 3 na niebieski, użyj ==> 'Skoroszyty (" SomeBook.xls ") Kolory (3) = RGB (0,0,255)' –

+0

Nigdy nie widziałem tego problemu z Interior.Color. Domyślam się, że konwersja RGB-int jest cofana. W ten sposób konwertuję RGB na int, gdy ustawiam Interior.Color: 'longColor = rgbColor * [1 256 256 * 256] ';'. Działa dla dowolnego koloru, który lubisz. – buzjwa

+0

Sprawdziłem teraz twoją metodę 'int2rgb'. Rzeczywiście odwraca R i B. – buzjwa

Odpowiedz

2

Z MSDN article Model kolorów RGB:

Model kolorów RGB służy do określania kolorów. Ten model określa intensywność czerwieni, zieleni i błękitu w skali od 0 do 255, przy czym 0 (zero) wskazuje minimalną intensywność. Ustawienia trzech kolorów są przekształcane do jednego wartości całkowitej za pomocą tego wzoru:

wartości RGB = czerwony + (zielony * 256) + (niebieski * 256 * 256)

Jak to został zasugerowany w chris neilsen answer, nie ma "właściwego" lub "niewłaściwego" pod względem kodowania kolorów. Microsoft wybrał ten szczególny sposób kodowania kolorów z powodów, które tylko znają, i powinienem się do nich przyłączyć.

Wartości RGB, które otrzymuję, są całkowicie poprawne.

W poniższej tabeli zostały uwzględnione wartości RGB podane w artykule MSDN obok tych, które dostaję w MATLAB i są idealnie dopasowane.

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

Twoja metoda int2rgb odwraca R i B. Wymień je i dostaniesz odpowiednią konwersję. Właściwość Interior.Color wykorzystuje konwencję, w której R jest najmniej znaczącą, a funkcja FileExchange, której używasz, używa konwencji przeciwnej.

Aby przekonwertować z int na RGB:

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

Do konwersji z RGB do int:

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

Moja pierwsza myśl to sprawdzić kolejność kanałów RGB vs. BGR.

Prawdopodobnie można uprościć tę funkcję int2rgb, używając zamiast tego typecast. Oto przykład przy użyciu wartości ty Wysłany:

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

Wyjście:

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

Nie ma „prawo” lub „źle” tutaj, Matlab i Excel po prostu zakodować kolor inaczej. Musisz to uwzględnić w swoim kodzie.

Najbliżej mogę znaleźć na oficjalnym źródłem jest ten artykuł MSDN, około połowie drogi na dół zobaczyć przykład kodowanie „Blue”

MSDN article

W poniższych przykładach przedstawionych wnętrza wybór komórek do koloru niebieskiego. Selection.Interior.Color = 16711680
Selection.Interior.Color = & HFF0000
Selection.Interior.Color = & O77600000
Selection.Interior.Color = RGB (0, 0, 255)

+0

To zaskakujące. Myślałem, że kodowanie kolorów jest takie samo dla wszystkich, jak rodzaj standardu. – codeaviator