Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.10.2010, 19:21   #1
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию AV при попытке вращения изображения

Нашел код вращения имаги, подчистил напилником под HBitMap. Получаю AV.

Может есть 100% работающий метод? Тем паче, что я так и не понял, где здеь устанавливается угол.
Код:
 TTexture = Record // Удобная надстройка
   Bitmap : HBitMap;
   Width  : LongInt;
   Height : LongInt;
  End;
Код:
Procedure RotateRight(Var T : TTexture);
 Var
  FirstC : Integer;
  LastC  : Integer;
  C      : Integer;
  R      : Integer;
  C2     : Integer;
  R2     : Integer;

  BI     : BitMapInfo;
  A      : Array of RGBQuad;
  Loc    : HDC;

  Procedure FixPixels(C1, R1 : Integer);
  Var
   SavePix  : RGBQuad;
   SavePix2 : RGBQuad;
   I        : Integer;
   NewC     : Integer;
   NewR     : Integer;
  Begin
   SavePix := A[C1 + (T.Height - 1 - R1) * T.Width];
   For I := 1 To 4 Do
    Begin
     NewC := T.Height - R1 + 1;
     NewR := C1;
     SavePix2 := A[NewC + (T.Height - 1 - NewR) * T.Width];
     A[NewC + (T.Height - 1 - NewR) * T.Width] := SavePix;
     SavePix := SavePix2;
     C1 := NewC;
     R1 := NewR;
    End;
  End;

 Begin
  Loc := CreateCompatibleDC(Warehouse.Buffer.DC);
  SelectObject(Loc, T.Bitmap);
  ZeroMemory(@BI, SizeOf(BI));
  BI.bmiHeader.biWidth := T.Width;
  BI.bmiHeader.biHeight := T.Height;
  BI.bmiHeader.biSize := SizeOf(BitMapInfoHeader);
  BI.bmiHeader.biCompression := BI_RGB;
  BI.bmiHeader.biBitCount := 32;
  BI.bmiHeader.biPlanes := 1;
  SetLength(A, T.Height * T.Width * 4);
  GetDIBits(Loc, T.Bitmap, 0, T.Height, @A[0], @BI, DIB_RGB_COLORS);

  FirstC := 0;
  LastC := T.Width;
  For R2 := 0 To T.Height Div 2 Do
   Begin
    For C2 := FirstC To LastC Do FixPixels(C,R);
    Inc(FirstC);
    Dec(LastC);
   End;

  SetDIBits(Loc, T.Bitmap, 0, T.Height, @A[0], @BI, DIB_RGB_COLORS);
  DeleteDC(Loc);
 End;
P.S. Нашел код на С++:
Код:
HBITMAP GetRotatedBitmapNT( HBITMAP hBitmap, float radians, COLORREF clrBack )
{
    // Create a memory DC compatible with the display
    CDC sourceDC, destDC;
    sourceDC.CreateCompatibleDC( NULL );
    destDC.CreateCompatibleDC( NULL );

    // Get logical coordinates
    BITMAP bm;
    ::GetObject( hBitmap, sizeof( bm ), &bm );

    float cosine = (float)cos(radians);
    float sine = (float)sin(radians);

    // Compute dimensions of the resulting bitmap
    // First get the coordinates of the 3 corners other than origin
    int x1 = (int)(bm.bmHeight * sine);
    int y1 = (int)(bm.bmHeight * cosine);
    int x2 = (int)(bm.bmWidth * cosine + bm.bmHeight * sine);
    int y2 = (int)(bm.bmHeight * cosine - bm.bmWidth * sine);
    int x3 = (int)(bm.bmWidth * cosine);
    int y3 = (int)(-bm.bmWidth * sine);

    int minx = min(0,min(x1, min(x2,x3)));
    int miny = min(0,min(y1, min(y2,y3)));
    int maxx = max(0,max(x1, max(x2,x3)));
    int maxy = max(0,max(y1, max(y2,y3)));

    int w = maxx - minx;
    int h = maxy - miny;

    // Create a bitmap to hold the result
    HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL), w, h);

    HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
    HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );

    // Draw the background color before we change mapping mode
    HBRUSH hbrBack = CreateSolidBrush( clrBack );
    HBRUSH hbrOld = (HBRUSH)::SelectObject( destDC.m_hDC, hbrBack );
    destDC.PatBlt( 0, 0, w, h, PATCOPY );
    ::DeleteObject( ::SelectObject( destDC.m_hDC, hbrOld ) );

    // We will use world transform to rotate the bitmap
    SetGraphicsMode(destDC.m_hDC, GM_ADVANCED);
    XFORM xform;
    xform.eM11 = cosine;
    xform.eM12 = -sine;
    xform.eM21 = sine;
    xform.eM22 = cosine;
    xform.eDx = (float)-minx;
    xform.eDy = (float)-miny;

    SetWorldTransform( destDC.m_hDC, &xform );

    // Now do the actual rotating - a pixel at a time
    destDC.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &sourceDC, 0, 0, SRCCOPY );

    // Restore DCs
    ::SelectObject( sourceDC.m_hDC, hbmOldSource );
    ::SelectObject( destDC.m_hDC, hbmOldDest );

    return hbmResult;
}
Но я не сишник, потому хотелось бы перевод :P
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ

