Всем добрый день. Возникла проблема с Windows 2000 и Win2000 Server. НА этих версиях еще нет альфа канала у иконок, и следовательно мы получаем некрасивые иконки в 2000ом и вообще трэш на сервере. Для 24битных все в порядке. Не подскажете как быстро конвертнуть иконку 32битной глубины цвета в 24битную.
Было бы здорово, как то пробовал, но нужно было очень срочно и до нужно результата не дошел. Буду очень признателен
Здравствуйте, Carc, Вы писали:
C>Здравствуйте, Multix, Вы писали:
M>>Всем добрый день. Возникла проблема с Windows 2000 и Win2000 Server. НА этих версиях еще нет альфа канала у иконок, и следовательно мы получаем некрасивые иконки в 2000ом и вообще трэш на сервере. Для 24битных все в порядке. Не подскажете как быстро конвертнуть иконку 32битной глубины цвета в 24битную.
C>Иконки откуда берутся?
C>Вообще как-то писал тут недавно saver из HICON в Ico-формат, но не особо заморачивался с деталями (альфы и прочие мелочи) — но вроде сносно работает... Доточить до создания HICON из битмапов разобранных будет видимо несложно.
C>Может код выложить?
Здравствуйте, Multix, Вы писали:
M>Было бы здорово, как то пробовал, но нужно было очень срочно и до нужно результата не дошел. Буду очень признателен
M>Здравствуйте, Carc, Вы писали:
C>>Здравствуйте, Multix, Вы писали:
M>>>Всем добрый день. Возникла проблема с Windows 2000 и Win2000 Server. НА этих версиях еще нет альфа канала у иконок, и следовательно мы получаем некрасивые иконки в 2000ом и вообще трэш на сервере. Для 24битных все в порядке. Не подскажете как быстро конвертнуть иконку 32битной глубины цвета в 24битную.
C>>Иконки откуда берутся?
C>>Вообще как-то писал тут недавно saver из HICON в Ico-формат, но не особо заморачивался с деталями (альфы и прочие мелочи) — но вроде сносно работает... Доточить до создания HICON из битмапов разобранных будет видимо несложно.
C>>Может код выложить?
Лови!
Сори, но комментариями не страдал. Замечания, критика конечно же принимаются, но строго не судить — писал срочно, под собственный проект и
был бухой кодил впопыхах
//HEADER: по сути никакого класса в понимании ООП нет, все член-функции static, разве что ограничения доступа можно потом использовать (protected, public, private)
//но т.к. старушка VC6 не очень любит namespace в дереве классов (просто неудобно в навигации), то и сделано как класс
// IconIO.h: interface for the IconIO class.
//
//////////////////////////////////////////////////////////////////////
//(C) by Mazov Gosha aka Carc
// http://www.amlpages.com, http://nonp.blogspot.com
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_ICONIO_H__A115D6E1_24BD_46E9_ADC1_076AC560AD3F__INCLUDED_)
#define AFX_ICONIO_H__A115D6E1_24BD_46E9_ADC1_076AC560AD3F__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class IconIO
{
IconIO();//private!!! ну вот шо, Cирожа... На этот раз хрена с два ты у меня создашь объект класса, объекты которого смысла создавать нет.
//В асю не стучи, пока не курну свежего сбора полемику об этом воспринимать не готовый я :)
~IconIO();
public:
static bool SaveIconToIcoFile(const HICON hIcon, LPCTSTR lpszPathName);
private:
static bool SaveIcon(const ICONINFO& info, const HANDLE hFile);
};
#endif // !defined(AFX_ICONIO_H__A115D6E1_24BD_46E9_ADC1_076AC560AD3F__INCLUDED_)
//Implementation (CPP)
// IconIO.cpp: implementation of the IconIO class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "IconIO.h"
#pragma pack(push, 1)
namespace { // unnamed namespace for hiding of internal classes
struct ICO_IMAGE : public BITMAPINFOHEADER
{
LPBYTE lpBits;
ICO_IMAGE():lpBits(NULL)
{
memset(this,NULL,sizeof(ICO_IMAGE));
biSize=sizeof(BITMAPINFOHEADER);
}
~ICO_IMAGE()
{
if (lpBits)
delete[] lpBits;
}
void MakeFromBitmapInfoHeader(const BITMAPINFOHEADER& info)
{
memcpy(this,&info,sizeof(BITMAPINFOHEADER));
}
private:
ICO_IMAGE& operator=(const ICO_IMAGE& rvalue);//DISALLOW COPYING THIS CLASS!!!
};
struct ICO_FILE_HEADER {
const WORD wReserved;
const WORD wType;
WORD wCount;
ICO_FILE_HEADER(WORD wIconCount):wCount(wIconCount),wType(1),wReserved(0)
{
}
};
class CAutoDC {
const HDC hdc;
void* operator new(size_t);
public:
CAutoDC():hdc(CreateCompatibleDC(NULL))
{
ASSERT(hdc);
}
~CAutoDC()
{
if (hdc)
VERIFY(DeleteDC(hdc));
}
bool operator!() const
{
return (NULL == hdc);
}
operator HDC() const
{
return hdc;
}
};
typedef struct
{
BYTE bWidth; // Width of the image
BYTE bHeight; // Height of the image (times 2)
BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
BYTE bReserved; // Reserved
WORD wPlanes; // Color Planes
WORD wBitCount; // Bits per pixel
DWORD dwBytesInRes; // how many bytes in this resource?
DWORD dwImageOffset; // where in the file is this image
} ICONDIRENTRY, *LPICONDIRENTRY;
};//namespace {
BOOL InitBitmapInfoHeader(HBITMAP hBitmap, BITMAPINFOHEADER& bih )
{
//int nBytes = 0;
// get BITMAP data
BITMAP bm; ZeroMemory(&bm, sizeof(BITMAP));
if (0 == GetObject(hBitmap, sizeof(BITMAP), &bm))
return FALSE;
// get DIBSECTION data
DIBSECTION ds; ZeroMemory(&ds, sizeof(DIBSECTION));
const int nBytes = GetObject(hBitmap, sizeof(DIBSECTION), &ds);
if (!nBytes)
return FALSE;
// init header
if (nBytes >= sizeof(ds.dsBm) + sizeof(ds.dsBmih) && ds.dsBmih.biSize >= sizeof(ds.dsBmih))
{
memcpy(&bih, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
}
else
{
ZeroMemory(&bih, sizeof(BITMAPINFOHEADER));
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = ds.dsBm.bmWidth;
bih.biHeight = ds.dsBm.bmHeight;
bih.biBitCount = (WORD)(ds.dsBm.bmPlanes * ds.dsBm.bmBitsPixel);
}
bih.biBitCount = bm.bmBitsPixel;
if (bih.biBitCount <= 8)
bih.biClrUsed = 1 << bih.biBitCount;
bih.biPlanes = 1;
if (bih.biClrImportant > bih.biClrUsed)
bih.biClrImportant = bih.biClrUsed;
if (0 == bih.biSizeImage )
bih.biSizeImage = ((bih.biWidth * bih.biBitCount + 31) / 32) * 4 * bih.biHeight;
// ready
return TRUE;
}
BOOL GetIconImageInternal(const HBITMAP hBitmap, ICO_IMAGE& image
, const bool /*bColor*/
, const HDC hdcScreen
, RGBQUAD** /*pColor*/, UINT** /*pnColor*/)
{
//const HBITMAP hBitmap=bColor ? _info.hbmColor : _info.hbmMask;
ASSERT(OBJ_BITMAP == GetObjectType(hBitmap));
ASSERT(OBJ_DC==GetObjectType(hdcScreen) || OBJ_MEMDC==GetObjectType(hdcScreen));
BITMAP bitmap={0};
if (sizeof(BITMAP) != GetObject(hBitmap,sizeof(BITMAP),&bitmap))
return FALSE;
const UINT nScanLines=bitmap.bmHeight;
BITMAPINFO bmInfo={0};
bmInfo.bmiHeader.biSize=sizeof(BITMAPINFO);
if (!GetDIBits(hdcScreen,hBitmap,0,nScanLines,NULL,&bmInfo,DIB_RGB_COLORS)) {
return FALSE;
}
//if (!bColor) {
// image.MakeFromBitmapInfoHeader(bmInfo.bmiHeader);
//}
//else
InitBitmapInfoHeader(hBitmap,(BITMAPINFOHEADER&)image);
const LONG nBytesCount=(bitmap.bmWidth*bitmap.bmHeight*image.biBitCount)/8;
BYTE* const pbStart=new BYTE[nBytesCount];
ASSERT(pbStart);
if (NULL == pbStart)
return FALSE;
ASSERT(!IsBadWritePtr(pbStart,nBytesCount));
BYTE* const pb=pbStart;
if (nBytesCount != GetBitmapBits(hBitmap,nBytesCount,pb))
return FALSE;
image.lpBits=pbStart;
return TRUE;
}
static
BOOL WriteBuffer(const HANDLE hFile, LPCVOID lp, const DWORD dwSize)
{
ASSERT(hFile);
ASSERT(!IsBadReadPtr(lp,dwSize));
DWORD dwWritten=0;
if (!WriteFile(hFile,lp,dwSize,&dwWritten,NULL)) {
const DWORD dwErr=GetLastError();
return FALSE;
}
return (dwSize == dwWritten);
}
//static
//BOOL WriteWord( const HANDLE hFile, const WORD wValue)
//{
// return WriteBuffer(hFile,&wValue,sizeof(wValue));
//}
//
//static
//BOOL WriteDWord( const HANDLE hFile, const DWORD wValue)
//{
// return WriteBuffer(hFile,&wValue,sizeof(wValue));
//}
//
SIZE GetBitmapSize(const HBITMAP h)
{
ASSERT(h);
ASSERT(OBJ_BITMAP == GetObjectType(h));
BITMAP bmp={0};
VERIFY(GetObject(h,sizeof(bmp),&bmp));
SIZE size;
size.cx=bmp.bmWidth;
size.cy=bmp.bmHeight;
return size;
}
BOOL WriteBits(const HANDLE hFile, const ICO_IMAGE& image)
{
const int nRowCount=image.biHeight;
const int nRowLen=(image.biSizeImage/ nRowCount);
ASSERT(hFile);
ASSERT(!IsBadReadPtr(image.lpBits,nRowLen*nRowCount));
for (int i=nRowCount - 1 ; i >= 0; i--) {
const BYTE* const pb=(image.lpBits + (nRowLen*i));
if (!WriteBuffer(hFile,pb,nRowLen))
return FALSE;
}
return TRUE;
}
DWORD CalcImageSize(const ICO_IMAGE& image)
{
ASSERT(image.biBitCount);
const DWORD dw=(image.biBitCount* image.biWidth * image.biHeight)/8;
ASSERT(dw);
ASSERT(dw*2 == image.biSizeImage || dw==image.biSizeImage);
return dw;
}
DWORD CalcBytesInRes(const ICO_IMAGE& imgColor, const ICO_IMAGE& imgMask, const int nNumPallettes)
{
ASSERT(&imgColor != & imgMask);
const DWORD dwColor=CalcImageSize(imgColor);
const DWORD dwMask=CalcImageSize(imgMask);
const DWORD dwPal=sizeof(PALETTEENTRY)*nNumPallettes;
const DWORD dwRet=sizeof(BITMAPINFOHEADER)
+ dwColor
+ dwMask
+ dwPal
;
return dwRet;
}
//WORD DIBNumColors(const BITMAPINFOHEADER* const lpbi)
//{
// ASSERT(!IsBadReadPtr(lpbi,sizeof(BITMAPINFOHEADER)));
// ASSERT(sizeof(BITMAPINFOHEADER) == lpbi->biSize);
//
// const DWORD dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
//
// if (dwClrUsed)
// return (WORD) dwClrUsed;
//
// const WORD wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
//
// switch (wBitCount)
// {
// case 1:
// return 2;
// case 4:
// return 16;
// case 8:
// return 256;
// default:
// return 0;
// }
//
// return 0;
//}
BOOL GetIconImageColor(const ICONINFO& info, ICO_IMAGE& image, const HDC hdcScreen)
{
return GetIconImageInternal(info.hbmColor,image,true,hdcScreen,NULL,NULL);
}
BOOL GetIconImageMask(const ICONINFO& info, ICO_IMAGE& image, const HDC hdcScreen)
{
return GetIconImageInternal(info.hbmMask,image,false,hdcScreen,NULL,NULL);
}
bool IconIO::SaveIconToIcoFile(const HICON hIcon, LPCTSTR lpszPathName)
{
ASSERT(hIcon);
ASSERT(!IsBadStringPtr(lpszPathName,INFINITE));
ASSERT(_tcslen(lpszPathName));
ICONINFO info;
if (!GetIconInfo(hIcon,&info)) {
ASSERT(FALSE);
return false;
}
const HANDLE hFile=CreateFile(lpszPathName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
if (INVALID_HANDLE_VALUE == hFile) {
ASSERT(FALSE);
return false;
}
const bool bRet=SaveIcon(info,hFile);
CloseHandle(hFile);
if (!bRet)
DeleteFile(lpszPathName);
return bRet;
}
bool IconIO::SaveIcon(const ICONINFO &info, const HANDLE hFile)
{
const ICO_FILE_HEADER icon_header(1);
ASSERT(sizeof(icon_header) == 6);
const CAutoDC hdcScreen;
ASSERT(hdcScreen);
if (!hdcScreen)
return false;
ICONDIRENTRY de={0};
ASSERT(sizeof(de) == 16);
const SIZE sizeIcon=GetBitmapSize(info.hbmColor);
de.bWidth=LOBYTE(LOWORD(sizeIcon.cx));
de.bHeight=LOBYTE(LOWORD(sizeIcon.cy));
//de.bColorCount=0;//for true-colors 0 == value
//de.bColorCount=32;
de.bReserved=0;//reserved by MS
//внимание - по оф. документации значение не используется, но тем не менее иногда его некоторые ставят
//в единицу, другие наоборот в 0
//в общем "хер его знает, товарищ полковние - собака след не берет"
//de.wPlanes=0;//обычно 1 но что этой хер его знает
de.dwImageOffset=sizeof(ICO_FILE_HEADER)+sizeof(ICONDIRENTRY);
//теперь получаем размеры обоих битмапов, и вычисляем размер для байтов в рисунке
ICO_IMAGE imageColor;
if (!GetIconImageColor(info,imageColor,hdcScreen))
return FALSE;
ICO_IMAGE imageMask;
if (!GetIconImageMask(info,imageMask,hdcScreen))
return false;
if (!WriteBuffer(hFile,&icon_header,sizeof(icon_header)))
return false;
const WORD nColors=0;
de.dwBytesInRes=CalcBytesInRes(imageColor,imageMask,nColors);
de.bColorCount=(BYTE)(imageColor.biPlanes*imageColor.biBitCount);
if (!WriteBuffer(hFile,&de,sizeof(de)))
return FALSE;
BITMAPINFOHEADER bmh;
memset(&bmh,0,sizeof(bmh));
memcpy(&bmh,&imageColor,sizeof(BITMAPINFOHEADER));
bmh.biHeight*=2; //высота COLOR + высота маски
if (!WriteBuffer(hFile,&bmh,sizeof(BITMAPINFOHEADER)))
return FALSE;
if (!WriteBits(hFile,imageColor))
return FALSE;
if (!WriteBits(hFile,imageMask))
return FALSE;
return true;
}
#pragma pack(pop,1)