Масштабирование битмапа : GDI+
От: Carc Россия https://vk.com/gosha_mazov
Дата: 13.01.17 11:32
Оценка:
Нужно отмасштабировать битмапку в памяти с заданными зумом. Вчера половину дня промаялся: пищит, мигает, известно куда не попадает.
Все масштабирует, зум на лицо, но обрезает по размеру исходого битмапа. Полный: *опа-кеды.
Уважаемый All, ткните носом, ЧЯДНТ!

HBITMAP CDlgPicResize::DoResizePlus(const LONG cx /*новая ширина для битмпап*/, const LONG cy /*новая высота*/)
{
    Gdiplus::Status st;

    TRACE(TEXT("DoResizePlus cx=%d cy=%d\n"),cx,cy);
    
    //расcчитываем Zoom-фактор 
    const float cx_factor=((float)cx/(float)m_szSRC.cx);//(m_szSRC - CSize с исходными размерами 1 в 1)
    const float cy_factor=((float)cy/(float)m_szSRC.cy);
    TRACE(TEXT("cx_factor=%f, CY_factor=%f\n"),cx_factor,cy_factor);

    const HDC hdcFrom=::GetDC(m_hwndRE);//HWND куда потом будет вставлен новый битпа
    ASSERT(hdcFrom);
    //////////////////////////////////////////////////////////////////////////
    //все эти с CAutoGDI*** - это auto-объекты, которые только освобождают ресурсы GDI на выходе
     const CAutoGDIHDC_Release release_dc_wnd(hdcFrom,m_hwndRE);
    //создаем битмап на котором будем рисовать в памяти
    HBITMAP hNew=CreateCompatibleBitmap(hdcFrom,cx,cy);
    ASSERT(hNew);

    //создаем временный GDI+ битмап и выбираем его в контекст
    Gdiplus::Bitmap bmpForDraw(cx
        ,cy
        ,PixelFormat24bppRGB) ;

    Gdiplus::Graphics g(&bmpForDraw);
    g.SetClip(Gdiplus::Rect(0,0,cx,cy)) ;

    st = g.SetInterpolationMode(Gdiplus::InterpolationModeBicubic);
    g.SetCompositingQuality(Gdiplus::CompositingQualityHighQuality);
    //устанавливаем масштабирование
    g.ScaleTransform(cx_factor, cy_factor);
    {/// рисуем исходный битмап с маштабированием и новой шириной\высотой
    Gdiplus::Bitmap bmpTemp(m_hSource,NULL);// m_hSource это HBITMAP исходный
    g.DrawImage(&bmpTemp,0,0,cx,cy);

    
    //забираем битмап
    HBITMAP h=NULL;
    st = bmpForDraw.GetHBITMAP(RGB(255,0,0),&h);
    ASSERT(Gdiplus::Ok == st);
    ASSERT(h);
    ASSERT(h != hNew);
    BITMAP bNew={0};
    GetObject(h, sizeof(BITMAP),&bNew);
    TRACE(TEXT("IN: cx=%d cy=%d\n"),bNew.bmWidth,bNew.bmHeight);
    hNew=h;//ДЛЯ кодо-копателей: да здесь идет потеря вышесозданного HBITMAP, но это издержки тестирования
//, поскольку уже 100 раз переписывалось и так и эдак, 
//изначально все корректно было, и потом, когда доводить буду -  “причешу”.
    }
    
#ifdef _DEBUG
    //всяко разно дебажные проверки (ширина\высота нового битмапа соответсвуют?
    //для просмотра кидаем в файл
    BITMAP bNew={0};
    GetObject(hNew , sizeof(BITMAP),&bNew);
    TRACE(TEXT("new cx=%d cy=%d\n"),bNew.bmWidth,bNew.bmHeight);

    {
    Gdiplus::Bitmap bmpForSave(hNew,NULL);
    CLSID bmpClsid ={0};
    
    GetCodecClsid(L"image/bmp", &bmpClsid);
    st= bmpForSave.Save(L"C:\\Test_GDI.bmp",&bmpClsid,NULL);
    ASSERT(Gdiplus::Ok == st);
    }
#endif

    
    return hNew;
}


Проблема в следующем: все масштабируется, но на выходе получаем обрезанный битмап по размеру исходного. То бишь зум видно невооруженным взглядом — все чики-поки. Но если масштаб больше 100 — тогда обрезается по размеру исходного битмапа. Если масштаб меньше 100 — то опять же, все масштабируется, результирующий битмап ессесна получается меньше исходого. Но опять же все по размеру исходного, просто с черным фоном.

Ни черта не понимаю уже. Что я не так то хоть делаю!?! Уже только что не перепробовал, не попеременял в коде. Ан фиг! Хелп, коллеги!
Aml Pages Home
Отредактировано 13.01.2017 14:59 Carc . Предыдущая версия . Еще …
Отредактировано 13.01.2017 14:59 Carc . Предыдущая версия .
Отредактировано 13.01.2017 12:25 Carc . Предыдущая версия .
Отредактировано 13.01.2017 12:23 Carc . Предыдущая версия .
Отредактировано 13.01.2017 12:20 Carc . Предыдущая версия .
Отредактировано 13.01.2017 11:35 Carc . Предыдущая версия .
Отредактировано 13.01.2017 11:34 Carc . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.