гос / sp-lect (1)
.pdf
Команда PMADDWD mm,mm / m64 спочатку попарно множить слова операндів, потім попарно додає отримані при множенні суміжні подвійні слова і розміщує результат на місце лівого операнду.
Рисунок 9.10
Команд пересилання, перетворення типів та арифметичних команд вже
виявляється достатньо для реалізації деяких алгоритмів, що і демонструє наступний приклад.
Приклад 9.1 Програма лінійного контрастування зображення 24-бітового bmp-файлу.
При лінійному контрастуванні використовується лінійне по елементне перетворення виду y=ax+b, параметри a і b якого визначаються бажаними значеннями мінімальної ymin і максимальної ymax вихідної яскравості.
Очевидно, що при лінійному перетворенні мінімальному xmin і максимальному xmax значенню вхідного сигналу відповідатиме мінімальне ymin і максимальне ymax значення вихідного.
При заміні ymin і ymax бажаними фіксованими значеннями мінімальної і максимальної вихідної яскравості і за умови, що xmin і xmax це фіксовані характеристики вхідного сигналу, отримуємо систему двох лінійних рівнянь з двома невідомими a і b.
ymin = a × xmin + b
= × +
ymax a xmax b
Розв'язавши відносно a і b систему і підставивши в y=ax+b отримаємо
формулу лінійного контрастування y = ymax − ymin ×( x - x ) + y .
xmax - xmin min min
Файли бітових образів починаються зі структури
BITMAPFILEHEADER STRUCT |
|
|
bfType |
WORD ? ; сигнатура «BM» (42h 4Dh) |
|
bfSize |
DWORD ? ; розмір файлу |
|
bfReserved1 |
WORD ? |
; не використовується |
bfReserved2 |
WORD ? |
; не використовується |
bfOffBits |
DWORD ? ; зсув даних бітового образа від заголовка |
|
BITMAPFILEHEADER ENDS |
|
|
Безпосередньо за нею розташовується структура BITMAPINFO, що |
||
містить усю інформацію про бітовий образ. |
||
BITMAPINFO STRUCT |
|
|
bmiHeader |
BITMAPINFOHEADER <?>; |
|
bmiColors |
RGBQUAD 1 dup (<>); |
|
BITMAPINFO ENDS
Структура BITMAPINFO ділиться на дві частини: масив структур RGBQUAD, що містить дані бітового образа і структуру BITMAPINFOHEADER, що описує характеристики бітового образа.
RGBQUAD STRUCT
rgbBlue |
BYTE ? ; червона складова |
rgbGreen |
BYTE ? ; зелена складова |
rgbRed |
BYTE ? ; синя складова |
rgbReserved |
BYTE ? ; альфа-канал |
RGBQUAD ENDS
В загальному випадку структура BITMAPINFOHEADER залежить від версії, однак перші її елементи фіксовані (вибірково)
BITMAPINFOHEADER STRUCT
biSize |
DWORD ? ; розмір цієї структури |
biWidth |
LONG ? ; ширина |
biHeight |
LONG ? ; і висота рисунку у пікселях |
………………………………… |
|
biBitCount |
WORD ? ; кількість бітів на піксель |
…………………………………
BITMAPINFOHEADER ENDS
; Файл contrast.inc
include windows.inc include user32.inc include kernel32.inc include masm32.inc
include C:\MASM32\MACROS\strings.mac includelib user32.lib
includelib kernel32.lib includelib masm32.lib Main PROTO
pdivuslb macro RegMMX1,RegMMX2,RegMMX3 pusha
movd eax,RegMMX1 movd ebx,RegMMX2 mov ecx,4
@@: push eax push ebx and eax,0FFh and ebx,0FFh div bl
shrd edx,eax,8 pop ebx
pop eax shr eax,8 shr ebx,8 loop @B
movd RegMMX3,edx popa
endm |
|
.const |
|
Ymin |
DWORD 0 |
Ymax |
DWORD 00FFFFFFh |
.data? |
|
hFile1 |
HANDLE ? |
hFile2 |
HANDLE ? |
FileSizeHigh |
DWORD ? |
FileSizeLow |
DWORD ? |
hMemFile1 |
HANDLE ? |
hMemFile2 |
HANDLE ? |
hMem1 |
HANDLE ? |
hMem2 |
HANDLE ? |
; Файл contrast.asm
.386
.model flat, stdcall
.MMX
.XMM ; SSE для pminub/pmaxub (>= Pentium III) include contrast.inc
.code
start:
invoke Main
invoke ExitProcess,0 Main proc
LOCAL InputBuffer[2*MAX_PATH]:BYTE
LOCAL OutputBuffer[128]:BYTE
;Контрастування на бажані значення
;мінімальної Ymin и максимальної Ymax яскравості
;Y = (X - Xmin)*(Ymax - Ymin)/(Xmax - Xmin) + Ymin
lea esi,InputBuffer
lea edi,OutputBuffer
invoke AllocConsole
invoke CharToOem,$CTA0("Лінійне контрастування зображень"), edi invoke SetConsoleTitle,edi
invoke ClearScreen invoke getcl_ex, 1, esi
.if eax==2
invoke CharToOem,\
$CTA0("Потрібно зазначити файл зображення"),edi invoke StdOut,edi
ret
.endif
invoke CreateFile,esi, GENERIC_READ OR GENERIC_WRITE,\ NULL,NULL,OPEN_EXISTING, NULL,NULL
.if eax== INVALID_HANDLE_VALUE
invoke CharToOem, $CTA0("Не можу відкрити файл "), edi invoke StdOut,edi
invoke StdOut,esi ret
.endif
mov hFile1, eax
invoke GetFileSize, eax, ADDR FileSizeHigh
mov FileSizeLow, eax ; bfSize в BITMAPFILEHEADER типу DWORD invoke CreateFileMapping, hFile1, NULL, \
PAGE_READWRITE, NULL, FileSizeLow, NULL mov hMemFile1, eax
invoke MapViewOfFile, eax, FILE_MAP_READ, NULL, NULL, NULL mov hMem1,eax
mov esi,eax
lea ebx,[esi+SIZEOF BITMAPFILEHEADER] assume ebx:PTR BITMAPINFO
.if [ebx].bmiHeader.biBitCount!=24 invoke CharToOem,\
$CTA0("Цей формат BMP-файлу не пiдтримується "),edi
invoke StdOut,edi ret
.endif
invoke CreateFile, $CTA0("output.bmp"),\ GENERIC_READ or GENERIC_WRITE, NULL, NULL,\ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
mov hFile2, eax
invoke CreateFileMapping, eax, NULL,\ PAGE_READWRITE, NULL, FileSizeLow, NULL
mov hMemFile2, eax
invoke MapViewOfFile, eax, FILE_MAP_WRITE, NULL, NULL, FileSizeLow mov hMem2,eax
mov edi,eax
; копіюємо заголовок в новий файл - він буде той самий
mov ecx,SIZEOF BITMAPFILEHEADER
add ecx,[ebx].bmiHeader.biSize
rep movsb |
|
|
|
push esi |
; потім знадобиться |
||
; визначимо кількість пікселів для обробки як Width х Height |
|||
mov eax,[ebx].bmiHeader.biWidth |
|
||
mul [ebx].bmiHeader.biHeight |
; DWORD * DWORD |
||
assume ebx:nothing |
|
|
|
mov ecx,eax |
; bfSize в BITMAPFILEHEADER типу DWORD |
||
dec ecx |
|
; і EDX не враховуємо |
|
push ecx |
|
|
; потім нагодиться |
movd |
mm0,dword ptr [esi] |
; початкове |
|
movq |
mm1,mm0 |
|
; значення min и max |
@@: add esi,3 |
|
|
; беремо RGB |
movd |
mm2,dword ptr [esi] |
; наступного пікселя |
|
pminub |
mm0,mm2 |
|
; і шукаємо |
pmaxub |
mm1,mm2 |
|
; min і max |
loop @B |
|
|
|
psubusb |
mm1,mm0 |
; Xmax - Xmin в mm1, Xmin в mm0, Ymin=0 |
movd |
mm2,Ymax |
; Ymax - Ymin в mm2 |
;В розширенні MMX немає команди ділення.
;"ММХ-ділення" реалізуємо власним макро pdivuslb
;на базі основної системи команд
;Вираз (Ymax - Ymin)/(Xmax - Xmin) складається з
;фіксованих значень і обчислюється тільки один раз
pdivuslb mm2,mm1,mm3 ;mm3 = (Ymax - Ymin)/(Xmax - Xmin)
pop ecx |
; кількість пікселів для обробки |
|
pop esi |
; в esi адреса початку даних, а edi залишилось від rep movsb |
|
psubd |
mm2,mm2 |
; mm2=0 для распакування |
punpcklbw mm3,mm2 |
; распакували для pmullw |
|
@@: movd |
mm4,dword ptr [esi] |
|
psubusb |
mm4,mm0 ; mm4=(X - Xmin) |
|
punpcklbw mm4,mm2 ; распакували для pmullw
pmullw mm4,mm3 ; mm4=(X - Xmin)*(Ymax - Ymin)/(Xmax - Xmin)
packuswb |
mm4,mm2 ; запакували mm4 для пересилання |
movd |
dword ptr [edi],mm4 |
add esi,3 |
|
add edi,3 |
|
loop @B |
|
invoke UnmapViewOfFile, hMem1 invoke UnmapViewOfFile, hMem2 invoke CloseHandle, hMemFile1 invoke CloseHandle, hMemFile2 invoke CloseHandle, hFile1 invoke CloseHandle, hFile2
ret
Main endp end start
Результати роботи програми цього прикладу демонструють наступні
рисунки: |
|
Вхідне зображення |
Вихідне зображення |
Вхідне зображення |
Вихідне зображення |
9.4.4 Логічні команди
Характерною рисою логічних команд є те, що вони можуть вважатися векторним, однак по суті їх виконання зводиться до побітових логічних операцій над усіма бітами операндів, так само як і для логічних команд загального призначення:
PAND mm,mm / m64 – побітова кон’юнкція;
PANDN mm,mm / m64 – заперечення побітової кон’юнкції;
POR mm,mm / m64 – побітова диз’юнкція;
PXOR mm,mm / m64 – побітова сума за модулем два.
Серед логічних MMX-команд нема інверсії, однак її можна виконати скориставшись тим що x × x = x , тобто звести до виконання команди PANDN.
9.4.5 Команди зрушення
Серед команд зрушення виділяють команди логічних і арифметичних зрушень. Команди з узагальненим позначенням
L |
W |
|
|
|
|
< приймач >,< джерело > |
|
PS L D |
|||
R |
|
|
|
|
Q |
|
|
виконують логічне зрушення вправо або вліво (L|R) усіх слів|подвійних слів|зчетверених слів (W|D|Q) приймача на однакову кількість бітів, що визначається значенням джерела. Розряди що звільняються при логічному зрушенні заповнюються нулями.
Приймач може бути тільки MMX-регістром, а джерело – MMX- регістром або 64-розрядним операндом в пам’яті. Для усіх команд окрім PSLLW джерело також може задаватися безпосереднім 8-бітним значенням, яке визначає однакову кількість бітів для зрушення усіх елементів приймача.
W
Команди з узагальненим позначенням PSRA виконують
D
арифметичне зрушення вправо усіх слів|подвійних слів (W|D) приймача на однакову кількість бітів, що визначається значенням джерела. Розряди що звільняються при логічному зрушенні заповнюються значенням старшого біту відповідного елементу.
Приймач може бути тільки MMX-регістром, а джерело – MMX- регістром, 64-розрядним операндом в пам’яті або задаватися безпосереднім 8-бітним значенням.
9.4.6 Команди порівняння
Команди з узагальненим позначенням
B |
|
|
|
|
EQ |
|
< приймач >,< джерело > |
виконують |
попарне |
PCMP W |
||||
GT |
|
|
|
|
D |
|
|
|
|
порівняння відповідних байтів|слів|подвійних слів Якщо відповідний елемент приймача і джерела елемент приймача більший ніж елемент джерела заповнюється одиницями, інакше нулями.
(B|W|D) приймача і джерела. рівні (EQ) або відповідний (GT), то елемент приймача
