Newsgroup: it.comp.lang.c++
Titolo: Come posso visualizzare un DIB in toni di grigio?

Dovrei, usando il Borland C++ 5.02, emulare il comportamento di un pulsante
della barra strumenti tipica di Internet Explorer 3, cioe' visualizzare la
bitmap in toni di grigio quando il mouse non e' sopra di essa, e cambiare
la visualizzazione a colori quando il mouse si trova sopra il pulsante.
Io avrei bisogno di usare la funzione StretchDIBits per visualizzare un
DIB, originariamente a colori, che ho gia' in memoria. Qualcuno di voi ha
qualche suggerimento? Per caso ha a che fare con l'ultimo parametro, il
Rop? Preciso inoltre che so come visualizzare la bitmap a colori, mi serve
solo il codice per visualizzarla in toni di grigio. Anche MFC va bene (al
massimo lo "traduco" in OWL!!). Ringrazio in anticipo.
-- 
Jo Parrello (
jopa...@tin.it
)
http://space.tin.it/computer/giparrel

solo il codice per visualizzarla in toni di grigio. Anche MFC va bene
(al
Forse una chiamata all'API CopyImage con il flag LR_MONOCHROME
potrebbe fare al caso tuo...? Naturalmente questo implica tenerti due
immagine, una colorata e una monocromatica, piuttosto che non fare
la conversione al volo -- inoltre, funziona su handles, non su dati in
memoria.  Se va bene il primo requisito ma non il secondo potresti pero`
implementarti tu stesso la conversione in memoria colori->grigi con
qualche semplice formula tipo livgrigio=(livverde+livrosso/2+livblu/2)/2
o giu` di li` (questa tende a funzionare meglio, oltre ad essere piu`
veloce, che non sommare tutti i tre e dividere per 3, vista la diversa
sensibilita` dell'occhio alle componenti G [massima], R [intermedia],
e B [minima] dei vari colori).
Alex

 e B [minima] dei vari colori).
Ho scovato in un sito dedicato ai programmatori MFC
(
http://www.codeguru.com
) una routine che e' fatta apposta per convertire a
run-time una DIB da bitmap a colori a monocromatica. Ho tradotto un po' il
codice in OWL e il risultato e':
[ inizio codice ]
TDib* Dib = GetGlyphDib();
BITMAPINFO &bmInfo = *(LPBITMAPINFO) *Dib ;
long nColors = Dib->NumColors();
if (nColors <= 256)
  { 	// Modify the bitmaps color table directly
  for( int i=0; i < nColors; i++)
     {
     long lSquareSum = bmInfo.bmiColors[i].rgbRed   *
bmInfo.bmiColors[i].rgbRed + bmInfo.bmiColors[i].rgbGreen *
bmInfo.bmiColors[i].rgbGreen + bmInfo.bmiColors[i].rgbBlue  *
bmInfo.bmiColors[i].rgbBlue;
     BYTE nGray = (BYTE) sqrt(((double) lSquareSum) / 3);
    bmInfo.bmiColors[i].rgbRed = nGray;
    bmInfo.bmiColors[i].rgbGreen = nGray;
    bmInfo.bmiColors[i].rgbBlue = nGray;
    }
}
  // Draw the image
  LPVOID lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
  TRect rect;
  GetInnerRect(rect);
 ::StretchDIBits(dc.GetHDC(), rect.left, rect.top, rect.Width(),
rect.Height(), 0, 0, Dib->Width(), Dib->Height(), lpDIBBits, (LPBITMAPINFO)
*Dib, DIB_RGB_COLORS, SRCCOPY);
delete Dib;
[ fine codice ]
Come si puo' vedere ho usato StretchDIBits perche' voglio disegnare anche
una bitmap ingrandita oltre che quella a dimensione reale. Nota il calcolo
che viene fatto per ogni colore, che e' un po' diverso da quello suggerito
da te. Inoltre il codice reale era assai piu' lungo poiche' prevedeva la
creazione di una nuova palette, la selezione della nuova palette, il
disegno della bitmap e il ripristino della palette. Questo, a parte il
tempo che impiega in piu' e la dimensione del codice, ha provocato
fastidiosi effetti di sfarfallio in tutte le immagini dello schermo, come,
ad esempio, la toolbar di Internet Explorer 3 e un'immagine incorporata in
un documento di Word. Ho preferito lasciare il codice suddetto poiche' non
utilizza nessuna palette, ed inoltre ho la fortuna di lavorare su una copia
della DIB, e non sull'originale, poiche' il codice suddetto si puo'
utilizzare solo su una copia di una DIB, altrimenti altera la DIB
originale. 
Grazie comunque per l'aiuto sempre molto risolutivo.
Ciao.


massimo lo "traduco" in OWL!!). Ringrazio in anticipo.


 codice in OWL e il risultato e':
Ho provato e riprovato il codice, da me tradotto, tutta la mattinata e devo
dire che non mi e' tanto piaciuto il calcolo fatto dall'algoritmo di
conversione sui tre colori primari, poiche' esso usa la funzione "sqrt" che
oltre a "fregarsi" un bel po' di tempo, non risulta neanche tanto preciso
(intendo l'algoritmo) poiche' ad esempio una parte di una bitmap con colore
blu viene convertito in grigio chiaro, quando invece deve essere almeno
grigio scuro se non proprio grigio scurissimo, quasi nero. Ho usato percio'
l'algoritmo fornitomi da Alex, ed ha funzionato perfettamente, ed inoltre
non usa la funzione "sqrt", risultando molto veloce e molto preciso.
Grazie, quindi, di tutto, Alex.
Per la cronaca il codice non e' ancora pronto per essere pubblicato sul mio
sito web ma spero, almeno entro fine Agosto, di poterlo inserire. Si tratta
della seconda versione del file BUTTONAP.ZIP che rappresenta un passo
avanti per quanto riguarda la gestione delle toolbar in OWL.
Ciao.


Grazie, quindi, di tutto, Alex.
Prego!  La formula piu` esatta se ben ricordo e` qualcosa come
(0.47*green + 0.34*red + 0.19*blue), ma approssimando invece
i fattori con 0.5,0.25,0.25, si e` pur sempre abbastanza vicini e
si puo` fare del tutto a meno del floating point, il che una volta era
cruciale ma anche oggi comunque accelera le cose (se poi uno
andasse a programmare in MMX, torna cruciale!-).
Alex