Последний раз редактировалось Alex Cones; 10.10.2010 в 19:27.
Alex Cones вне форума Ответить с цитированием
Старый 10.10.2010, 20:09   #2
Altera
Старожил
 
Аватар для Altera
 
Регистрация: 29.01.2008
Сообщений: 2,406
По умолчанию

Код:
function GetRotatedBitmapNT(hBitmap: tHandle; radians: float; clrBlack: COLORREF): tHandle;
var
  sourceDC, destDC: tCDS;
  bm: tBitmap;

  cosine, sine: float;

  x1, x2, x3, y1, y2, y3: integer;

  minx, miny, maxx, maxy: integer;

  w, h: integer;

  hbmResult, hbmOldSource, hbmOldDest: tHandle;

  hbrBack, hbrOld: tHandle;

  xform: tXForm;
begin
    sourceDC.CreateCompatibleDC( NULL );
    destDC.CreateCompatibleDC( NULL );

    GetObject( hBitmap, sizeof(bm), @bm);
    
    x1 := round(bm.Height * sine);
    xy := round(bm.Height * cosine);
    x2 := round(bm.Width * cosine + bm.Height * sine);
    y2 := round(bm.Height * cosine - bm.Width * sine);
    x3 := round(bm.Width * cosine);
    y3 := round(-bm.Width * sine);

    minx := min(0, min(x1, min(x2, x3)));
    miny := min(0, min(y1, min(y2, y3)));
    maxx := max(0, max(x1, max(x2, x3)));
    maxy := max(0, max(y1, max(y2, y3)));
    
    w := maxx - minx;
    h := max - miny;

    hbmResult := CreateCompatibleBitmap(CClientDC(NULL), w, h);

    hbmOldSource = tHandle(SelectObject(sourceDC.m_hDC, hBitmap));
    hbmOldDest = tHandle(SelectObject(destDC.m_hDC, hbmResult));

    hbrBack := CreateSolidBrush(clrBack);
    hbrOld := tHandle(SelectObject(destDC.m_hDC, hbrBack));

    destDC.PatBlt(0, 0, w, h, PATCOPY);
    DeleteObject(SelectObject(destDC.m_hDC, hbrOld));

    xform.eM11 := cosine;
    xform.eM12 := -sine;
    xform.eM21 := sine;
    xform.eM22 := cosine;
    xform.eDx := round(-minx);
    xform.eDy := round(-miny);

    SetWorldTransform(destDC.m_hDC, @xform);

    destDC.BitBlt(0, 0, bm.bmWidth, bm.Height, @sourceDC, 0, 0, SRCCOPY);

    SelectObject(sourceDC.m_hDC, hbmOldSource);
    SelectObject(destDC.m_hDC, hbmOldDest);

    result := hbmResult;
end;
Altera вне форума Ответить с цитированием
Старый 10.10.2010, 20:17   #3
DomiNick
Студент, не
Старожил
 
Аватар для DomiNick
 
Регистрация: 29.01.2009
Сообщений: 2,067
По умолчанию

У меня AV на строке:
Код:
SavePix := A[C1 + (T.Height - 1 - R1) * T.Width];
Может нужно размер массиву задавать, а то как-то без инициализации-то.....
Или он туда неправильный передаётся...

Сейчас посмотрю что там дальше.....
I am the First of Cyber Evolution...
I am the First to Program your Future...
DomiNick вне форума Ответить с цитированием
Старый 10.10.2010, 20:19   #4
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Длина массива задается позже - это предобъявленная функа.

