Avatar billede narrr Nybegynder
28. december 2003 - 16:10 Der er 10 kommentarer

Gemme DC på disk

Hej. Er der nogen, der gider skrive et eksempel på hvordan kan tager indholdet fra et HDC og gemmer det i en bmp-fil på disken? Jeg har selv prøvet på at lave noget, men jeg ved ikke helt hvad der gik galt. Billedet blev bare fyldt med "støj" ...

Det skal være i ren win32-api, dvs. ikke noget MFC og den slags.
Avatar billede bertelbrander Novice
28. december 2003 - 19:53 #1
Så vidt jeg ved indehoder en DC ikke pixels, en DC er en dims der bliver brugt til at tegne med.

Så vidt jeg ved skal du lave en DC der er en fil, og derefter "tegne" det du vil have i filen.

Prøv at vise det du har, så kan vi bygge videre på det.
Avatar billede narrr Nybegynder
28. december 2003 - 21:24 #2
Nu har jeg godt nok slettet det kode fordi jeg blev lidt irriteret, men det var noget lign det her(ikke testet):

HDC hdc = GetDC(hwnd); // så har vi en DC til det, der skal gemmes i filen

HDC compDC = CreateCompatibleDC(hdc);

//300 er width og height
HBITMAP bitmap = CreateCompatibleBitmap(hdc, 300, 300);

//Så tegner jeg så fra hdc til compDC(og dermed til bitmap)
BitBlt(compDC, 0, 0, 300, 300, hdc, 0, 0, SRCCOPY);

//Nu vil jeg så have bitsne fra bitmap over i et array
unsigned char* bits = new unsigned char[300*300*3]; //*3 for RGB, ikk?
GetBitmapBits(bitmap, 300*300*3, bits);

//Og så havde jeg et stykke kode der kunne skrive en BMP-fil til disken, hvis du også vil se det så sig lige til. Koden kommer fra en bog, så jeg skulle da mene at den virker. Sig lige til hvis du også vil se det.

WriteBitmapFile(filename, width, height, bits)
Avatar billede narrr Nybegynder
28. december 2003 - 21:28 #3
Her er det alligevel:

---
int WriteBitmapFile(char *filename, int width, int height, unsigned char *imageData)
{
    FILE            *filePtr;            // file pointer
    BITMAPFILEHEADER bitmapFileHeader;    // bitmap file header
    BITMAPINFOHEADER bitmapInfoHeader;    // bitmap info header
   
    // open file for writing binary mode
    filePtr = fopen(filename, "wb");
    if (!filePtr)
        return 0;

    // define the bitmap file header
    bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER);
    bitmapFileHeader.bfType = 0x4D42;
    bitmapFileHeader.bfReserved1 = 0;
    bitmapFileHeader.bfReserved2 = 0;
    bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
   
    // define the bitmap information header
    bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitmapInfoHeader.biPlanes = 1;
    bitmapInfoHeader.biBitCount = 24;                        // 24-bit
    bitmapInfoHeader.biCompression = BI_RGB;                // no compression
    bitmapInfoHeader.biSizeImage = width * abs(height) * 3;    // width * height * (RGB bytes)
    bitmapInfoHeader.biXPelsPerMeter = 0;
    bitmapInfoHeader.biYPelsPerMeter = 0;
    bitmapInfoHeader.biClrUsed = 0;
    bitmapInfoHeader.biClrImportant = 0;
    bitmapInfoHeader.biWidth = width;                        // bitmap width
    bitmapInfoHeader.biHeight = height;                    // bitmap height

    // write the bitmap file header
    fwrite(&bitmapFileHeader, 1, sizeof(BITMAPFILEHEADER), filePtr);

    // write the bitmap info header
    fwrite(&bitmapInfoHeader, 1, sizeof(BITMAPINFOHEADER), filePtr);

    // write the image data
    fwrite(imageData, 1, bitmapInfoHeader.biSizeImage, filePtr);

    // close our file
    fclose(filePtr);

    return 1;
}
---
Avatar billede bertelbrander Novice
29. december 2003 - 00:57 #4
Jeg er ikke sikker, men jeg tror ikke at man kan hente data fra en DC på den måde.

