Umfrage zur maximalen Imagegröße
- computerkranker
- Beiträge: 66
- Registriert: 12.10.2004 21:21
CreateCompatibleBitmap_() erzeugt keine Image mehr in diesen test. Das wird sicher auch das Problem sein. Es muss aber eine lösung geben, da in win98 nur 13MB benutzt werden können.
Vielleicht hat ja einer ne Idee...
Vielleicht hat ja einer ne Idee...
Code: Alles auswählen
Structure PB_StructureImage
Bitmap.l
Width.w
Height.w
Depth.w
ColorArray.l
EndStructure
Procedure IMAGE_GetOrAllocImageSpace(Number)
!EXTRN _PB_Image_GetOrAllocateID
!MOV EAX,[Esp]
!CALL _PB_Image_GetOrAllocateID
ProcedureReturn
EndProcedure
Procedure CreateImage_Test(Number,Width,Height)
hdc=CreateDC_("DISPLAY",#Null,#Null,#Null)
If GetObjectType_(hdc)=0::Debug "hdc no Object":ProcedureReturn 0:EndIf
hBitmap=CreateCompatibleBitmap_(hdc,Width,Height)
DeleteDC_(hdc)
If GetObjectType_(hBitmap)=0:Debug "hBitmap no Object":ProcedureReturn 0:EndIf
*ImgPtr.PB_StructureImage=IMAGE_GetOrAllocImageSpace(Number)
If *ImgPtr=0:Debug "*ImgPtr=0":ProcedureReturn 0:EndIf
If GetObjectType_(*ImgPtr\Bitmap):DeleteObject_(*ImgPtr\Bitmap):EndIf
GetObject_(hBitmap,SizeOf(BITMAP),BmpInf.BITMAP)
*ImgPtr\Bitmap=hBitmap
*ImgPtr\Width=BmpInf\bmWidth
*ImgPtr\Height=BmpInf\bmHeight
*ImgPtr\Depth=BmpInf\bmBitsPixel
*ImgPtr\ColorArray=0
UseImage(Number)
ProcedureReturn hBitmap
EndProcedure
Exit=0
Size=3000
Repeat
If CreateImage_Test(1,Size,Size)
FreeImage(1)
Size+10
Debug Size
Else
Exit=#True
EndIf
Until Exit
Debug "Erstellt bis: "+Str(Size)
Debug Str(Size*Size*4/1024/1204)+"MB" ;32Bit Color
Ich nutze sowieso lieber DIBitmaps als DDBitmaps. Ein SetDIBitsToDevice reicht aus und man kann das Bitmap auf jeden beliebigen Device Context bringen. Geht flotter und man braucht keine Speichercontexts mittels CreateCompatibleDC() für jeden Devicecontext erstellen, auf dem man die Bitmaps darstellen will.
- NicTheQuick
- Ein Admin
- Beiträge: 8808
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
Bei mir gehts jetzt bis 4683x4683, also 83 MB.
Ich habe das Programm aber auch etwas abgeändert, damit man nicht so lange warten muss
Ich habe das Programm aber auch etwas abgeändert, damit man nicht so lange warten muss
Code: Alles auswählen
Size=3000
add=256
Repeat
If CreateImage(1, Size, Size)
Debug "Image (" + Str(Size) + "x" + Str(Size) + ") erstellt."
FreeImage(1)
Size + add
Else
Debug "Image (" + Str(Size) + "x" + Str(Size) + ") nicht erstellt."
add / 2
Debug "Verringere Größe wieder: Delta = " + Str(add)
If add = 0 : Break : EndIf
Size - add
EndIf
ForEver
Debug "Erstellt bis: " + Str(Size) + "x" + Str(Size)
Debug Str((Size * Size) >> 18) + " MB"
- computerkranker
- Beiträge: 66
- Registriert: 12.10.2004 21:21
Ein bisschen Code hast nicht gerade rum liegen.Ich nutze sowieso lieber DIBitmaps als DDBitmaps
Ich habe das Problem das z.B. unter Win98 mir der Image Speicher ausgeht.
Wenn ich eine alternative dazu hätte wäre das sehr hilfreich.
Ich verstehe aber immer noch nicht warum Windows nur eine bestimmte Größe zulässt. Dabei scheint es keine Rolle zu spielen wie viele Image erzeugt werden. Sondern nur die Größe der Summe aller Image eines Programms. Wobei jedes Programm die gleiche Größe an Speicher zur Verfügung hat.
In der Windows API habe ich noch nichts dazu gefunden.
Wenn jemand einen Vorschlag hat wie man das Problem umgeht, wäre ich sehr dankbar.
War das eine Frage? Also ich hätte einen BMP + TGA Loader mit Bitmap-Klasse in C++ Code anzubieten:computerkranker hat geschrieben:Ein bisschen Code hast nicht gerade rum liegen.
Man erstellt zuerst ein Objekt der Klasse bitmap_class und kann dann mit den Methoden load_bmp_from_file() oder load_tga_from_file() ein BMP- oder ein TGA-Bitmap einladen. Dieses kann man dann mittels draw_to_device() auf jedem beliebigen Device Context angezeigt werden. Außerdem kann man TGAs in BMPs umwandeln (im Speicher). Speichern der BMPs hab ich noch nicht eingerichtet, die Klasse befindet sich noch im Aufbau, weshalb es auch noch wenig optimiert ist.
Auch werden bisher nur unkomprimierte TGAs und BMPs in 32 und 24 Bit Farbtiefe unterstützt.
(Der TGA-Loader ist größtenteils von Nehe übernommen. => http://nehe.gamedev.net/)
Code: Alles auswählen
//Includefile for bitmaps
class bitmap_class
{
private: BITMAPFILEHEADER bmpfileheader;
BITMAPINFOHEADER bmpinfoheader;
unsigned char* data;
public: BITMAPFILEHEADER get_bmpfileheader( void ) {return bmpfileheader;}
BITMAPINFOHEADER get_bmpinfoheader( void ) {return bmpinfoheader;}
unsigned char* get_data( void ) {return data;}
bitmap_class( void );
void set_bmpfileheader( BITMAPFILEHEADER param) { bmpfileheader = param;}
void set_bmpinfoheader( BITMAPINFOHEADER param) { bmpinfoheader = param;}
void set_data_size( int size) {data = (unsigned char*) malloc(size);}
void set_buffer_to_data( unsigned char* adresse, int size) {memcpy(data, adresse, size);}
bool load_bmp_from_file(char* filename); //Methode for loading bmps from harddisc
bool load_tga_from_file(char* filename);
bool create_bmp_from_image_data(char* image_data, int size_x, int size_y, int bit_per_pixel);
void draw_to_device(HDC hdc, int pos_x, int pos_y, int size_x, int size_y, int source_x, int source_y, int source_size_x, int souce_size_y, unsigned char* buffer, BITMAPINFO* bitmapinfo);
};
void bitmap_class::draw_to_device(HDC hdc, int pos_x, int pos_y, int size_x, int size_y, int source_x, int source_y, int source_size_x, int source_size_y, unsigned char* buffer, BITMAPINFO* bmpinfo)
{
SetDIBitsToDevice( hdc, // handle of device context
pos_x, // x-coordinate of upper-left corner of dest. rect.
pos_y, // y-coordinate of upper-left corner of dest. rect.
size_x, // source rectangle width
size_y, // source rectangle height
source_x, // x-coordinate of lower-left corner of source rect.
source_y, // y-coordinate of lower-left corner of source rect.
source_size_x, // first scan line in array
source_size_y, // number of scan lines
buffer, // address of array with DIB bits
bmpinfo, // address of structure with bitmap info.
DIB_RGB_COLORS // RGB or palette indices
);
}
bitmap_class::bitmap_class( void )
{
data = NULL; //Set data for image data to zero
}
bool bitmap_class::create_bmp_from_image_data(char* image_data, int size_x, int size_y, int bit_per_pixel)
{
if ((bit_per_pixel != 32 && bit_per_pixel != 24) || image_data == NULL || size_x <= 0 || size_y <= 0) //check for possible false parameters and return false
{
return false;
}
int image_size = size_x * size_y * (bit_per_pixel / 8);
if (data != NULL) //If there is already another bitmap loaded, free these image byte
{
free(data);
}
this->data = (unsigned char*) malloc(image_size); //Reserve memory for image Data
memcpy(this->data, (unsigned char*)image_data, image_size); //Copy the bytedata to data-buffer for use later
int temp = 0;
for(unsigned int i=0; i< (int)(image_size); i += (bit_per_pixel/8)) // Loop Through The Image Data
{ // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
temp=this->data[i]; // Temporarily Store The Value At Image Data 'i'
this->data[i] = this->data[i + 2]; // Set The 1st Byte To The Value Of The 3rd Byte
this->data[i + 2] = temp; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
}
bmpinfoheader.biSize = sizeof(BITMAPINFOHEADER); //Fill the bitmapinfoheader with infos from bitmap
bmpinfoheader.biWidth = size_x;
bmpinfoheader.biHeight = size_y;
bmpinfoheader.biPlanes = 1;
bmpinfoheader.biBitCount = bit_per_pixel;
bmpinfoheader.biCompression = BI_RGB;
bmpinfoheader.biSizeImage = 0;
bmpinfoheader.biXPelsPerMeter = 96;
bmpinfoheader.biYPelsPerMeter = 96;
bmpinfoheader.biClrUsed = 0;
bmpinfoheader.biClrImportant = 0;
return true;
}
bool bitmap_class::load_tga_from_file(char *filename) // Loads A TGA File Into Memory
{
TextureImage texture;
GLubyte TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header
GLubyte TGAcompare[12]; // Used To Compare TGA Header
GLubyte header[6]; // First 6 Useful Bytes From The Header
GLuint bytesPerPixel; // Holds Number Of Bytes Per Pixel Used In The TGA File
GLuint imageSize; // Used To Store The Image Size When Setting Aside Ram
GLuint temp; // Temporary Variable
GLuint type=GL_RGBA; // Set The Default GL Mode To RBGA (32 BPP)
FILE *file = fopen(filename, "rb"); // Open The TGA File
if( file==NULL || // Does File Even Exist?
fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) || // Are There 12 Bytes To Read?
memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0 || // Does The Header Match What We Want?
fread(header,1,sizeof(header),file)!=sizeof(header)) // If So Read Next 6 Header Bytes
{
if (file == NULL) // Did The File Even Exist? *Added Jim Strong*
return FALSE; // Return False
else // Otherwise
{
fclose(file); // If Anything Failed, Close The File
return FALSE; // Return False
}
}
texture.width = header[1] * 256 + header[0]; // Determine The TGA Width (highbyte*256+lowbyte)
texture.height = header[3] * 256 + header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
if( texture.width <=0 || // Is The Width Less Than Or Equal To Zero
texture.height <=0 || // Is The Height Less Than Or Equal To Zero
(header[4]!=24 && header[4]!=32)) // Is The TGA 24 or 32 Bit?
{
fclose(file); // If Anything Failed, Close The File
return FALSE; // Return False
}
texture.bpp = header[4]; // Grab The TGA's Bits Per Pixel (24 or 32)
bytesPerPixel = texture.bpp/8; // Divide By 8 To Get The Bytes Per Pixel
imageSize = texture.width*texture.height*bytesPerPixel; // Calculate The Memory Required For The TGA Data
texture.imageData=(GLubyte *)malloc(imageSize); // Reserve Memory To Hold The TGA Data
if( texture.imageData==NULL || // Does The Storage Memory Exist?
fread(texture.imageData, 1, imageSize, file)!=imageSize) // Does The Image Size Match The Memory Reserved?
{
if(texture.imageData!=NULL) // Was Image Data Loaded
free(texture.imageData); // If So, Release The Image Data
fclose(file); // Close The File
return FALSE; // Return False
}
for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel) // Loop Through The Image Data
{ // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
temp=texture.imageData[i]; // Temporarily Store The Value At Image Data 'i'
texture.imageData[i] = texture.imageData[i + 2]; // Set The 1st Byte To The Value Of The 3rd Byte
texture.imageData[i + 2] = temp; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
}
fclose (file); // Close The File
data = (unsigned char*) malloc(imageSize); //Reserve memory for image Data
memcpy(this->data, texture.imageData, imageSize); //Copy the bytedata to data-buffer for use later
bmpinfoheader.biSize = sizeof(BITMAPINFOHEADER); //Fill the bitmapinfoheader with infos from bitmap
bmpinfoheader.biWidth = texture.width;
bmpinfoheader.biHeight = texture.height;
bmpinfoheader.biPlanes = 1;
bmpinfoheader.biBitCount = texture.bpp;
bmpinfoheader.biCompression = BI_RGB;
bmpinfoheader.biSizeImage = 0;
bmpinfoheader.biXPelsPerMeter = 96;
bmpinfoheader.biYPelsPerMeter = 96;
bmpinfoheader.biClrUsed = 0;
bmpinfoheader.biClrImportant = 0;
return true; // Texture Building Went Ok, Return True
}
bool bitmap_class::load_bmp_from_file(char* filename)
{
int bytesread;
int bit_size;
ifstream file(filename, ios::in | ios::binary);
if (!file)
{
return false;
}
else
{
file.read((char*)&bmpfileheader, sizeof(BITMAPFILEHEADER));
file.read((char*)&bmpinfoheader, sizeof(BITMAPINFOHEADER));
bit_size = (bmpfileheader.bfSize) - bmpfileheader.bfOffBits; //Size of bit-map
data = (unsigned char*) malloc(bit_size); //Change size of bit-data
file.read((char*)data, bit_size); //Read bit data in temp buffer
file.close();
return true;
}
}
Der Vorteil von DIBitmaps ist, dass man praktisch nur die Daten aus dem Bitmap im Speicher brauch und dann mit nur einer Funktion einen Pointer auf die Bitdaten und auf den Infoheader bereich legt und schon kann man das Bitmap überall anzeigen lassen. Speichern geht natürlich dann auch recht einfach, indem man die Daten + Header einfach wieder in eine Datei schreibt und speichert.
- computerkranker
- Beiträge: 66
- Registriert: 12.10.2004 21:21
Erstmal danke, es war eine Frage
... aber wenn ich was in C++ schreiben wolte, hätte ich bestimmt nicht in diesem Forum eine Lösung gesucht. 
Fred seine Aussage ist ja auch sehr nett


