Конвертанция из 32битного цвета в 24битный у иконок
От: Multix  
Дата: 26.09.11 06:49
Оценка:
Всем добрый день. Возникла проблема с Windows 2000 и Win2000 Server. НА этих версиях еще нет альфа канала у иконок, и следовательно мы получаем некрасивые иконки в 2000ом и вообще трэш на сервере. Для 24битных все в порядке. Не подскажете как быстро конвертнуть иконку 32битной глубины цвета в 24битную.
Re: Конвертанция из 32битного цвета в 24битный у иконок
От: Carc Россия https://vk.com/gosha_mazov
Дата: 26.09.11 09:06
Оценка:
Здравствуйте, Multix, Вы писали:

M>Всем добрый день. Возникла проблема с Windows 2000 и Win2000 Server. НА этих версиях еще нет альфа канала у иконок, и следовательно мы получаем некрасивые иконки в 2000ом и вообще трэш на сервере. Для 24битных все в порядке. Не подскажете как быстро конвертнуть иконку 32битной глубины цвета в 24битную.

Иконки откуда берутся?
Вообще как-то писал тут недавно saver из HICON в Ico-формат, но не особо заморачивался с деталями (альфы и прочие мелочи) — но вроде сносно работает... Доточить до создания HICON из битмапов разобранных будет видимо несложно.
Может код выложить?
Aml Pages Home
Re[2]: Конвертанция из 32битного цвета в 24битный у иконок
От: Multix  
Дата: 26.09.11 09:16
Оценка:
Было бы здорово, как то пробовал, но нужно было очень срочно и до нужно результата не дошел. Буду очень признателен

Здравствуйте, Carc, Вы писали:

C>Здравствуйте, Multix, Вы писали:


M>>Всем добрый день. Возникла проблема с Windows 2000 и Win2000 Server. НА этих версиях еще нет альфа канала у иконок, и следовательно мы получаем некрасивые иконки в 2000ом и вообще трэш на сервере. Для 24битных все в порядке. Не подскажете как быстро конвертнуть иконку 32битной глубины цвета в 24битную.

C>Иконки откуда берутся?
C>Вообще как-то писал тут недавно saver из HICON в Ico-формат, но не особо заморачивался с деталями (альфы и прочие мелочи) — но вроде сносно работает... Доточить до создания HICON из битмапов разобранных будет видимо несложно.
C>Может код выложить?
Re[3]: Конвертанция из 32битного цвета в 24битный у иконок
От: Carc Россия https://vk.com/gosha_mazov
Дата: 26.09.11 09:58
Оценка: 6 (1)
Здравствуйте, 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)
Aml Pages Home
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.