2016-02-06 17 views
5

Ho scritto un pezzo di codice che mi consente di recuperare il colore di ombreggiatura di una cella specifica all'interno di un foglio di una cartella di lavoro Excel. Ho recuperato con successo il valore intero RGB avviando un server COM utilizzando MATLAB actxserver e quindi accedendo allo Color Property dell'oggetto interno di quel particolare oggetto cella. Quindi ottengo la tripletta RGB equivalente di quello intero, quindi posso usarla più tardi per tracciare in MATLAB.Interior.Color Proprietà inverte i colori?

Al fine di verificare che il mio codice funziona correttamente ho progettato il seguente test: ho creato una cartella di lavoro di Excel chiamato colorTest.xlsx con 8 diversi colori:

enter image description here

Poi eseguo il mio codice MATLAB, che estrae il informazioni sul colore su ogni cella della colonna B. Dovrei ottenere una trama con i colori sullo stesso ordine verticale e una tabella con il valore int e la tripletta RGB di ogni colore.

Tuttavia accade qualcosa di inaspettato! Guardate i risultati:

enter image description here

Si noti che il valore intero che si ottiene dalla proprietà di colore non sempre corrisponde al colore della cella originale, per il nero, bianco, verde e magenta i valori interi sono corretto, ma questo non è vero per tutti gli altri colori. Ad esempio, è possibile vedere che per il colore rosso su Excel, l'output int e la terzina RGB corrispondono al colore blu.

Ho aggiunto la seguente tabella con i risultati corretti devo ottenere, per riferimento:

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 

ho ottenuti i valori interi corretti per ciascun colore usando this RGB Int Calculator.

Se confrontiamo le due tabelle, possiamo dedurre che i canali Rosso e Blu sono invertiti.

Il codice:

La funzione che eseguo per eseguire il test si chiama getCellColor. Date un'occhiata al codice:

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 

(*) Questa istruzione è responsabile del recupero del numero intero di colori.


Nota: Le funzioni descritte successiva, non causano il problema poiché non prendono parte alla ottenimento del numero intero colore (sono usati soltanto per compiti secondari). Ho incluso queste informazioni solo per completezza.

Durante questo processo io uso tre privati ​​ funzioni dalla cartella iofun del MATLAB, che sono: validpath, xlsCleanup e openExcelWorkbook. Li ho semplicemente copiati in una cartella denominata privata all'interno della cartella del progetto.

Infine, per ottenere la terzina RGB dal numero intero di colori, utilizzo una funzione che ho adattato da this other function che ho trovato in rete.

Ecco il codice per la mia funzione 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 

Sto cercando di dare un senso di questo, ma io in realtà non hanno alcuna idea di ciò che sta accadendo. Ho fatto qualche ricerca, senza molta fortuna, ma lo this post e lo this other post hanno attirato la mia attenzione. Forse ha qualcosa a che fare con il mio problema.

Così la proprietà Interior.Color inverte realmente i colori?

Se questo è il caso, dovrei considerare questo come comportamento normale o si tratta di un bug?


link per scaricare:

ho imballato l'intero progetto su un file .zip e lo ha caricato, in modo da poter eseguire questo test sulla vostra macchina subito. Scarica il file e decomprimi.

getCellColor.zip

+0

A questo punto è possibile apportare modifiche alla tavolozza di Excel? Ho trovato questo che potrebbe essere utile. Sfortunatamente, non ho Matlab per risolverlo da solo: [link] (http://www.cpearson.com/excel/colors.aspx) --- Si modificano i valori nella tavolozza predefinita modificando l'array Colors del Oggetto cartella di lavoro. Ad esempio, per cambiare il colore referenziato da ColorIndex valore 3 a blu, utilizzare ==> 'Cartelle di lavoro (" SomeBook.xls "). Colori (3) = RGB (0,0,255)' –

+0

Non ho mai visto questo problema con Interior.Color. La mia ipotesi è che la conversione RGB-int sia al contrario. Ecco come convertire RGB in int quando ho impostato Interior.Color: 'longColor = rgbColor * [1 256 256 * 256] ';'. Funziona per qualsiasi colore che ti piace. – buzjwa

+0

Ho controllato il tuo metodo 'int2rgb' ora. In effetti inverte R e B. – buzjwa

risposta

2

Dal MSDN article sul modello di colore RGB:

Il modello di colore RGB viene utilizzato per specificare i colori. Questo modello specifica l'intensità di rosso, verde e blu su una scala da 0 a 255, con 0 (zero) che indica l'intensità minima. Le impostazioni di i tre colori vengono convertiti in un unico valore intero utilizzando questo formula:

valore RGB = Rosso + (Verde * 256) + (Blu * 256 * 256)

Come è stato suggerito in chris neilsen answer, non c'è "giusto" o "sbagliato" in termini di codifica a colori. Microsoft ha scelto questo modo particolare di codificare i colori solo per ragioni che conoscono, e io dovrei attenermi ad esso.

Quindi i valori RGB che ottengo sono completamente corretti.

Nella seguente tabella sono stati inclusi i valori RGB forniti nell'articolo MSDN accanto a quelli che ottengo in MATLAB e rappresentano una corrispondenza perfetta.

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

Il tuo metodo int2rgb inverte R e B. li sostituire e si otterrà il diritto di conversione. La proprietà Interior.Color utilizza la convenzione in cui R è il meno significativo, mentre la funzione FileExchange utilizzata utilizza la convenzione opposta.

Per convertire da int a RGB:

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

Per convertire da RGB a int:

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

Il mio primo pensiero è controllare l'ordine canali RGB vs BGR.

Probabilmente si potrebbe semplificare la funzione int2rgb utilizzando typecast. Ecco un esempio utilizzando i valori in cui hai postato:

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

L'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 
5

non esiste un "giusto" o "sbagliato" qui, Matlab e Excel solo codificano colore in modo diverso. Devi tenerne conto nel tuo codice.

Il più vicino che posso trovare a una fonte ufficiale è questo articolo di MSDN, circa a metà strada verso il basso vedere l'esempio di codifica dei "blu"

MSDN article

Gli esempi che seguono set l'interno di una selezione di celle per il colore blu. Selection.Interior.Color = 16711680
Selection.Interior.Colore = & HFF0000
Selection.Interior.Color = & O77600000
Selection.Interior.Color = RGB (0, 0, 255)

+0

Questo è sorprendente. Pensavo che la codifica del colore fosse la stessa per tutti, come una sorta di standard. – codeaviator