Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Как повернуть изображение в HBITMAP на 180?


Автор: VSergeyV 14.12.2006, 14:15
Как повернуть изображение в HBITMAP на 180?

Автор: Earnest 14.12.2006, 15:44
1) Считать биты в буфер, поменять местами первую и последнюю строку, вторую и предпоследнюю, etc? закачать обратно в битмап
2) Можно попробовать повернуть на выводе - через соответствующие переметры StretchBlt. 

Автор: The Thing 21.12.2006, 11:59
Исходник как повернуть изображение на любой угол.. 

файл: TurnImView.h
Код

// TurnImView.h : interface of the CTurnImView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_TURNIMVIEW_H__DDA2FBD8_0C64_4E02_B12D_977665250476__INCLUDED_)
#define AFX_TURNIMVIEW_H__DDA2FBD8_0C64_4E02_B12D_977665250476__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


class CTurnImView : public CView
{
protected: // create from serialization only
    CTurnImView();
    DECLARE_DYNCREATE(CTurnImView)

// Attributes
public:
    CTurnImDoc* GetDocument();

    float m_iangel;
    bool m_draw;
    
    void Formating(CDC *pDC);
    void LoadFile(CDC *pDC);
    void SinCos(double AngleRad, double &ASin, double &ACos);

// Operations
public:

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CTurnImView)
    public:
    virtual void OnDraw(CDC* pDC);  // overridden to draw this view
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
    protected:
    virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
    virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
    virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
    virtual void DoDataExchange(CDataExchange* pDX);
    //}}AFX_VIRTUAL

// Implementation
public:
    virtual ~CTurnImView();
#ifdef _DEBUG
    virtual void AssertValid() const;
    virtual void Dump(CDumpContext& dc) const;
#endif

protected:
    HBITMAP m_hbitmap;
    BITMAP m_bm;
// Generated message map functions
protected:
    //{{AFX_MSG(CTurnImView)
    afx_msg void OnViewSetangle();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

#ifndef _DEBUG  // debug version in TurnImView.cpp
inline CTurnImDoc* CTurnImView::GetDocument()
   { return (CTurnImDoc*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_TURNIMVIEW_H__DDA2FBD8_0C64_4E02_B12D_977665250476__INCLUDED_)


файл: TurnImView.cpp
Код

// TurnImView.cpp : implementation of the CTurnImView class
//

#include "stdafx.h"
#include "TurnIm.h"

#include "TurnImDoc.h"
#include "TurnImView.h"
#include "math.h"

#include "SetAngle.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTurnImView

IMPLEMENT_DYNCREATE(CTurnImView, CView)

BEGIN_MESSAGE_MAP(CTurnImView, CView)
    //{{AFX_MSG_MAP(CTurnImView)
    ON_COMMAND(ID_VIEW_SETANGLE, OnViewSetangle)
    //}}AFX_MSG_MAP
    // Standard printing commands
    ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTurnImView construction/destruction

CTurnImView::CTurnImView()
{
    // TODO: add construction code here
    m_iangel = 0;
    m_draw = false; //ïåðåðèñîâêà
}

CTurnImView::~CTurnImView()
{
}

BOOL CTurnImView::PreCreateWindow(CREATESTRUCT& cs)
{
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs
    return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CTurnImView drawing

void CTurnImView::OnDraw(CDC* pDC)
{
    CTurnImDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // TODO: add draw code for native data here
    if(GetDocument()->m_bloadfile){
        LoadFile(pDC);
        GetDocument()->m_bloadfile = false;
    }
    if(m_draw){
        Formating(pDC);
    }
    //pDC->DrawState(CPoint(0,0), CSize(m_bm.bmWidth, m_bm.bmHeight), m_hbitmap, DST_BITMAP);

}

/////////////////////////////////////////////////////////////////////////////
// CTurnImView printing

BOOL CTurnImView::OnPreparePrinting(CPrintInfo* pInfo)
{
    // default preparation
    return DoPreparePrinting(pInfo);
}

void CTurnImView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
    // TODO: add extra initialization before printing
}

void CTurnImView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
    // TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CTurnImView diagnostics

#ifdef _DEBUG
void CTurnImView::AssertValid() const
{
    CView::AssertValid();
}

void CTurnImView::Dump(CDumpContext& dc) const
{
    CView::Dump(dc);
}

CTurnImDoc* CTurnImView::GetDocument() // non-debug version is inline
{
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTurnImDoc)));
    return (CTurnImDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CTurnImView message handlers

void CTurnImView::DoDataExchange(CDataExchange* pDX) 
{
    CView::DoDataExchange(pDX);
}

//çàãðóçêà èç êàðòèíêè ôàéëà
void CTurnImView::LoadFile(CDC* pDC)
{
    m_hbitmap = GetDocument()->m_hBitmap; 
    GetObject(m_hbitmap, sizeof(BITMAP), (LPVOID)&m_bm);

    //Ðèñóåì ôàéë
    CDC dc;
    dc.CreateCompatibleDC(pDC);
    dc.SelectObject(m_hbitmap);
    
    //Êîïèðóåì åãî
    ::BitBlt(pDC->m_hDC, 0, 0, m_bm.bmWidth, m_bm.bmHeight, dc.m_hDC, 0, 0, SRCCOPY);
    dc.DeleteDC();
}

void CTurnImView::OnViewSetangle() 
{
    //âûñòàâëÿåì óãîë
    m_draw = true;
    CSetAngle Angle;
    if(Angle.DoModal() == IDOK){
        m_iangel = Angle.GetAngle();
    }
    InvalidateRect(0, 0);
}

// Àëãîðèòì ïîâîðîòà èçîáðàæåíèÿ. Ïóñòü: 
//
// O - ýòî öåíòð ïîâîðîòà, 
// M - íåêàÿ òî÷êà èñõîäíîãî èçîáðàæåíèÿ. 
// Äëÿ êàæäîé òî÷êè M íóæíî íàéòè óãîë alpha ìåæäó îòðåçêîì OM è
// ãîðèçîíòàëüþ è äëèíó r îòðåçêà OM. Òåïåðü, ÷òîáû ïîâåðíóòü èçîáðàæåíèå
// íà óãîë beta, íóæíî êàæäîé òî÷êå M ïðèñâîèòü öâåò òî÷êè èñõîäíîãî
// èçîáðàæåíèÿ ñ êîîðäèíàòàìè x,y, ãäå 
//
// x = xo + r * cos(alpha + beta)
// y = yo + r * sin(alpha + beta)
//
// xo,yo - öåíòð ïîâîðîòà, 
// r - äëèíà îòðåçêà OM 

// Âàæíî èìåííî êàæäîé òî÷êå íîâîãî èçîáðàæåíèÿ ñîïîñòàâëÿòü òî÷êó ñòàðîãî
// èçîáðàæåíèÿ, à íå íàîáîðîò, òàê êàê èíà÷å íåêîòîðûå òî÷êè íîâîãî
// èçîáðàæåíèÿ îñòàíóòñÿ íå çàêðàøåííûìè. 

void CTurnImView::Formating(CDC *pDC){
    CBitmap *bm, *bm1;

    CDC dc, dc1;
    dc.CreateCompatibleDC(pDC);
    dc1.CreateCompatibleDC(pDC);

    int x, y;
    float r;
    int xo, yo;
    double s, c;

    bm = new CBitmap;
    bm->Attach(m_hbitmap);
    dc.SelectObject(bm);

    xo = m_bm.bmWidth/2;
    yo = m_bm.bmHeight/2;
    bm1 = new CBitmap;
    bm1->CreateCompatibleBitmap(pDC, m_bm.bmWidth, m_bm.bmHeight);
    dc1.SelectObject(bm1);
    ::BitBlt(dc1.m_hDC, 0, 0, m_bm.bmWidth, m_bm.bmHeight, dc1.m_hDC, 0, 0, WHITENESS);

    for(y = 0; y < (m_bm.bmHeight - 1); y++){
        for(x = 0; x< (m_bm.bmWidth - 1); x++){
            
            r = sqrt(pow((x - xo), 2) + pow((y - yo), 2));

            SinCos(m_iangel + atan2((y - yo), (x - xo)), s, c);
            dc1.SetPixel(x, y, dc.GetPixel( (int)(xo + r * c), (int)(yo + r * s) ) );
        }
    }
    ::BitBlt(pDC->m_hDC, 0, 0, m_bm.bmWidth, m_bm.bmHeight, dc1.m_hDC, 0, 0, SRCCOPY);
    
    bm1->DeleteObject();
    bm->Detach();
    dc.DeleteDC();
    dc1.DeleteDC();


}

void CTurnImView::SinCos(double AngleRad, double &ASin, double &ACos)
{
    ASin = sin(AngleRad);
    ACos = cos(AngleRad);
}


Файл TurnImDoc.cpp
Код

void CTurnImDoc::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {
        // TODO: add storing code here
    }
    else
    {
        // TODO: add loading code here
        m_strputh = (ar.GetFile())->GetFilePath();
        m_hBitmap = (HBITMAP) LoadImage(0, m_strputh,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
        m_bloadfile = true;

    }
}

Автор: Earnest 22.12.2006, 08:44
The Thing, ну ты даешь!
Теоретически, конечно, поворот на 180 - это частный случай поворота на произвольный угол, но за подобное "общее" решение задачи я бы программиста сразу уволила. smile 

Автор: The Thing 22.12.2006, 15:39
1. ммм.. мы не на работе
2. Я хотел привести более сложный вариант поворота, откуда человек может почерпнуть то, что ему нужно! А на счет работы не переживай.. меня никто не заставит сделать больше, чем это будет оговоренно.. даже поворот на 180 градусов smile
Форум - учебный материал

Добавлено @ 15:46 
А вообще.. (только сейчас заметил...) у него не указана размерность.. по умолчанию идет в радианах! А в радианах - это не прямой угол. И тобою описанный метод - не подходит smile !

Автор: Earnest 25.12.2006, 08:46
Точно, скорее всего имелось ввиду - повернуть на 180 радиан... ты прав smile 

Автор: The Thing 25.12.2006, 12:01
Ну вот.. а меня уже увольнять собрались smile smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)