PDA

Visualizza la versione completa : [C++] Screenshot con salvataggio file


nigel
16-05-2007, 10:14
Ciao a tutti!

In diverse discussioni del forum per c++ Ŕ stato affrontato il problema del cattura schermo, ma non ho trovato soluzione al mio problema:
volevo implementare una classe in un mio programma per salvare lo schermo al verificarsi di alcuni errori nel programma principale in modo da poterli analizzare successivamente.

Di seguito vi mostro il codice riportato in un prorammino a se stante che funziona correttamente, ma il grosso problema Ŕ che non riesco a salvare file che siano pi¨ piccoli di 1,5 Mb. In caso di modifica delle impostazioni della risoluzione grafica riesco ad ottenere file di output pi¨ piccoli ma con 4 colori e quasi illegibili.

L' obiettivo Ŕ quello di ottenere un file bitmap con almeno 256 colori e di dimensioni dell' ordine di 100 - 200 kb.

Potete aiutarmi?

Di seguito il codice del programma:



#include <windows.h>
#include <stdio.h>
#include <wingdi.h>

#include <iostream.h> // per cout

#define BITSPERPIXEL 16



void cap(); //prototipo procedura cattura

int Tempo = 0;

int main() //main procedure
{
Tempo = GetTickCount();
cap();
return 0;
}

void cap()
{
BITMAPINFO bmi; //info del file di destinazione
BITMAPFILEHEADER bfh; //header del file di destinazione

int nWidth;
int nHeight;
HWND hWnd;
HDC hdc ;
HDC memDC;
HBITMAP hbm ;
HBITMAP hbmOld;
BYTE *pbBits;

HANDLE hfile;

// MOD
FILE *FileSave;
int infosize = 0;
int size = 0;
int bitsize = 0;

nWidth = GetSystemMetrics(SM_CXSCREEN); //dimensioni del rettangolo da catturare
nHeight = GetSystemMetrics(SM_CYSCREEN);

hWnd = GetDesktopWindow(); //creazione bitmap
hdc = GetDC(hWnd);
memDC = CreateCompatibleDC(hdc);
hbm = CreateCompatibleBitmap(hdc, nWidth, nHeight);
hbmOld = (HBITMAP)SelectObject(memDC, hbm); //hande to bitmap

BitBlt(memDC, 0, 0, nWidth, nHeight, hdc, 0, 0, SRCCOPY); //cattura bitmap

//modifica settaggio modalita grafica
ZeroMemory(&bmi,sizeof(BITMAPINFO));
bmi.bmiHeader.biSize=sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth=GetSystemMetrics(SM_CXSCREEN );
bmi.bmiHeader.biHeight=GetSystemMetrics(SM_CYSCREE N);
bmi.bmiHeader.biPlanes=1;
bmi.bmiHeader.biBitCount=16;
bmi.bmiHeader.biCompression= BI_RGB; //BI_RLE4; // BI_RGB;
bmi.bmiHeader.biSizeImage=3 * bmi.bmiHeader.biWidth * bmi.bmiHeader.biHeight;

pbBits = (byte *) malloc(bmi.bmiHeader.biSizeImage); //alloca la memoria per l' immagine

// get image from Desktop
GetDIBits( memDC, //handle to device
hbm, //Handle to the bitmap
0, //first scan line to set in destination bitmap
bmi.bmiHeader.biHeight, //number of scan lines to copy
pbBits, //address of array for bitmap bits
&bmi, //address of structure with bitmap data
DIB_RGB_COLORS ); //RGB or palette index //DIB_PAL_COLORS);

infosize = sizeof(BITMAPINFOHEADER);

size = sizeof(BITMAPFILEHEADER); // + infosize + bmi.bmiHeader.biSizeImage ;

bfh.bfType='MB';
bfh.bfOffBits=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bfh.bfSize=bmi.bmiHeader.biSizeImage + bfh.bfOffBits;

int CalcoloTeorico = (sizeof(BITMAPFILEHEADER) + bmi.bmiHeader.biSize +
bmi.bmiHeader.biClrUsed * sizeof(RGBQUAD) +
bmi.bmiHeader.biSizeImage);

cout << "Calcolo teorico dimensione file " << CalcoloTeorico << "\n";

cout << "Dimensione reale file " << size << "\n";

cout << " \n\n\n\n\n\n statistiche ";
cout << " dimensione BITMAPFILEHEADER " << sizeof(BITMAPFILEHEADER) << "\n";
cout << " dimensione infosize " << infosize << "\n";
cout << " dimensione biSizeImage "<< bmi.bmiHeader.biSizeImage << "\n";
cout << " Dimensione BSIZEIMAGE " << bmi.bmiHeader.biSizeImage << "\n";
cout << "size = " << size << "\n";

//buffer - size item - max number of item - pointer of file

//salvataggio su file
FileSave = fopen("PrimoTipo.bmp","wb");
if (FileSave != NULL)
{
fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), FileSave);
fwrite(&bmi, 1, infosize, FileSave);
fwrite((char *)pbBits, 1, bmi.bmiHeader.biSizeImage, FileSave);

fclose(FileSave);
}

// rilascio risorse
DeleteDC(memDC);
ReleaseDC(hWnd,hdc);
DeleteObject(hbm);

//bmi = NULL;
hfile = NULL;
pbBits = NULL;
free(pbBits);

cout << " Tempo utilizzato per creazione e salvataggio ms " << (GetTickCount() - Tempo) << "\n";
//exit(1);
}

oregon
16-05-2007, 11:09
Le dimensioni dipendono dall'area prelevata e non puoi gestirla tu.

Se prendi un'area di 1024*768 in cui un byte rappresenta il colore di un pixel, solamente di informazioni grafiche hai 786432 byte a cui aggiungerai quelli della "struttura" della bitmap.

Per ridurre la dimensione, devi utilizzare un formato di tipo jpg (o comunque compresso) ma, ovviamente, non puoi utilizzare questo codice ...

nigel
16-05-2007, 11:52
Ok, il discorso fila, ma ho visto dei programmi giÓ compilati che fanno degli screenshot con salvataggio, in cui c'Ŕ la possibilitÓ di salvare il file di output in diversi formati... Tra questi c'Ŕ anche il bitmap ed il prodotto Ŕ un file di circa 120 Kb con risoluzione di 256 colori.

A questo punto devo pensare che si tratti semplicemente di un file jpg rinominato in bitmap... o no?!?!

In ogni caso dato che non mi interessa il tipo di file, ma volevo solo ottimizzare il prodotto in output, potresti consigliarmi un qualche algoritmo che soddisfi le mie necessitÓ con la produzione di un file grafico compresso come il jpg?

Tieni solo presente che sto sviluppando in Visual C++ versione 6, e quindi in modalitÓ unmanagement, senza utilizzare il framework....

Grazie ancora!!!

oregon
16-05-2007, 12:08
Bisogna capire se quei file di cui parli sono effettivamente bmp standard o in un altro formato. Se le hai, falle scaricare e si vede come sono fatte ...

Se vuoi salvare il file in formato jpg, ti devi affidare a delle librerie (magari open source) che lo fanno.

nigel
16-05-2007, 12:44
Dovrei ritrovare quel programma per verificare gli header dei file di output...

Comunque se trovo qualche libreria o altro che finalizzi il mio scopo ti illustrer˛ la soluzione... conosci qualche sito dove poter scaricare librerie per C++ ?

Ciao Ciao!

Loading