Jeg har lavet en lille funktion der skriver på en DC og så gemmer det den har skrevet i en .bmp-fil, det ser ud til at virke.

BOOL Testing(HWND hwnd)
{
  HDC hdc = GetDC(hwnd);
  HBRUSH Brush = CreateSolidBrush(RGB(255, 0, 0));
  HBRUSH OldBrush = SelectObject(hdc, Brush);
  RECT Rect = {0, 0, 300, 300};
  FillRect(hdc, &Rect, Brush);
  HPEN Pen = CreatePen(PS_SOLID, 10, RGB(0, 0, 255));
  HPEN OldPen = SelectObject(hdc, Pen);
  MoveToEx(hdc, 10, 10, 0);
  LineTo(hdc, 290, 290);
  MoveToEx(hdc, 290, 10, 0);
  LineTo(hdc, 10, 290);
  MoveToEx(hdc, 100, 10, 0);
  LineTo(hdc, 200, 10);

  MoveToEx(hdc, 10, 100, 0);
  LineTo(hdc, 10, 200);

  unsigned char *bits = malloc(300*300*3);
  int i, j, c;
  for(i = 0; i < 300; i++)
    for(j = 0; j < 300; j++)
    {
          c = GetPixel(hdc, j, i);
          bits[((299 - i)*300 + j)*3 + 0] = (c >> 16) & 0xFF;
          bits[((299 - i)*300 + j)*3 + 1] = (c >> 8) & 0xFF;
          bits[((299 - i)*300 + j)*3 + 2] = (c >> 0) & 0xFF;
    }

  WriteBitmapFile("d:\\Test.bmp", 300, 300, bits);

  SelectObject(hdc, OldBrush);
  SelectObject(hdc, OldPen);
  free(bits);

  ReleaseDC(hwnd, hdc);

  return 1;
}
Avatar billede narrr Nybegynder
29. december 2003 - 15:31 #5
Ja, det virker. Jeg prøvede at sætte min kode med GetBitmapBits ind i stedet for din løkke, og den gav mig et billede der lignede det på skræmen lidt. Mon det skyldes at GetBitmapBits gemmer bitsne i arrayet på en anden måde, end WriteBitmapFile forventer?

Anyways, så prøvede jeg GetDIBits i stedet for GetBitmapBits, og det virkede sørme!
Avatar billede bertelbrander Novice
29. december 2003 - 17:37 #6
Jeg kunne forestille mig at GetBitmapBits gemmer 4 bytes for hver pixel. Prøv at kikke i .bmp filen med en editor der kan vise rå bytes og prøv om du kan se et mønster (eller send mig .bmp filen, zippet).

Jeg vil meget gerne se koden med GetDIBits, hvis jeg må.
Avatar billede jpk Nybegynder
29. december 2003 - 17:39 #7
narrr >> du mangler en SelectObject i din kode efter du har oprettet bitmappen.
Hvis du ikke vælger den ind i DC'et før du tegner (Blt'er) i det, giver det ingen mening...
Avatar billede narrr Nybegynder
29. december 2003 - 18:15 #8
ja ok, den glemte jeg lige.. jeg har den naturligvis med i den "rigtige" kode.
Avatar billede olennert Nybegynder
02. januar 2004 - 11:19 #9
Nu er det mange år siden jeg har kodet under Windows, så tag dette med et gran salt.

Jeg synes jeg kan huske noget med at de ting man skriver på en DC svarer til kommandoerne i en WMF fil. Så det burde være muligt på en nem måde at tage en DC og smide den i en WMF fil. Tror jeg nok, altså.
Avatar billede bertelbrander Novice
02. januar 2004 - 13:39 #10
Du husker rigtigt, man bruger CreateMetaFile() til at lave filen og få en DC som man så "tegner" med. Se f.ex:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/metafile_612d.asp
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester