Umfrage zur maximalen Imagegröße

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Ynnus
Beiträge: 855
Registriert: 29.08.2004 01:37
Kontaktdaten:

Beitrag von Ynnus »

Aber das nicht der volle Speicher ausgereizt wird, wenn das Programm dies mittels Image-Erstellung versucht, sollte ihm wohl klar sein. Das lässt sich ja auch nun nicht mehr leugnen nach zahlreichen Tests, heut und in der Vergangenheit auch schon.
Benutzeravatar
computerkranker
Beiträge: 66
Registriert: 12.10.2004 21:21

Beitrag von computerkranker »

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...

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
Benutzeravatar
Ynnus
Beiträge: 855
Registriert: 29.08.2004 01:37
Kontaktdaten:

Beitrag von Ynnus »

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.
Benutzeravatar
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

Beitrag von NicTheQuick »

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

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"
Benutzeravatar
computerkranker
Beiträge: 66
Registriert: 12.10.2004 21:21

Beitrag von computerkranker »

Ich nutze sowieso lieber DIBitmaps als DDBitmaps
Ein bisschen Code hast nicht gerade rum liegen.
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.
Benutzeravatar
Ynnus
Beiträge: 855
Registriert: 29.08.2004 01:37
Kontaktdaten:

Beitrag von Ynnus »

computerkranker hat geschrieben:Ein bisschen Code hast nicht gerade rum liegen.
War das eine Frage? Also ich hätte einen BMP + TGA Loader mit Bitmap-Klasse in C++ Code anzubieten:

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.
Benutzeravatar
computerkranker
Beiträge: 66
Registriert: 12.10.2004 21:21

Beitrag von computerkranker »

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 :mrgreen:
To be honnest i don't know. It's may be documented in the MSDN ?
http://forums.purebasic.com/english/vie ... 5084#95084
Benutzeravatar
Ynnus
Beiträge: 855
Registriert: 29.08.2004 01:37
Kontaktdaten:

Beitrag von Ynnus »

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. /:->
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.
Benutzeravatar
Batze
Beiträge: 1492
Registriert: 03.06.2005 21:58
Wohnort: Berlin
Kontaktdaten:

Beitrag von Batze »

Wenn du kein c++ verstehst lies dir ein Tutorial durch.
Der Code ist recht einfach, den sollte man in PureBasic umsetzen können. :allright:
Hier sind meine Codes (aber die Seite geht gerade nicht):
http://www.basicpure.de.vu
Benutzeravatar
computerkranker
Beiträge: 66
Registriert: 12.10.2004 21:21

Beitrag von computerkranker »

Wenn du kein c++ verstehst lies dir ein Tutorial durch.
Ne geht schon,...:mrgreen:

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)
Antworten