Altera, код к сожалению не рабочий, Delphi и C++ спуталось. Но спасибо за попытку.
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ
Alex Cones вне форума Ответить с цитированием
Старый 11.10.2010, 14:31   #5
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Моя версия. Подмогните перевести выделенные строки.
Код:
Function GetRotatedBitmapNT(
 BitMap : HBITMAP, 
 Radians : Real, 
 COLORREF clrBack )
:HBitMap;
Var
 SourceDC, DestDC : HDC;
 bm : TBitMap;
 Cosine, Sine : Real;
 X1, Y1, X2, Y2, X3, Y3 : Integer;
 MinX, MinY, MaxX, MaxY : Integer;
 W, H : Integer;
 hbmResult, hbmOldSource, hbmOldDest : HBitMap;
 hbrBack, hbrOld : HBrush;
 formX : XForm;
Begin
 SourceDC := CreateCompatibleDC(Nil);
 DestDC := CreateCompatibleDC(Nil);
 GetObject(Bitmap, sizeof(bm), @bm);
 
 Cosine := Cos(Radians);
 Sine    := Sin(Radians);

 X1 := Round(bm.bmHeight * Sine);
 Y1 := Round(bm.bmHeight * Cosine);
 X2 := Round(bm.bmWidth * Cosine + bm.bmHeight * Sine);
 Y2 := Round(bm.bmHeight * Cosine - bm.bmWidth * Sine);
 X3 := Round(bm.bmWidth * Cosine);
 Y3 := Round(-bm.bmWidth * Sine);

 MinX := Min(0,Min(X1, Min(X2,X3)));
 MinY := Min(0,Min(Y1, Min(Y2,Y3)));
 MaxX := Max(0,Max(X1, Max(X2,X3)));
 MaxY := Max(0,Max(Y1, Max(Y2,Y3)));

 W := MaxX - MinX;
 H := MaxY - MinY;

 hbmResult := CreateCompatibleBitmap(CClientDC(Nil), w, h);
 hbmOldSource := SelectObject( sourceDC.m_hDC, hBitmap );
 hbmOldDest := SelectObject( destDC.m_hDC, hbmResult );

 hbrBack = CreateSolidBrush( clrBack );
 hbrOld = SelectObject( destDC.m_hDC, hbrBack );
 destDC.PatBlt( 0, 0, w, h, PATCOPY );
 DeleteObject(SelectObject(destDC.m_hDC, hbrOld));

  SetGraphicsMode(destDC.m_hDC, GM_ADVANCED);
   FormX.eM11 = Cosine;
   FormX.eM12 = -Sine;
   FormX.eM21 = Sine;
   FormX.eM22 = Cosine;
   FormX.eDx = -MinX;
   FormX.eDy = -MinY;

   SetWorldTransform( destDC.m_hDC, @FormX );

    destDC.BitBlt(0,0,bm.bmWidth, bm.bmHeight, @SourceDC, 0, 0, SRCCOPY );

    SelectObject( sourceDC.m_hDC, hbmOldSource );
    SelectObject( destDC.m_hDC, hbmOldDest );

    Result := hbmResult;
End;
Непонятные мне конструкции подчеркнул.
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ
Alex Cones вне форума Ответить с цитированием
Старый 11.10.2010, 14:58   #6
DomiNick
Студент, не
Старожил
 
Аватар для DomiNick
 
Регистрация: 29.01.2009
Сообщений: 2,067
Восклицание

Не знаю что есьм "Warehouse.Buffer.DC" поставил заместо него "Form1.Canvas.Handle" вроде сойдёт...
В GetDIBits у меня не указатель на BI хочет а саму переменную (это Лазарус чтоль не совпал так?)...

Вот что: вызывается FixPixels(C, R) тогда как переменные C и R не инициализированны... И получается что идёт обращение к какому-то минус тридцатитысячному элементу A[]... Может там нужно было C1 и R1?
Запутался я в этой процедуре, можно сам алгоритм взглянуть где-нибудь? Поворот на какой грудус-то нужен - на любой?
Цитата:
Подмогните перевести выделенные строки.
Там DestDC и остальные - это не HDC, а CDC... Не очень припоминаю, но это вроде некий аналог VCL'ского TCanvas в MFC...
Тогда просто стереть точку и то что после неё... destDC.BitBlt() - это вроде MFC'шная обёртка, тож самое что BitBlt(destDC, ...), заместо COLORREF вроде Cardinal пойдёт...

Хотя.... А да там вообще всё можно выкинуть - весь поворот на апи-функции PatBlt делается по сути-то...
I am the First of Cyber Evolution...
I am the First to Program your Future...
DomiNick вне форума Ответить с цитированием
Старый 11.10.2010, 15:03   #7
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

http://pblog.ru/lab/?p=341#more-341
http://pblog.ru/lab/?p=652
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ
Alex Cones вне форума Ответить с цитированием
Старый 11.10.2010, 15:11   #8
DomiNick
Студент, не
Старожил
 
Аватар для DomiNick
 
Регистрация: 29.01.2009
Сообщений: 2,067
По умолчанию

Цитата:
на апи-функции PatBlt делается
Точнее тут через SetWorldTransform, а вообще посмотрите функцию PlgBlt... *
I am the First of Cyber Evolution...
I am the First to Program your Future...
DomiNick вне форума Ответить с цитированием
Старый 11.10.2010, 15:43   #9
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Если честно, не понял, как из параллелограмма получить вращение.
http://vsokovikov.narod.ru/New_MSDN_...dtransform.htm - а вот это уже полезней, но не до конца понял, как заюзать.

Вот нашел пример, но цифры не понятно, откуда:
Цитата:
case ROTATE: // Повернем на 30 градусов против часовой стрелки.
xForm.eM11 = (FLOAT) 0.8660;
xForm.eM12 = (FLOAT) 0.5000;
xForm.eM21 = (FLOAT) -0.5000;
xForm.eM22 = (FLOAT) 0.8660;
xForm.eDx = (FLOAT) 0.0;
xForm.eDy = (FLOAT) 0.0;
SetWorldTransform(hDC, &xForm);
P.S. Нашел объяснение цифрам: http://vsokovikov.narod.ru/New_MSDN_.../str_xform.htm
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ

Последний раз редактировалось Alex Cones; 11.10.2010 в 15:47.
Alex Cones вне форума Ответить с цитированием
Старый 11.10.2010, 19:20   #10
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Уже битый час сижу и не могу понять, что не так.
Код:
var B:TBitMap;
procedure TForm2.FormCreate(Sender: TObject);
var M:TXFORM;
    a:Double;
    HDC:THandle;
begin
   B := TBitMap.Create;
   B.LoadFromFile('logo.bmp');

   hDc := image1.Canvas.Handle;
   SetGraphicsMode(hDc, GM_ADVANCED);

   M.eM11 := 1;
   M.eM12 := 0;
   M.eM21 := 0;
   M.eM22 := 1;
   M.eDx := -B.Width div 2;
   M.eDy := -B.Height div 2;
   SetWorldTransform(hDc, M);

   a := PI/6;
   fillChar(M, sizeOf(M), 0);
   M.eM11 := Cos(a);
   M.eM12 := Sin(a);
   M.eM21 := -Sin(a);
   M.eM22 := Cos(a);
   M.eDx := 0;
   M.eDy := 0;
   ModifyWorldTransform(hDc, M, MWT_RIGHTMULTIPLY);

   M.eM11 := 1;
   M.eM12 := 0;
   M.eM21 := 0;
   M.eM22 := 1;
   M.eDx := B.Width div 2;
   M.eDy := B.Height div 2;
   ModifyWorldTransform(hDc, M, MWT_RIGHTMULTIPLY);

   image1.Canvas.Draw(0, 0, b);
// или BitBlt(hDc, 0, 0, image1.Width, image1.Height, B.Canvas.Handle, 0, 0, SRCCOPY);
end;
- Этот код нашел на нашем форуме. Судя по отзывам - рабочий. Вот только я не могу его под чистый API заточить. Мне нужно повернуть hBitMap на N градусов по часовой.
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ
Alex Cones вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при попытке повторного открытии окна ssdm Общие вопросы по Java, Java SE, Kotlin 0 25.01.2010 19:41
приложение подвисает, при попытке обновить шрифты AnTe Общие вопросы Delphi 2 07.12.2009 11:36
Ощибка при попытке заменить компонент ogg Помощь студентам 3 16.07.2009 18:57
ошибка при попытке запустить программу Fellot Общие вопросы Delphi 3 23.04.2009 21:23
Ошибка при попытке вывода полей из таблицы в ORACLE older Общие вопросы Delphi 2 04.06.2008 17:26