Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Phili

unregistriert

1

16.03.2006, 07:51

Bmp aus Datei Laden, ohne D3DX zu benutzen

Ich hoehre immer wieder, man solle ohgne D3DX auskommen(leuchtet mir auch ein), das meiste hab ich auch schon entfernt, aber wie man eine Bmp-Datei laden kann, ohne D3DXCreateTextureFromFile() zu benutzen, hab ich noch nicht rausgefunden.

2

16.03.2006, 08:12

Im Internet gibt's ziemlich viele Beispiele zum Laden von Bitmaps. Im Grunde musst du nur nen BITMAPFILEHEADER und danach nen BITMAPINFOHEADER laden (siehe MSDN). Danach kommen die Pixeldaten. Wie genau man die Daten jetzt bei Direct3D in ne Textur lädt weiß ich nicht, aber Stichwort: D3DLOCKED_RECT.
Mein Projekt: Rise of the Sylvan

Anonymous

unregistriert

3

16.03.2006, 19:57

Grundlagen sind das, Zuerst eine Surface laden und von da aus direkt zur Textur. (Geht auch noch direkter, aber so lernt man es besser!)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// ###########################################################################

// Datei:        surface.cpp

// ###########################################################################

// Autor:        Patrick Ullmann

// Erstellt:     18.12.2005

// Änderungen:   18.12.2005/Patrick: Datei erstellt

// ###########################################################################

// Beschreibung: Diverse Surface Hilfsfunktionen /- Strukturen


// I N C L U D E S ###########################################################

#include "surface.h"

// F U N K T I O N E N #######################################################

namespace core
{
// ///////////////////////////////////////////////////////////////////////////

// PUBLIC

// 

// Funktion zum vertauschen von Daten

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

void flip (unsigned char* image, unsigned long bytesPerLine, unsigned long height)
{
        // Speicher bereit stellen

    unsigned char *line1 = new unsigned char [bytesPerLine];
    unsigned char *line2 = new unsigned char [bytesPerLine];    

        // Spiegeln

    for (unsigned long i=0; i<height/2; ++i)
    {
        memcpy (line1, &image [i * bytesPerLine], bytesPerLine);
        memcpy (line2, &image [(height - 1 - i) * bytesPerLine], bytesPerLine);

        memcpy (&image [i * bytesPerLine], line2, bytesPerLine);
        memcpy (&image [(height - 1 - i) * bytesPerLine], line1, bytesPerLine);
    }

        // Aufräumen nach der Party

    delete [] line1;
    delete [] line2;
}

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

// PUBLIC

// 

// Läd eine Bitmap in eine Direct3D Surface

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

::IDirect3DSurface9* loadSurfaceFromFile (const std::basic_string<wchar_t>& fileName, ::IDirect3DDevice9* device)
{
    DEBUG_STACK;

        // Es kann nur ein gültiges Device benutzt werden.

    if (!device) EXCEPTION (L"Invalid parameters");

        // Hilfsstrukturen /-Variabeln

    ::BITMAPFILEHEADER  FileHeader;     // BMP Datei Header

    ::BITMAPINFOHEADER  InfoHeader;     // BMP Datei Info Header

    unsigned long       mem;            // Zwischenspeicher

    unsigned long       pitch;          // lPitch der Surface >> 1

    void*               dest;           // Für die Pixeldaten

    ::D3DLOCKED_RECT    rectLock;       // Enthält Speicheradresse

    ::IDirect3DSurface9 *result = NULL; // Rückgabesurface


        // BMP Datei öffnen

    ::HANDLE file = ::CreateFile (fileName.c_str(),         // Datei Name

                                  GENERIC_READ,             // Nur lesen

                                  FILE_SHARE_READ,          // andere auch

                                  NULL,                     // keine Attrib.

                                  OPEN_EXISTING,            // exist. Datei

                                  FILE_ATTRIBUTE_NORMAL,    // norm.Attrib.

                                  NULL);                    // unbenutzt


        // Hat es geklappt?

    if (file == INVALID_HANDLE_VALUE) 
        EXCEPTION (L"Invalid file! (FILE_SHARE_READ)");

        // BMP Header einlesen

    if (!::ReadFile(file, &FileHeader, sizeof(FileHeader), &mem, NULL)) 
    {
        ::CloseHandle(file);
        EXCEPTION (L"Invalid file! (BMPFILEHEADER)");
    }

        // BMP Info-Header einlesen

    if (!::ReadFile(file, &InfoHeader, sizeof(InfoHeader), &mem, NULL)) 
    {
        ::CloseHandle(file);
        EXCEPTION (L"Invalid file! (BMPINFOHEADER)");
    }

        // Hat das Bitmap das gewünschte Format

    if (InfoHeader.biBitCount != 24) 
    {
        ::CloseHandle(file);
        EXCEPTION (L"Invalid file! (File must be 24bpp)");
    }

        // Initialisiere Surface Objekt im Bildschirmformat

    if (device->CreateOffscreenPlainSurface (InfoHeader.biWidth, InfoHeader.biHeight, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &result, NULL) != D3D_OK)
    {
        ::CloseHandle(file);
        EXCEPTION (L"Invalid file! (BMPFILEHEADER)");
    }

        // Speicher dynamisch bereitstellen

    unsigned char* data = new unsigned char [InfoHeader.biSizeImage];

        // Lies die eigentlichen Bilddaten des BMP

    if (!::ReadFile (file, data, InfoHeader.biSizeImage, &mem, NULL)) 
    {
        ::CloseHandle(file);
        EXCEPTION (L"Invalid file! (Reading imagedata)");
    }

        // Schliesse die Datei wieder

    ::CloseHandle(file);

        // Surface verriegeln

    if (result->LockRect (&rectLock, NULL, 0) != D3D_OK) 
        EXCEPTION (L"IDirect3DSurface9::LockRect");

    pitch   = rectLock.Pitch >> 2; // Byte/2 weil 32bpp = 4 Byte

    dest    = (unsigned long *)rectLock.pBits;

        // Spiegelung durchführen

    flip (data, InfoHeader.biSizeImage/InfoHeader.biHeight, InfoHeader.biHeight);

        // Wir müssen jeden Pixel umwandeln, also Pixel für Pixel

        // das Bild kopieren, und zwar von unten nach oben

    for (unsigned long cy=0; cy<static_cast<unsigned long>(InfoHeader.biHeight); ++cy) 
    {
        for (unsigned long cx=0; cx<static_cast<unsigned long>(InfoHeader.biWidth); ++cx) 
        {
                // Farbe mit Alpha = 100 % initialisieren

            unsigned long color = 0xff000000;

                // Kopiere 24 Bit Farbe in den 32 Bit Wert

            memcpy (&color, &data[(cy*InfoHeader.biWidth + cx)*3], sizeof(unsigned char)*3);

                // Pixel in 32 Bit Farbe schreiben

            ((unsigned long*)dest)[cx + (cy*pitch)] = color;
        }
    }

        // Entriegeln der Surface nach dem Schreiben der Daten

    result->UnlockRect();

        // Speicher freigeben

    if (data != NULL)
    {
        delete [] data;
        data = NULL;
    }

        // Surface zurückgeben

    return (result);
}
} // Namespace: core

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// ///////////////////////////////////////////////////////////////////////////

