C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Вырезать кусок TImage, Имея только координаты
Aptem
Отправлено: 25.02.2006, 15:16


Мастер участка

Группа: Участник
Сообщений: 349



Привет, всем.

Очередная проблема с изображениями sad.gif

Есть одномерный массив, собственно изображение. В программе я формирую bmp файл и вывожу его на экран через TImage. Пользователь выделяет область изображения. То есть имееются координаты верхнего левого угла (x и y) и правого нижнего угла, тоже x и y. Мне необходимо вырезать из одномерного массива эту выделенную область и вывести на экран уже обрезанную. Не могу сообразить как это сделать!

Напоминаю, что одномерный массив это само изображение, без всяких там палитр и заголовков.

Надеюсь на вашу помощь. Спасибо.
Grigoriy
Отправлено: 26.02.2006, 03:46


Мастер участка

Группа: Участник
Сообщений: 381



Изображение из массива можно выводить даже без всяких там КАНВ и Т_ИМАДЖЕ весьма БЫСТРО, легко, и не использовать излишних наворотов, которые только загружают ЦП.

Для вывода изображений из массива в окно предназначена замечательная API функция, которая называется

CODE

int SetDIBitsToDevice(HDC:DC, int DestX, int DestY, unsigned long Width, unsigned long Height, int SrcX, int SrcY, unsigned int StartScan, unsigned int NumScans, const void* Bits, const tagBITMAPINFO* BitsInfo, unsigned int);

Устанавливает биты на поверхности устpойства пpямо из каpты бит, независящей от устpойства.


Паpаметpы:
DC: Контекст устpойства.
DestX, DestY: Начало прямоугольника назначения в устройстве.
Width: Экстент по X пpямоугольника DIB.
Height: Экстент по Y пpямоугольника DIB.
SrcX, SrcY: Исходное положение DIB.
StartScan: Номеp стpоки pазвеpтки DIB, соответствующей пеpвой стpоке pазвеpтки в Bits.
NumScans: Число стpок pазвеpтки DIB в Bits.
Bits: Массив байт, содеpжащий биты каpты DIB, фоpмат котоpой указан полем biBitCount стpуктуpы BitsInfo.
BitsInfo: Стpуктуpа TBitmapInfo, содеpжащая инфоpмацию о каpте DIB.
Usage: Описывает содеpжимое полей bmiColors стpуктуpы BitsInfo.


В свою очередь
tagBITMAPINFO
состоит из следующих полей
CODE

tagBITMAPINFOHEADER tagBITMAPINFO::bmiHeader
tagRGBQUAD[1] tagBITMAPINFO::bmiColors

В свою очередь tagBITMAPINFOHEADER
состоит из следующих полей
CODE

unsigned long  tagBITMAPINFOHEADER::biSize
//размер структуры tagBITMAPINFOHEADER в байтах
long tagBITMAPINFOHEADER::biWidth
//ширина изображения
long tagBITMAPINFOHEADER::biHeight
//высота изображения
unsigned short tagBITMAPINFOHEADER::biPlanes
//число битовых плоскостей
unsigned short tagBITMAPINFOHEADER::biBitCount
//число бит приходящихся на один пиксел
unsigned long tagBITMAPINFOHEADER::biCompression
//метод сжатия (обычно = 0)
unsigned long tagBITMAPINFOHEADER::biSizeImage
//размер изображения в байтах
long tagBITMAPINFOHEADER::biXPelsMeter
long tagBITMAPINFOHEADER::biYPelsMeter
unsigned long tagBITMAPINFOHEADER::biClrUsed
unsigned long tagBITMAPINFOHEADER::biClrImportant


Перед выводом изображения из массива устанавливаем
нужные значения полей.
В нашем случае число битовых плоскостей равно 1.
Размер структуры tagBITMAPINFOHEADER вычисляем оператором sizeof.
Поля
long tagBITMAPINFOHEADER::biXPelsMeter
long tagBITMAPINFOHEADER::biYPelsMeter
unsigned long tagBITMAPINFOHEADER::biClrUsed
unsigned long tagBITMAPINFOHEADER::biClrImportant
лично я не устанавливал.

