TRANSFER BITMAP (VDI 170, 0)
Dekl.: void vr_transfer_bits( int16 handle, GCBITMAP *src_bm, GCBITMAP *dst_bm, RECT16 *src_rect, RECT16 *dst_rect, int16 mode );
Die Funktion TRANSFER BITMAP verknüpft die Quellbitmap <src_bm> mit der Zielbitmap <dst_bm>, wobei <mode> die Transferfunktion angibt. Das Quellrechteck wird in <src_rect> und das Zielrechteck in <dst_rect> übergeben. Die Koordinaten werden dabei (wie bei allen anderen VDI- Funktionen) als diskrete Werte angegeben.
Wenn das Quell- und das Zielrechteck nicht die gleichen Ausmaße haben, skaliert TRANSFER BITMAP die Quellbitmap. Bei Verkleinerungen werden die Bitmapdaten interpoliert, wenn die Quelle direkte Farbwerte enthält (16 oder 32 Bit) oder wenn die Ausgabe mit Dithern erfolgt.
Falls die Quell- und die Zielbitmap nicht das gleiche Pixelformat oder die gleiche Farbtiefe haben, werden die Quelldaten automatisch in das Zielformat umgesetzt (die Quellbitmap bleibt dabei natürlich unverändert).
Wenn <src_bm> oder <dst_bm> 0 ist, wird als Quelle bzw. Ziel der Operation die Bitmap der Workstation <handle> benutzt. Bei Ausgaben auf dem Bildschirm sollte ein Programm auf jeden Fall 0 für <dst_bm> übergeben und nicht versuchen, eine eigene Bitmapbeschreibung aufzubauen. Clipping erfolgt nur für die Zielbitmap (und das nur, wenn die Zielbitmap die Bitmap der Workstation ist).
Transfermodi
In der folgenden Liste sind die Konstanten für die in <mode> übergebenen Transfermodi definiert. In den Kommentaren ist dabei die Art der Operation in symbolischer Schreibweise aufgeführt (<src> ist das Quellpixel, <dst> ist das Zielpixel, <bg_col> ist der Pixelwert der Hintergrundfarbe, <hilite_col> ist der Pixelwert der Farbe für Hervorhebungen):
/* logische Transfermodi */ #define T_LOGIC_COPY 0 /* dst = src; */ #define T_LOGIC_OR 1 /* dst = src OR dst; */ #define T_LOGIC_XOR 2 /* dst = src XOR dst; */ #define T_LOGIC_AND 3 /* dst = src AND dst; */ #define T_LOGIC_NOT_COPY 4 /* dst = ( NOT src ); */ #define T_LOGIC_NOT_OR 5 /* dst = ( NOT src ) OR dst; */ #define T_LOGIC_NOT_XOR 6 /* dst = ( NOT src ) XOR dst; */ #define T_LOGIC_NOT_AND 7 /* dst = ( NOT src ) AND dst; */ /* Zeichenmodi */ #define T_REPLACE 32 /* dst = src; */ #define T_TRANSPARENT 33 /* if ( src != bg_col ) dst = src; */ #define T_HILITE 34 /* if ( src != bg_col ) */ /* { */ /* if ( dst == bg_col ) */ /* dst = hilite_col; */ /* else if ( dst == hilite_col ) */ /* dst = bg_col; */ /* } */ #define T_REVERS_TRANSPARENT 35 /* if ( src == bg_col ) dst = src; */
Hinweis: Bei den arithmetischen Transfermodi werden Quelle und Ziel nicht anhand ihres Pixelwerts verknüpft, sondern ihre (RGB-) Farbwerte werden je nach Verknüpfung addiert oder subtrahiert, ...
In der symbolischen Beschreibung ist RGB( x ) der RGB-Farbwert eines Pixels und PIXELWERT( rgb ) ist der Pixelwert eines RGB-Farbwerts. MAX( rgb_a, rgb_b ) liefert die maximalen Komponenten zweier RGB- Farbwerte; MIN( rgb_a, rgb_b ) liefert dementsprechend die minimalen Komponenten zurück. <max_rgb> ist ein maximaler RGB-Farbwert, <min_rgb> ist ein minimaler RGB-Farbwert. <Gewichtung> ist ein Wert zwischen 0 und 1.0, der die Mischung von Quell- und Zielfarbe angibt.
/* arithmetische Transfermodi */ #define T_BLEND 64 /* Quell- und Zielfarbe mischen */ /* rgb = RGB( src ) * Gewichtung ); */ /* rgb += RGB( dst ) * (1-Gewichtung));*/ /* dst = PIXELWERT( rgb ); */ #define T_ADD 65 /* Quell- und Zielfarbe addieren */ /* rgb = RGB( src ) + RGB( dst ) */ /* if ( rgb > max_rgb ) */ /* rgb = max_rgb; */ /* dst = PIXELWERT( rgb ); */ #define T_ADD_OVER 66 /* Quell- und Zielfarbe addieren, */ /* Überlauf nicht abfangen */ /* rgb = RGB( src ) + RGB( dst ) */ /* dst = PIXELWERT( rgb ); */ #define T_SUB 67 /* Quell- von Zielfarbe subtrahieren */ /* rgb = RGB( dst ) - RGB( src ) */ /* if ( rgb < min_rgb ) */ /* rgb = min_rgb; */ /* dst = PIXELWERT( rgb ); */ #define T_MAX 69 /* maximale RGB-Komponenten */ /* rgb = MAX(RGB( dst ), RGB( src ))*/ /* dst = PIXELWERT( rgb ); */ #define T_SUB_OVER 70 /* Quell- von Zielfarbe subtrahieren, */ /* Überlauf nicht abfangen */ /* rgb = RGB( dst ) - RGB( src ) */ /* dst = PIXELWERT( rgb ); */ #define T_MIN 71 /* minimale RGB-Komponenten */ /* rgb = MIN(RGB( dst ), RGB( src ))*/ /* dst = PIXELWERT( rgb ); */
Für alle Transfermodi kann man außerdem durch Addition einer der beiden folgenden Konstanten die Art der Verknüpfung beeinflussen.
#define T_COLORIZE 16 /* Quelle einfärben */ #define T_DITHER_MODE 128 /* Quelldaten dithern */
Dithern
<T_DITHER_MODE> führt dazu, daß eine Fehlerverteilungsfunktion benutzt wird, wenn die Zielbitmap 256 oder weniger Farben hat (außerdem wird bei Verkleinerungen in diesem Fall interpoliert, damit die Details in der Verkleinerung nicht vollkommen verloren gehen).
Falls die Quell- und Zielpalette gleich sind (oder die Quellpalette eine Untermenge der Systemfarbpalette ist), verwendet NVDI intern (automatisch) eine schnellere Transferfunktion ohne Dither.
Einfärbung
T_LOGIC_COPY Blende bei allen gesetzen Bits im Farbwert die Hintergrundfarbe ein und bei allen gelöschten Bits die Vordergrundfarbe: rgb = (( NOT RGB( src )) & RGB( fg_col )) OR ( RGB( src ) AND RGB( bg_col )); dst = PIXELWERT( rgb ); T_LOGIC_NOT_COPY Blende bei allen gesetzen Bits im Farbwert die Vordergrundfarbe ein und bei allen gelöschten Bits die Hintergrundfarbe: rgb = ( RGB( src ) & RGB( fg_col )) OR ((( NOT RGB( src )) AND RGB( bg_col )); dst = PIXELWERT( rgb ); T_LOGIC_OR Überall dort, wo Quellbits gesetzt sind, wird beim Ziel ( src AND fg_col) eingeblendet: dst = ( src AND fg_col ) OR (( NOT src ) AND dst ); T_LOGIC_NOT_OR Überall dort, wo Quellbits gelöscht sind, wird beim Ziel ((NOT src ) AND fg_col) eingeblendet: dst = (( NOT src ) AND fg_col ) OR ( src AND dst ); T_LOGIC_XOR T_LOGIC_NOT_XOR Die XOR-Verknüpfung ignoriert die Einfärbung. T_LOGIC_AND Überall dort, wo Quellbits gelöscht sind, wird beim Ziel ((NOT src ) AND bg_col) eingeblendet: dst = ((NOT src ) AND bg_col ) OR ( src AND dst ); T_LOGIC_NOT_AND Überall dort, wo Quellbits gesetzt sind, wird beim Ziel ( src AND bg_col) eingeblendet: dst = ( src AND bg_col ) OR ((NOT src ) AND dst );
red_range = bg_col.red - fg_col.red; green_range = bg_col.green - fg_col.green; blue_range = bg_col.blue - fg_col.blue; dst.red = fg_col.red + ( src_color.red * red_range / 65535 ); dst.green = fg_col.green + ( src_color.green * green_range / 65535 ); dst.blue = fg_col.blue + ( src_color.blue * blue_range / 65535 );
Bitmaps
Statt eines antiquierten MFDBs erwartet diese Funktion eine GCBITMAP- Struktur, um die Bitmaps zu beschreiben:
typedef struct _gcbitmap /* öffentliche Bitmapbeschreibung (Struktur mit Versionsheader) */ { int32 magic; /* Strukturkennung 'cbtm' */ int32 length; /* Strukturlänge */ int32 format; /* Strukturformat (0) */ int32 reserved; /* reserviert (0) */ uint8 *addr; /* Adresse der Bitmap */ int32 width; /* Breite einer Zeile in Bytes */ int32 bits; /* Bittiefe */ uint32 px_format; /* Pixelformat */ int32 xmin; /* minimale diskrete x-Koordinate der Bitmap */ int32 ymin; /* minimale diskrete y-Koordinate der Bitmap */ int32 xmax; /* maximale diskrete x-Koordinate der Bitmap + 1 */ int32 ymax; /* maximale diskrete y-Koordinate der Bitmap + 1 */ CTAB_REF ctab; /* Verweis auf die Farbtabelle oder 0L */ ITAB_REF itab; /* Verweis auf die inverse Farbtabelle oder 0L */ int32 reserved0; /* reserviert (muß auf 0 gesetzt werden) */ int32 reserved1; /* reserviert (muß auf 0 gesetzt werden) */ } GCBITMAP;
Die Strukturelemente haben im einzelnen folgende Bedeutung:
magic | Strukturkennung |
length | Strukturlänge (für Format 0 immer 64) |
format | Strukturformat, in diesem Fall 0 (für spätere Erweiterungen) |
reserved | reserviert, auf 0 setzen |
addr | Zeiger auf die Bitmapdaten |
width | Breite einer Zeile in Bytes (sollte aus Performace-Gesichtspunkten ein Vielfaches von 16 Bytes sein) |
bits | Bits pro Pixel |
px_format | Beschreibung des Pixelformat (siehe unten) |
xmin | x-Koordinate der linken oberen Ecke der Bitmap (in der Regel 0) |
ymin | y-Koordinate der linken oberen Ecke der Bitmap (in der Regel 0) |
xmax | max. x-Koordinate der rechten unteren Ecke der Bitmap + 1 (in der Regel "Breite in Pixeln") |
ymax | max. y-Koordinate der rechten unteren Ecke der Bitmap + 1 (in der Regel "Höhe in Pixeln") |
ctab | bei Strukturformat 0 ein Zeiger auf die Farbtabelle |
itab | Verweis auf die inverse Farbtabelle (muß nur bei Zielbitmaps gesetzt werden, sonst 0) |
reserved0 | reserviert, muß auf 0 gesetzt werden |
reserved1 | reserviert, muß auf 0 gesetzt werden |
Wenn <ctab> 0L ist, wird die der Bittiefe entsprechende Systemfarbtabelle für den Aufruf benutzt (wenn die Bitmap mehr als 8 Bit pro Pixel hat, d.h. direkte Farbwerte benutzt, kann <ctab> ebenfalls auf 0L gesetzt werden).
Quellbitmaps benötigen keine inverse Farbtabelle, hier kann <itab> auf 0L gesetzt werden. Bei einer selbst verwalteten Zielbitmap muß man vom VDI eine Referenz auf eine inverse Farbtabelle anfordern (und irgendwann später auch wieder freigeben).
Vereinfachte Sonderfälle
Damit Bitmaps im Format des Bildschirms auch ohne Anforderung einer Farbtabelle und einer Referenz auf eine inverse Farbtabelle ähnlich unkompliziert wie bei vro_cpyfm() kopiert werden können, gibt es einige vereinfachte Sonderfälle bei vr_transfer_bits():
Hinweis: Es empfiehlt sich, für Bitmaps außerhalb des Bildschirms mit v_open_bm() oder v_opnbm() eine Bitmap vom VDI erzeugen zu lassen, da man sich in diesem Fall nicht um die Verwaltung von Farbtabellen und inversen Farbtabellen kümmern muß.
Pixelformate
Um Bitmaps zwischen verschiedenen Bittiefen und Pixelformaten wandeln zu können, benötigt TRANSFER BITMAP eine Beschreibung des Pixelformats, die im Strukturelement <px_format> enthalten ist. Der Aufbau dieses Bitvektors wird in der folgenden Liste beschrieben; für Programmierer dürften aber vor allem die vordefinierten Formate interessant sein:
/* Konstanten für Pixelformate */ #define PX_1COMP 0x01000000L /* Pixel besteht aus einer benutzten Komponente: Farbindex */ #define PX_3COMP 0x03000000L /* Pixel besteht aus drei benutzten Komponenten, z.B. RGB */ #define PX_4COMP 0x04000000L /* Pixel besteht aus vier benutzten Komponenten, z.B. CMYK */ #define PX_REVERSED 0x00800000L /* Pixel wird in umgekehrter Bytereihenfolge ausgegeben */ #define PX_xFIRST 0x00400000L /* unbenutzte Bits liegen vor den benutzen (im Motorola-Format betrachtet) */ #define PX_kFIRST 0x00200000L /* K liegt vor CMY (im Motorola-Format betrachtet) */ #define PX_aFIRST 0x00100000L /* Alphakanal liegen vor den Farbbits (im Motorola-Format betrachtet) */ #define PX_PACKED 0x00020000L /* Bits sind aufeinanderfolgend abgelegt */ #define PX_PLANES 0x00010000L /* Bits sind auf mehrere Ebenen verteilt (Reihenfolge: 0, 1, ..., n) */ #define PX_IPLANES 0x00000000L /* Bits sind auf mehrere Worte verteilt (Reihenfolge: 0, 1, ..., n) */ #define PX_USES1 0x00000100L /* 1 Bit des Pixels wird benutzt */ #define PX_USES2 0x00000200L /* 2 Bit des Pixels werden benutzt */ #define PX_USES3 0x00000300L /* 3 Bit des Pixels werden benutzt */ #define PX_USES4 0x00000400L /* 4 Bit des Pixels werden benutzt */ #define PX_USES8 0x00000800L /* 8 Bit des Pixels werden benutzt */ #define PX_USES15 0x00000f00L /* 15 Bit des Pixels werden benutzt */ #define PX_USES16 0x00001000L /* 16 Bit des Pixels werden benutzt */ #define PX_USES24 0x00001800L /* 24 Bit des Pixels werden benutzt */ #define PX_USES32 0x00002000L /* 32 Bit des Pixels werden benutzt */ #define PX_USES48 0x00003000L /* 48 Bit des Pixels werden benutzt */ #define PX_1BIT 0x00000001L /* Pixel besteht aus 1 Bit */ #define PX_2BIT 0x00000002L /* Pixel besteht aus 2 Bit */ #define PX_3BIT 0x00000003L /* Pixel besteht aus 3 Bit */ #define PX_4BIT 0x00000004L /* Pixel besteht aus 4 Bit */ #define PX_8BIT 0x00000008L /* Pixel besteht aus 8 Bit */ #define PX_16BIT 0x00000010L /* Pixel besteht aus 16 Bit */ #define PX_24BIT 0x00000018L /* Pixel besteht aus 24 Bit */ #define PX_32BIT 0x00000020L /* Pixel besteht aus 32 Bit */ #define PX_48BIT 0x00000030L /* Pixel besteht aus 48 Bit */ #define PX_CMPNTS 0x0f000000L /* Maske für Anzahl der Pixelkomponenten */ #define PX_FLAGS 0x00f00000L /* Maske für diverse Flags */ #define PX_PACKING 0x00030000L /* Maske für Pixelformat */ #define PX_USED 0x00003f00L /* Maske für Anzahl der benutzten Bits */ #define PX_BITS 0x0000003fL /* Maske für Anzahl der Bits pro Pixel */ /* Pixelformate für ATARI-Grafik */ #define PX_ATARI1 ( PX_PACKED + PX_1COMP + PX_USES1 + PX_1BIT ) #define PX_ATARI2 ( PX_IPLANES + PX_1COMP + PX_USES2 + PX_2BIT ) #define PX_ATARI4 ( PX_IPLANES + PX_1COMP + PX_USES4 + PX_4BIT ) #define PX_ATARI8 ( PX_IPLANES + PX_1COMP + PX_USES8 + PX_8BIT ) #define PX_FALCON15 ( PX_PACKED + PX_3COMP + PX_USES16 + PX_16BIT ) /* Pixelformate für Mac */ #define PX_MAC1 ( PX_PACKED + PX_1COMP + PX_USES1 + PX_1BIT ) #define PX_MAC4 ( PX_PACKED + PX_1COMP + PX_USES4 + PX_4BIT ) #define PX_MAC8 ( PX_PACKED + PX_1COMP + PX_USES8 + PX_8BIT ) #define PX_MAC15 ( PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES15 + PX_16BIT ) #define PX_MAC32 ( PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES24 + PX_32BIT ) /* Pixelformate für Grafikkarten */ #define PX_VGA1 ( PX_PACKED + PX_1COMP + PX_USES1 + PX_1BIT ) #define PX_VGA4 ( PX_PLANES + PX_1COMP + PX_USES4 + PX_4BIT ) #define PX_VGA8 ( PX_PACKED + PX_1COMP + PX_USES8 + PX_8BIT ) #define PX_VGA15 ( PX_REVERSED + PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES15 + PX_16BIT ) #define PX_VGA16 ( PX_REVERSED + PX_PACKED + PX_3COMP + PX_USES16 + PX_16BIT ) #define PX_VGA24 ( PX_REVERSED + PX_PACKED + PX_3COMP + PX_USES24 + PX_24BIT ) #define PX_VGA32 ( PX_REVERSED + PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES24 + PX_32BIT ) #define PX_MATRIX16 ( PX_PACKED + PX_3COMP + PX_USES16 + PX_16BIT ) #define PX_NOVA32 ( PX_PACKED + PX_3COMP + PX_USES24 + PX_32BIT ) /* Pixelformate für Drucker */ #define PX_PRN1 ( PX_PACKED + PX_1COMP + PX_USES1 + PX_1BIT ) #define PX_PRN8 ( PX_PACKED + PX_1COMP + PX_USES8 + PX_8BIT ) #define PX_PRN32 ( PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES24 + PX_32BIT ) /* bevorzugte (schnelle) Pixelformate für Bitmaps */ #define PX_PREF1 ( PX_PACKED + PX_1COMP + PX_USES1 + PX_1BIT ) #define PX_PREF2 ( PX_PACKED + PX_1COMP + PX_USES2 + PX_2BIT ) #define PX_PREF4 ( PX_PACKED + PX_1COMP + PX_USES4 + PX_4BIT ) #define PX_PREF8 ( PX_PACKED + PX_1COMP + PX_USES8 + PX_8BIT ) #define PX_PREF15 ( PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES15 + PX_16BIT ) #define PX_PREF32 ( PX_xFIRST + PX_PACKED + PX_3COMP + PX_USES24 + PX_32BIT )
Für Programme, die selber Bitmaps erzeugen (oder laden) und anschließend auf dem Bildschirm ausgeben wollen, sind besonders die zuletzte angegeben Formate PX_PREFx zu empfehlen, da sie bei einem anderen Pixelformat des Bidlschirms mit geringerem Aufwand als einige andere Formate gewandelt werden können.
Hinweis: Wenn der Treiber die neuen Rasterfunktionen, anbietet, ist bei den erweiterten Parametern von vq_extnd() in work_out[30] Bit 1 gesetzt.
Binding/Parameterübergabe
Dekl.: void vr_transfer_bits( int16 handle, GCBITMAP *src_bm, GCBITMAP *dst_bm, RECT16 *src_rect, RECT16 *dst_rect, int16 mode ); Aufruf: vr_transfer_bits( handle, image, 0L, src_rect, dst_rect, T_REPLACE | T_DITHER ); Variable Belegung Bedeutung Eingaben: contrl[0] 170 contrl[1] 4 Einträge in ptsin contrl[3] 4 Einträge in intin contrl[5] 0 Unterfunktionsnummer contrl[6] handle contrl[7-8] src_bm contrl[9-10] dst_bm contrl[11-12] 0 reserviert (auf 0 setzen) intin[0] mode Transfermodus intin[1-3] 0 reserviert (auf 0 setzen) ptsin[0-3] src_rect Quellrechteck ptsin[4-7] dst_rect Zielrechteck Ausgaben: contrl[2] 0 Einträge in ptsout contrl[4] 0 Einträge in intout