// PUBLIC 

//

// Läd eine 24Bit (!!!) Bitmap in den Texturmanager

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

void texture::loadTexture (const std::basic_string<wchar_t>& file)
{
    DEBUG_STACK;

        // Ist die zu ladene Textur schon enthalten?

    if (texture_.find(file) != texture_.end()) return;

        // Hilfsstrukturen

    ::IDirect3DTexture9*    texture         = NULL;
    ::IDirect3DSurface9*    surface         = loadSurfaceFromFile (file, direct3d::getInstance().direct3d_device_);
    ::D3DSURFACE_DESC       desc_surface;
    ::D3DLOCKED_RECT        locked_surface;
    ::D3DLOCKED_RECT        locked_texture;

        // Daten der Surface abfragen

    surface->GetDesc (&desc_surface);

        // Größe berechnen

    unsigned long size = desc_surface.Width*desc_surface.Height*2*2;
        // Speicher für Bilddaten bereitstellen

    unsigned char* data = new unsigned char [size*sizeof(unsigned char)];

        // Bilddaten aus der Surface kopieren

    surface->LockRect (&locked_surface, NULL, D3DLOCK_READONLY);
    memcpy (data, locked_surface.pBits, size * sizeof(unsigned char));
    surface->UnlockRect ();
       
        // Surface ggf. freigeben und NULLen

    if (surface != NULL)
    {
        surface->Release ();
        surface = NULL;
    }
    
        // Initialisiere das IDirect3DTexture9 Objekt

    if (direct3d::getInstance().direct3d_device_->CreateTexture 
       (desc_surface.Width, desc_surface.Height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL) != D3D_OK)
        EXCEPTION (L"IDirect3DDevice9::CreateTexture(); failed!");

        // Farbdaten von der Surface in die Textur kopieren

    texture->LockRect (0, &locked_texture, NULL, 0);
    memcpy (locked_texture.pBits, data, size * sizeof(unsigned char));
    texture->UnlockRect (0);

        // Datenarray freigeben

    delete [] data;

        // Alphakey setzen

    setAlphakey (&texture, 0xFFFF00FF, 0x00FFFFFF);

        // Textur und Dateiname in den Manager einfügen

    texture_.insert (std::make_pair(file, texture));
}
Und für Alphakey:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    // Einer Textur einen Alphakey geben

void setAlphakey (::IDirect3DTexture9** texture, unsigned long colorkey, unsigned long alpha)
{
        // Hilfsobjekte

    static ::D3DSURFACE_DESC    describe;
    static ::D3DLOCKED_RECT     rect;

        // Surfacebeschreibung holen

    (*texture)->GetLevelDesc (0, &describe);

        // Textur verriegeln

    (*texture)->LockRect (0, &rect, NULL, 0);

        // 32 Bit Pointer auf Bilddaten in der Textur

    for (unsigned long y=0; y<static_cast<unsigned long>(describe.Height); ++y) 
    {
        for (unsigned long x=0; x<static_cast<unsigned long>(describe.Width); ++x) 
        {
            if ((static_cast<unsigned long*>(rect.pBits))[describe.Width*y+x] == colorkey)
                (static_cast<unsigned long*>(rect.pBits))[describe.Width*y+x] = alpha;
        }
    }

        // Textur entriegeln

    (*texture)->UnlockRect (0);
}


Achtung: Alphakey läuft NUR mit Alphablending!

koschka

Community-Fossil

Beiträge: 2 862

Wohnort: Dresden

Beruf: Student

  • Private Nachricht senden

4

16.03.2006, 21:26

bzw. WinAPI. Siehe anderer Bitmap Thread (der aktuell ist)... da hab ich was reingeschrieben

Phili

unregistriert

5

11.07.2006, 15:30

@nix da
Dieser Thread ist ja schon recht alt, aber ich will ihn doch nochmal aufgreifen.
Ich find es zwr sehr nett, das du dir die Mühe gemacht hast :) , mir den gesamten Quellcode der nötig ist zu posten, aber ich will mal ganz erlich sein(din ich ja immer :lol: ): ich hab nicht wirklich viel von dem verstanden, was da in deinem Code steht :cry: . Vor allem auch, weil ich z.B. zum laden von FiIles immer fstream verwende und mir Funktionen wie memcpy zwar was sagen, die ich aber die angewendet habe.
Mit Techniken wie EXEPTIONS... geht es mir ähnlich.
Jetzt würd ich das ganze gern Schrittweise angehen, und erstmal die Textur mit fstream in ein Vektorarray(für jeden Pixel ein Vektor3 für die drei Farben). Aber auch dafür werd ich wohl hilfe benötigen... :(

koschka

Community-Fossil

Beiträge: 2 862

Wohnort: Dresden

Beruf: Student

  • Private Nachricht senden

6

11.07.2006, 17:31

ich glaube für dich wäre es besser wenn du dich erstmal an DDraw ranwagst. Dort ist es einfacher eine Bitmap in ein Surface zu laden (hier kann man es sich es auch einfacher machen z.B. mit LoadBitmap, aber der Autor wollte ja alles "hardcore" ^^). Ein tutorial gibts auf www.germangamedev.de (Funny Break oder so).

Die Exceptions sind "Fehlermeldungen" bzw. besser gesagt Ausnahmen. Nix da hat einen eigenen Exeption Handler mit Nummer der Zeile wo der Fehler aufgetreten ist, funktion u.s.w. Die funktion wird beendet, und/oder der Fehler ausgegeben

Phili

unregistriert

7

11.07.2006, 17:38

@koschka
Ich glaub du verstehst mich falsch, ich hab schon ne kleine aber voll funktionsfähige D3D-Engine geschrieben, die aber zum laden von Texturen(und auch NUR zum laden von Texturen) die D3DX-Funktionen benutzt. Und das soll sich jetzt ändern

Steven77

Alter Hase

Beiträge: 515

Wohnort: Münster - Gievenbeach

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

8

11.07.2006, 17:41

Phili, soll nix da dir jetzt 'ne adaptierte Version vorwerfen, oder was genau möchtest du?
Setz dich doch einfach selbst damit auseinander, bringt dir persönlich doch wesentlich mehr, zumal ich nix da's oberen Code ziemlich intuitiv finde.
Wenn du keine Exceptions und auch nicht Funktionen wie memcpy kennst, besteht dort absoluter Nachholbedarf, bevor du etwas mit komplexeren "Sachen" wie Direct3D entwickelst.

Phili

unregistriert

9

11.07.2006, 18:34

@Steven77

Wie gesagt beschäftige ich mich bereits seit längerem durchaus erfolgreich mit D3D, ohne Exeptions zu nutzen. Wie aus dem kontext sicher ersichtlich wird ist auch mein einziges Problem, das ich mich nie verstärkt mit filestream auseinandergesetzt hab und deswegen Probleme damit hab, nen bmp-File Byteweise einzulesen.
ALso: Wie liest man einzelne bytes mit fstream ein.

CW_Kovok

Alter Hase

Beiträge: 836

Wohnort: nähe Bonn

Beruf: Schüler

  • Private Nachricht senden

10

11.07.2006, 18:38

du kannst es auch häppchenweise machen. Öffne erstmal eine bitmap und versuch dir den inhalt anzugucken. Dann guck dir die Methode IDirect3DDevice9::CreateTexture und dann guck mal was du brauchst und wo du es herbekommst
Was es alles gibt, das ich nich brauche - Aristoteles

Werbeanzeige