1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
#if defined(CIMAGE_DITHERING)
// Effectue le dithering de l'image, de m_nTypeImage vers nNewType
BOOL CImage::Dither(int nNewType, BOOL bDither)
{
BOOL bRet=FALSE;
if(!m_hDib)
return FALSE;
// Le type demandé est-il connu?
if(nNewType<IMG_TYPE_COL24 || nNewType>IMG_TYPE_NB)
return FALSE;
// Cas spécial: image source en 16 ou 32 bits. Formats non supportés -> passage en 24 bits avant le dithering
if(GetBPP()==32 || GetBPP()==16)
{
LPBITMAPINFOHEADER BmSrcInfo=(LPBITMAPINFOHEADER)GlobalLock(m_hDib);
LPBITMAPINFO biSrc=(LPBITMAPINFO)BmSrcInfo;
// Détermination du nombre de couleurs
int nColors = BmSrcInfo->biClrUsed ? BmSrcInfo->biClrUsed : NULL;
int nScanWidthSrc = WIDTHBYTES(BmSrcInfo->biWidth * BmSrcInfo->biBitCount);
// Détermination de la zone des bits de l'image source et largeur lignes en octets
BYTE* lpSrcBits = (BYTE*)BmSrcInfo+BmSrcInfo->biSize+nColors*sizeof(RGBQUAD);
// Largeur des lignes du nouveau bitmap en 24 bits
int nScanWidthDest = WIDTHBYTES(BmSrcInfo->biWidth * 24);
// On crée une nouvelle zone mémoire pour accueillir le nouveau bitmap
HGLOBAL hNewDib=GlobalAlloc(GHND, BmSrcInfo->biSize+(nScanWidthDest*BmSrcInfo->biHeight));
if(!hNewDib)
{
GlobalUnlock(m_hDib);
return FALSE; // Pas assez de mémoire ou problème
}
// Adresse du nouveau bitmap
LPBITMAPINFOHEADER BmDestInfo=(LPBITMAPINFOHEADER)GlobalLock(hNewDib);
LPBITMAPINFO biDest=(LPBITMAPINFO)BmDestInfo;
// Copie du Header ds le nouveau bitmap
CopyMemory(biDest, biSrc, BmSrcInfo->biSize);
// Changement des paramètres sur le nouveau bitmap
BmDestInfo->biBitCount = 24;
BmDestInfo->biClrUsed = 0;
BmDestInfo->biSizeImage = nScanWidthDest*BmDestInfo->biHeight;
// Détermination de la zone des bits de l'image source et largeur lignes en octets
BYTE* lpDestBits = (BYTE*)BmDestInfo+BmDestInfo->biSize;
// Copie Pixel à pixel de l'ancien vers le nouveau bitmap
if(BmSrcInfo->biBitCount==32) // de 32 vers 24 bits
{
for(int y=0; y<BmDestInfo->biHeight; y++)
{
BYTE* lpSrc = lpSrcBits + (y*nScanWidthSrc);
BYTE* lpDest = lpDestBits + (y*nScanWidthDest);
for(int x=0; x<BmDestInfo->biWidth; x++)
{
*(lpDest++) = *(lpSrc++);
*(lpDest++) = *(lpSrc++);
*(lpDest++) = *(lpSrc++);
lpSrc++; // on saute un octet pour chaque pixel
}
}
}
else // 16 vers 24 bits (32000 couleurs, pas 65000)
{
for(int y=0; y<BmDestInfo->biHeight; y++)
{
WORD* lpSrc = (WORD*)(lpSrcBits + (y*nScanWidthSrc));
BYTE* lpDest = lpDestBits + (y*nScanWidthDest);
for(int x=0; x<BmDestInfo->biWidth; x++)
{
*(lpDest++) = (BYTE)((*(lpSrc) & 0x1F) * 8.2258 + 0.5);
*(lpDest++) = (BYTE)(((*(lpSrc)>>5) & 0x1F) * 8.2258 + 0.5);
*(lpDest++) = (BYTE)(((*(lpSrc)>>10) & 0x1F) * 8.2258 + 0.5);
lpSrc++; // on passe au pixel suivant
}
}
}
// Pas de couleur transparente en 32 ou 16 bits
m_dwTransparentColor = NULL;
GlobalUnlock(m_hDib);
GlobalUnlock(hNewDib);
GlobalFree(m_hDib);
// On supprime l'ancien DIB et on le remplace par le nouveau
m_hDib = hNewDib;
m_nTypeImage = IMG_TYPE_COL24;
}
// Pas de dithering si le type demandé est celui en cours (ou que la transformation en 24 bits a suffit)
if(nNewType==m_nTypeImage)
return TRUE;
// Si type actuel non connu -> on le cherche (couleur par défaut)
if(m_nTypeImage==IMG_TYPE_UNKNOWN)
m_nTypeImage = GetDefaultType(GetBPP());
// Si transparent -> On retrouve la position d'un pixel transparent
BOOL bOk = FALSE;
BOOL bDoIt = FALSE;
int xTrans = 0;
int yTrans = 0;
if(m_dwTransparentColor & 0x80000000L)
{
LPBITMAPINFOHEADER BmInfo=(LPBITMAPINFOHEADER)GlobalLock(m_hDib);
int nColors = BmInfo->biClrUsed ? BmInfo->biClrUsed : 0x1FF & (1 << BmInfo->biBitCount);
BYTE* lpBits = (BYTE*)BmInfo+BmInfo->biSize+nColors*sizeof(RGBQUAD);
int nScanWidth = WIDTHBYTES(BmInfo->biWidth * BmInfo->biBitCount);
DWORD dwColor = m_dwTransparentColor & 0x7FFFFFFFL;
for(yTrans=0; yTrans<BmInfo->biHeight && !bOk; yTrans++)
for(int xTrans=0; xTrans<BmInfo->biWidth && !bOk; xTrans++)
if(dwColor == GetPixel(xTrans, yTrans, BmInfo, nColors, nScanWidth, lpBits))
bOk = TRUE;
GlobalUnlock(m_hDib);
}
// De 24 bits vers tous les autres
if(m_nTypeImage==IMG_TYPE_COL24)
{
switch(nNewType)
{
case IMG_TYPE_COL256:
bRet = DitherQuantize(256, bDither);
if(bRet)
bDoIt = TRUE;
break;
case IMG_TYPE_COL16:
bRet = DitherQuantize(16, bDither);
if(bRet)
bDoIt = TRUE;
break;
case IMG_TYPE_NG256:
bRet = DitherGrayScale();
// Cas particulier du 24 bits vers
// 256NG: réduction facile, sans dithering
{
LPBITMAPINFOHEADER BmSrcInfo=(LPBITMAPINFOHEADER)GlobalLock(m_hDib);
LPBITMAPINFO biSrc=(LPBITMAPINFO)BmSrcInfo;
// Si != de 24 bits -> c'est pas bon
if(BmSrcInfo->biBitCount!=24)
{
GlobalUnlock(m_hDib);
return FALSE; // Pas assez de mémoire ou problème
}
// Détermination du nombre de couleurs
int nColors = BmSrcInfo->biClrUsed ? BmSrcInfo->biClrUsed : 0x1FF & (1 << BmSrcInfo->biBitCount);
// Détermination de la zone des bits de l'image source et largeur lignes en octets
BYTE* lpSrcBits = (BYTE*)BmSrcInfo+BmSrcInfo->biSize+nColors*sizeof(RGBQUAD);
int nScanWidthSrc = WIDTHBYTES(BmSrcInfo->biWidth * BmSrcInfo->biBitCount);
// Largeur des lignes du nouveau bitmap
int nScanWidthDest = WIDTHBYTES(BmSrcInfo->biWidth * 8);
// On crée une nouvelle zone mémoire pour accueillir le nouveau bitmap
HGLOBAL hNewDib=GlobalAlloc(GHND, BmSrcInfo->biSize+256*sizeof(RGBQUAD)
+ (nScanWidthDest*BmSrcInfo->biHeight));
if(!hNewDib)
{
GlobalUnlock(m_hDib);
return FALSE; // Pas assez de mémoire ou problème
}
// Adresse du nouveau bitmap
LPBITMAPINFOHEADER BmDestInfo=(LPBITMAPINFOHEADER)GlobalLock(hNewDib);
LPBITMAPINFO biDest=(LPBITMAPINFO)BmDestInfo;
// Copie du Header ds le nouveau bitmap
CopyMemory(biDest, biSrc, BmSrcInfo->biSize);
// Création palette en 256NG
for(int i=0; i<256; i++)
biDest->bmiColors[i].rgbRed = biDest->bmiColors[i].rgbGreen
= biDest->bmiColors[i].rgbBlue = i;
// Changement de paramètres ds la structure
BmDestInfo->biBitCount = 8;
BmDestInfo->biClrImportant = BmDestInfo->biClrUsed = 256;
BmDestInfo->biSizeImage = nScanWidthDest*BmSrcInfo->biHeight;
// Détermination de la zone des bits de l'image source et largeur lignes en octets
BYTE* lpDestBits = (BYTE*)BmDestInfo+BmDestInfo->biSize+256*sizeof(RGBQUAD);
// Copie des octets
BYTE* lpDest = lpDestBits;
BYTE* lpSrc = lpSrcBits;
int j;
for(i=0; i<BmSrcInfo->biHeight; i++)
{
for(j=0; j<BmSrcInfo->biWidth; j++)
{
*(lpDest++) = *lpSrc;
lpSrc += 3;
}
lpDestBits += nScanWidthDest;
lpSrcBits += nScanWidthSrc;
lpDest = lpDestBits;
lpSrc = lpSrcBits;
}
GlobalUnlock(m_hDib);
GlobalUnlock(hNewDib);
GlobalFree(m_hDib);
m_hDib = hNewDib;
bRet = TRUE;
}
break;
case IMG_TYPE_NG16:
if(bRet = DitherQuantize(16, bDither))
if(bRet = DitherGrayScale())
bDoIt = TRUE;
break;
case IMG_TYPE_NB:
if(bRet = DitherQuantize(2, bDither))
m_dwTransparentColor = NULL;
break;
}
}
.
.
.
} |
Partager