Fred seine Aussage ist ja auch sehr nett

http://forums.purebasic.com/english/vie ... 5084#95084To be honnest i don't know. It's may be documented in the MSDN ?
Nun, aus dem C++ Code kannst du dir ja ansehen wie man es machen könnte. Einen anderen Code kann ich dir nicht geben da ich seit gewisser Zeit nur noch in C/C++ scheibe, Anwendungen mit DIBs oder DDB hab ich nur in C.computerkranker hat geschrieben:Erstmal danke, es war eine Frage... aber wenn ich was in C++ schreiben wolte, hätte ich bestimmt nicht in diesem Forum eine Lösung gesucht.
- computerkranker
- Beiträge: 66
- Registriert: 12.10.2004 21:21
Ne geht schon,...Wenn du kein c++ verstehst lies dir ein Tutorial durch.

Also irgend wie komme ich auch mit DIB nicht weiter, gleiches prob.
Code: Alles auswählen
#DIB_32=36
Global GlobalHDC
GlobalHDC=CreateDC_("DISPLAY", #Null,#Null, #Null)
Procedure.l CreateDIBImage(ImageId,Width,Height,ColorFormat)
bmpinfoheader.BITMAPINFOHEADER
bmpinfoheader\biSize=SizeOf(BITMAPINFOHEADER)
bmpinfoheader\biWidth=Width
bmpinfoheader\biHeight=Height
bmpinfoheader\biPlanes=1
bmpinfoheader\biBitCount=ColorFormat
bmpinfoheader\biCompression=0
bmpinfoheader\biSizeImage=0
bmpinfoheader\biXPelsPerMeter=96
bmpinfoheader\biYPelsPerMeter=96
bmpinfoheader\biClrUsed=0
bmpinfoheader\biClrImportant=0
Result=CreateDIBitmap_(GlobalHDC,bmpinfoheader,0,0,0,#DIB_RGB_COLORS)
ProcedureReturn Result
EndProcedure
Exit=0
Size=3000
Repeat
ImageId=CreateDIBImage(1,Size,Size,#DIB_32)
If ImageId
DeleteObject_(ImageId)
Size+10
Debug Size
Else
Exit=#True
EndIf
Until Exit
Debug "Erstellt bis: "+Str(Size)
Debug Str(Size*Size*4/1024/1204)+"MB" ;32Bit Color
DeleteDC_(GlobalHDC)