Далее поле bmiColors тоже не устанавливал.

Теперь объясню значение каждого локального параметра функции.

Дело заключается в следующем.
В массиве Имеется некоторое прямоугольное изображение, которое может даже занимать площадь в несколько раз болшую, чем площадь экрана, а может и меньше. Высота и ширина этого изображения может быть больше высоты и ширины изображения рабочего стола.
Цель функции — вывести в нужную область нужного окна (необязательно на весь экран, а можно и во весь!) часть этого общего изображения.

Имеется две двумерные системы Декартовых координат.

1) Система Декартовых координат окна, в которое выводится часть исходного изображения; в этой системе ось горизонтальная направлена слева направо;вертикальная ось — сверху вниз;
2) Система Декартовых координат Исходного изображения; в этой системе ось горизонтальная направлена слева направо;вертикальная ось — снизу вверх !


Прямоугольный участок исходного изображения определяется так.
Вершина нижнего левого угла участка исходного изображения определяется относительно второй системы координат локальными переменными


int SrcX;
int SrcY;


Размер же этого участка записан в


unsigned long Width;
unsigned long Height.


А позиция этого участка на экране определяется так.
Координаты верхнего левого угла участка относительно первой системы координат хранятся в следующих переменных


int DestX;
int DestY.


unsigned int StartScan установим в 0.
unsigned int NumScans установим равным ширине исходного (общего)изображения.

Я проверял скорость вывода изображения этой функцией на своем компьютере.
Сделал окно распахнутое во весь экран включая нижнюю панель задач.
Выводил изображение во весь экран.
Удавалось выводить до 150 полноэкранных изображений в секунду.
Так что думаю, если сделаю трехмерный движок, который отображает плоские поверхности с текстурами, где ориентация каждой плоской поверхности будет задана базисом системы координат принадлежащей этой поверхности относительно общей системы координат и будет задан базис виртуальной камеры, то с помощью матрицы перехода от базиса отображаемой текстуры к базису виртуальной камеры можно достич высокого быстродействия !

А теперь я предоставлю Вам две программы.
1) Программа, делающая приблизительно то, что спрашивал Артём.
2) Программа воспроизводящая интересный эффект.
Все они выводят изображение с помощью вышеприведенной АПИ-функции.

И так я приведу сначала коды модулей, а расстановку компонентов и прочую ерунду можно скачать с присоединенного файла.

И так — код модуля первой проги

CODE

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1SetDIBitsToDevice.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
unsigned int vb[1000000];
tagBITMAPINFO* bi= new tagBITMAPINFO;
void* p;
int i;
int pr;
unsigned short int  DestX1, DestY1, Width1, Height1, SrcX1, SrcY1, StartScan, NumScans,
 X1,X2,Y1,Y2;
void sq()
{
Form1->Repaint();
/*function SetDIBitsToDevice
(DC: HDC; DestX, DestY, Width, Height,
SrcX, SrcY; StartScan, NumScans: Word;
Bits: Pointer; var BitsInfo: TBitmapInfo; Usage: Word): Integer;*/
SetDIBitsToDevice(Form1->Canvas->Handle,DestX1,DestY1,
Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
};

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
{
p=vb;
for (i=0;i<1000000;i++) vb[i]=i;//это Вы можете делать по своему
bi->bmiHeader.biSize=sizeof(bi->bmiHeader);
bi->bmiHeader.biWidth=500;
bi->bmiHeader.biHeight=500;
bi->bmiHeader.biPlanes=1;
bi->bmiHeader.biCompression=0;
bi->bmiHeader.biBitCount=32;
bi->bmiHeader.biSizeImage=4000000;
pr=0;
ScrollBar3->Position=500;
ScrollBar4->Position=500;
}
//---------------------------------------------------------------------------


void __fastcall TForm1::ScrollBar1Scroll(TObject *Sender,
     TScrollCode ScrollCode, int &ScrollPos)
{
DestX1=Form1->ScrollBar1->Position;
DestY1=Form1->ScrollBar2->Position;
Width1=Form1->ScrollBar3->Position;
Height1=Form1->ScrollBar4->Position;
SrcX1=Form1->ScrollBar5->Position;
SrcY1=Form1->ScrollBar6->Position;
StartScan=0;
NumScans=500;
sq();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
     TShiftState Shift, int X, int Y)
{
if (pr==0) {
X1=X;
Y1=Y;
pr=1;
}
else
{
X2=X;
Y2=Y;
pr=0;
Form1->Repaint();
sq();
SetDIBitsToDevice(Form1->Canvas->Handle,600,100,X2-X1,Y2-Y1,SrcX1+(X1-DestX1),
SrcY1+(DestY1+Height1-Y2),0,500,p,bi,0);
};
}
//---------------------------------------------------------------------------



void __fastcall TForm1::FormCreate(TObject *Sender)
{
Form1->BorderStyle=bsNone;
Form1->WindowState=wsMaximized;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
DestX1=Form1->ScrollBar1->Position;
DestY1=Form1->ScrollBar2->Position;
Width1=Form1->ScrollBar3->Position;
Height1=Form1->ScrollBar4->Position;
SrcX1=Form1->ScrollBar5->Position;
SrcY1=Form1->ScrollBar6->Position;
StartScan=0;
NumScans=500;
sq();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
Application->Terminate();
}


Значит, небольшое пояснение к работе с 1 программой.
Сначала Вы её запускаете, нажимаете на клавишу запуска.
Появится изображение, сформированное через массив.
Потом наводите курсор мыши на какую-нибудь точку этого изображения и клацаете. Потом отпускаете кнопку мыши.
Отводите курсор мыши правее и ниже и все же на изображение и снова клац...
И в итоге в позиции (600;100) должен появиться участок...

Код модуля второй проги.

CODE


//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1effectSetDIBitsToDevice.h"
#include "math.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
unsigned int masim[4000000];
tagBITMAPINFO* bi= new tagBITMAPINFO;
void* p;
int i;
int pr;
unsigned short int  DestX1, DestY1, Width1, Height1, SrcX1, SrcY1, StartScan, NumScans,
 X1,X2,Y1,Y2;
HDC D;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
{

}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClick(TObject *Sender)
{
int i,fy,j,k;
D=Form1->Canvas->Handle;
SetDIBitsToDevice(D,DestX1,DestY1,
Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
bi->bmiHeader.biSize=sizeof(bi->bmiHeader);
bi->bmiHeader.biWidth=1024;
bi->bmiHeader.biHeight=768;
bi->bmiHeader.biPlanes=1;
bi->bmiHeader.biCompression=0;
bi->bmiHeader.biBitCount=32;
bi->bmiHeader.biSizeImage=1024*768*4;
DestX1=0;
DestY1=0;
Width1=1024;
Height1=768;
SrcX1=0;
SrcY1=0;
StartScan=0;
NumScans=1024;
p=masim;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
     int X, int Y)
{
unsigned int x,y,i,j,c,r;
c=0;
for (j=768;j>0;j--)
for (i=0;i<1024;i++)
{r=abs(X-i)*abs(X-i)+abs(Y-j)*abs(Y-j);
masim[c]=r*256;
c++;}
D=Form1->Canvas->Handle;
SetDIBitsToDevice(D,DestX1,DestY1,
Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
     TShiftState Shift, int X, int Y)
{
unsigned int x,y,i,j,c,r,c1,ht;
ht=0;
for (c1=0;c1<100;c1++){ht++;c=0;
for (j=768;j>0;j--)
for (i=0;i<1024;i++)
{r=abs(X-i)*abs(X-i)+abs(Y-j)*abs(Y-j)-ht*ht*1000;
masim[c]=r*256;
c++;}
D=Form1->Canvas->Handle;
SetDIBitsToDevice(D,DestX1,DestY1,
Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);}
}



Когда запустите эту прогу, то увидите нечто интересное и клацнете мышью и будет ещё интереснее.

Незабудьте перерисовывать свои изображения, а то ведь они выводились API-функцией.

ФАЙЛЫ :

User Attached Image Скачать файл
prog1_and_2.zip


Grigoriy
Отправлено: 27.02.2006, 03:16


Мастер участка

Группа: Участник
Сообщений: 381



Пробовал вместо дескриптора устройства окна программы использовать дескриптор устройства самого экрана (GetDC(0)). При полноэкранном окне шло все нормально. После завершения работы програмы все окна обновлялись нормально.
Интересно, когда в свойстве окна WindowState установил так чтоб окно было не навесь экран, то пошли такие глюки с рабочим столом...
А вообще, кто нибудь знает как можно ещё быстрее вывести изображение на весь экран, чем я предлагаю ?
Или API-функция SetDIBitsToDevice — это самый быстрый способ ?

Отредактировано Grigoriy — 27/02/2006, 03:22
Grigoriy
Отправлено: 15.03.2006, 08:15


Мастер участка

Группа: Участник
Сообщений: 381



Только что узнал как ещё создать более эффективное устройство для вывода изображения из массива на экран ! biggrin.gif

Вот так его надо создать

CODE

//----------------------------------------
HDC D;
//----------------------------------------
D=CreateDC("DISPLAY",0,0,0);


По виду выводит ещё быстрее изображение.

Я только что убедился что в предыдущем коде, если заменить устройство на "новое" скорость изменения изображения больше.
А основное время тратится на вычисление цветов пикселов.
Я сейчас на Ассемблере создам аналогичный алгоритм. Посмотрю что будет. smile.gif
Grigoriy
Отправлено: 15.03.2006, 09:37


Мастер участка

Группа: Участник
Сообщений: 381



Составил код на встроенном ассемблере.

Обрадовался. Блин, фурычит наверно раза в два быстрее, чем при использовании C++ !
Да, теперь убедился,
ASSEMBLER выигрывает по скорости.
Я умнее компилятора оказался biggrin.gif biggrin.gif .

Вот обработчик отпускания кнопки мыши...
Полную версию демо-программы можно скачать по ссылке выше.

CODE

void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
     TShiftState Shift, int X, int Y)
{
unsigned int x,y,i,j,c,r,c1,ht;
unsigned int v1000=1000;
ht=0;
asm
{
mov esi,X;
mov edi,Y;
mov c1,0;
@c3:cmp c1,100;
jz @1;
inc ht;
mov ecx,0;
mov j,768;
@c2:cmp j,0;
jz @2;
mov i,0;
@c1:cmp i,1024;
jz @3;
mov eax,esi;
sub eax,i;
jg @n1;
neg eax;
@n1:mul eax;
mov ebx,eax;
mov eax,edi;
sub eax,j;
jg @n2;
neg eax;
@n2:mul eax;
add ebx,eax;
mov eax,ht;
mul eax;
mov edx,v1000;
mul edx;
sub ebx,eax;
shl ebx,8;
mov masim+ecx*4,ebx;
inc ecx;
inc i;
jmp @c1;
@3:dec j;
jmp @c2;
@2:inc c1;
};
SetDIBitsToDevice(D,DestX1,DestY1,Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
asm{
jmp @c3;
@1:
};
/*for (c1=0;c1<100;c1++){ht++;c=0;
for (j=768;j>0;j--)
for (i=0;i<1024;i++)
{r=abs(X-i)*abs(X-i)+abs(Y-j)*abs(Y-j)-ht*ht*1000;
masim[c]=r*256;
c++;}
SetDIBitsToDevice(D,DestX1,DestY1,Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
}*/
}


Если кто хочет сравнить быстродействие, пусть раскомментит код на C++ и закомментит АСМ-овский !
Grigoriy
Отправлено: 15.03.2006, 10:28


Мастер участка

Группа: Участник
Сообщений: 381



Я ещё попытаюсь с помощью инструкций так называемого
расширения процессора
Multimedia Extension
составить этот алгоритм.
Если кто не знает, что такое MMX-расширение центрального процессора, то я могу объяснить.
MMX-расширение — это специальный набор инструкций, которые позволяют выполнять четыре одинаковые арифметико-логические операции над соответствующими четырьмя операндами (унарная операция) или четырьмя парами операндов (бинарная операция)
ЗА ОДИН ТАКТ.
Это расширение впервые появилось в микропроцессорах раннего семейства Pentium (насколько я знаю). Если кто помнит — был микропроцессор Pentium MMX... и там что-то дописывалось.
Это расширение предназначено для составления программ обработки видео и звуковой информации. В учебнике у меня описаны все команды MMX-расширения вплоть до процессора семейства Pentium III.
В теперешних процессорах (современных) MMX-расширение ещё делится на два подтипа -
старое MMX
новое XMM.
XMM-расширение — это просто часть MMX, но это расширение предназначено для обработки упакованных операндов с плавающей точкой размером 4 байта каждое (короткие вещественные числа). В то время как целочисленное MMX может обрабатывать упакованные целые размером 16 бит каждое.
Ну целочисленное расширение появилось первым.
А вещественное появилось только в микропроцессорах семейства Pentium III. Кроме того были добавлены ещё некоторые команды в целочисленное расширение.

Для работы с целочисленным MMX-расширением есть 8
64-битных регистров, в каждом из которых хранятся по 4 целых числа. Вот эти числа целые называются по другому ещё — УПАКОВАННЫЕ ЦЕЛЫЕ ЧИСЛА.
А сами эти регистры являются частями регистров устройства процессора для выполнения операций с плавающей точкой (сопроцессора). Каждый из них просто занимает младшие 64 бита 80-битного регистра стека.

А расширение XMM (дробное расширение) использует уже отдельные 8
128-разрядные регистры, в кждом из которых хранится 4 коротких вещественных числа. И эти числа называются соответственно УПАКОВАННЫЕ ВЕЩЕСТВЕННЫЕ ЧИСЛА.
И ещё в дробном расширении есть логические команды для выполнения логической операции над 128 битами одновременно за один такт.

Далее.
У меня есть такие сведения (если кто их опровергнет, пусть напишет в этой теме).
Процессор современный имеет три устройства для выполнения микроопераций:
1- устройство для работы с памятью
2- устройство для работы с целочисленными операндами
3- устройство для работы с вещественными операндами
И все эти три устройства могут работать абсолютно параллельно при условии если для выполнения микрооперации никакому из них не нужен результат выполнения микрооперации другого устройства процессора.
Что такое микрооперации ?
Это елементарные операции, осуществляемые одним из вышеприведенных устройств процессора.
Чем они отличаются от инструкций процессора ?
Тем что для выполнения одной инструкции во многих случаях должно быть задействовано не одно устройство процессора, а например два.
К примеру арифметическая инструкция использующая операнд в памяти востребует и работы устройства для работы с памятью и устройство АЛУ. Для декодирования команд в микрооперации в процессоре существуют декодеры. На сколько я знаю из учебника ещё в Pentium III их было три. Два простых декодера и один сложный. И простые декодеры могли выдавать только одну микрооперацию за такт, а сложный четыре.
А потом ещё процессор как то хитро переставляет местами микрооперации, чтобы от этой перестановки ничего не изменилось, а устройства были задействованы максимально эффективно.
Вот кто не знает, пусть теперь узнает то что я написал !
Так вот, хитрость заключается в том, что проц может одновременно выполнять какую-нибудь арифметическую операцию и подгружать в том же такте из памяти какой-то операнд для следующей операции.

Но все это хорошо конечно.
Но есть ещё какие-то расширения типа 3D Now !
Я не знаю набора инструкций этих расширений. Может найду в интернете. И хотя бы коды этих команд найти. Если не распознает компилятор, то можно и просто целыми числами писать код.

Может я далеко отошел от темы ?
Grigoriy
Отправлено: 15.03.2006, 11:33


Мастер участка

Группа: Участник
Сообщений: 381



Да, сам исходный алгоритм можно преобразовать конечно...
Если кто заметил, даже исходный алгоритм по сути неефективен.
Ту же суть можно реализовать по другому.

Ведь в цикле выражение abs(Y-j)*abs(Y-j) в общем то равно
(Y-j)*(Y-j)
biggrin.gif biggrin.gif biggrin.gif
и изменяется оно редко (реже) чем
abs(X-i)*abs(X-i)
И то равно
(X-i)*(X-i)

Но это уже чисто алгоритмические преобразования.
Их можно сделать в любом случае.
Главное — мы знаем ресурсы процессора.

Отредактировано Grigoriy — 15/03/2006, 11:38
Grigoriy
Отправлено: 15.03.2006, 12:52


Мастер участка

Группа: Участник
Сообщений: 381



Еще раз преобразовал свою демку.
Изменил две функции — обработчика.
Теперь изображение от курсора мыши вообще не отстает.
И учитывается положение курсора мыши при изменении изображения после отпускания кнопки. Добавил число прохождений цикла.
Эффект на вид ещё стал лучше.

CODE

void __fastcall TForm1::FormCreate(TObject *Sender)
{
bi->bmiHeader.biSize=sizeof(bi->bmiHeader);
bi->bmiHeader.biWidth=1024;
bi->bmiHeader.biHeight=768;
bi->bmiHeader.biPlanes=1;
bi->bmiHeader.biCompression=0;
bi->bmiHeader.biBitCount=32;
bi->bmiHeader.biSizeImage=1024*768*4;
DestX1=0;
DestY1=0;
Width1=1024;
Height1=768;
SrcX1=0;
SrcY1=0;
StartScan=0;
NumScans=1024;
p=masim;
D=CreateDC("DISPLAY",0,0,0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
     int X, int Y)
{
unsigned int x,y,i,j,c,r,Yj;
/*c=0;
for (j=768;j>0;j--)
for (i=0;i<1024;i++)
{r=abs(X-i)*abs(X-i)+abs(Y-j)*abs(Y-j);
masim[c]=r*256;
c++;}*/
asm{
mov esi,X;
mov edi,Y;
mov ecx,0;
mov j,768;
@c2:cmp j,0;
jz @2;
mov i,0;
mov eax,edi;
sub eax,j;
imul eax;
mov Yj,eax;
@c1:cmp i,1024;
jz @3;
mov eax,esi;
sub eax,i;
imul eax;
add eax,Yj;
shl eax,8;
mov masim+ecx*4,eax;
inc ecx;
inc i;
jmp @c1;
@3:dec j;
jmp @c2;
@2:
};
SetDIBitsToDevice(D,DestX1,DestY1,Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
     TShiftState Shift, int X, int Y)
{
unsigned int x,y,i,j,c,r,c1,ht,ht1,Yj;
unsigned int v1000=6;
tagPOINT tp1;
ht=0;
asm
{
mov c1,0;
@c3:cmp c1,10000;
jz @1;
}
GetCursorPos(&tp1);
asm{
mov esi,dword ptr tp1;
mov edi,dword ptr tp1+4;
inc ht;
mov eax,ht;
mul eax;
imul v1000;
mov ht1,eax;
mov ecx,0;
mov j,768;
@c2:cmp j,0;
jz @2;
mov i,0;
mov eax,edi;
sub eax,j;
imul eax;
mov Yj,eax;
@c1:cmp i,1024;
jz @3;
mov eax,esi;
sub eax,i;
imul eax;
add eax,Yj;
sub eax,ht1;
shl eax,8;
mov masim+ecx*4,eax;
inc ecx;
inc i;
jmp @c1;
@3:dec j;
jmp @c2;
@2:inc c1;
};
SetDIBitsToDevice(D,DestX1,DestY1,Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
asm{
jmp @c3;
@1:
};
/*for (c1=0;c1<100;c1++){ht++;c=0;
for (j=768;j>0;j--)
for (i=0;i<1024;i++)
{r=abs(X-i)*abs(X-i)+abs(Y-j)*abs(Y-j)-ht*ht*1000;
masim[c]=r*256;
c++;}
SetDIBitsToDevice(D,DestX1,DestY1,Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
}*/
}

Вернуться в Вопросы программирования в C++Builder