bmp-kuva luetaan koodilla:
void BitMapTest(void) { HBITMAP valikko=LoadImage(NULL, "C:\\kuva.bmp", IMAGE_BITMAP, 1024, 1024, LR_LOADFROMFILE); HDC src=CreateCompatibleDC(NULL); SelectObject(src, valikko); HDC dst=GetDC(hwnd); BitBlt(dst, 0, 0, 1024, 1024, src, 0, 0, SRCCOPY); }
Nyt pelissä muokataan tuota kuvaa, mutta miten se tallennetaan?
Tähän löytyy hyvinkin koodeja esim. hakusanoilla WinAPI save BMP.
Onko jokin syy, miksi ylipäänsä käytät WinAPIa etkä jotain yksinkertaisempaa kirjastoa?
Metabolix kirjoitti:
(08.02.2020 12:47:38): Tähän löytyy hyvinkin koodeja esim...
Olen ohjelmoinut kaikki WinApilla, eikä noilla hakusanoilla löydy yksinkertaista koodiesimerkkiä, miten bmp tiedosto käytännössä tallennetaan kovalevylle. Voisiko täältä saada esimerkin funktiolle:
TallenaBMPtiedosto(char *tiedostonNimi, HDC hdc, HWND hwnd, int leveys, int korkeus) { // Talletettava 24-bittinen bmp tiedosto alkaa pisteestä (0, 0) }
Tallennettava bmp tiedosto on RGB väreissä.
Teen fraktaalizoomausta. Minun pahin ongelma on, etten vielä osaa hyvin englanninkieltä.
Viestini ensimmäinen linkki vie suoraan koodiin, joten miten on mahdollista, että et löydä? Koodi on kyllä erittäin pitkä ja hankala. Jos ei ole jotenkin aivan erityistä kiinnostusta juuri WinAPI:n käyttöön, olisi viisasta tehdä ohjelma jollain helpommalla työkalulla. Sopiva työkalu riippuu toki ohjelmasta, mutta useimpiin ohjelmiin on varmasti olemassa helpompia vaihtoehtoja kuin suora WinAPI:n käyttö.
Lahdevesi kirjoitti:
Olen ohjelmoinut kaikki WinApilla, eikä noilla hakusanoilla löydy yksinkertaista koodiesimerkkiä, miten bmp tiedosto käytännössä tallennetaan kovalevylle.
Jos etsit muutaman rivin esimerkkiä WinApilla, et löydä sellaista vaan pääset kirjoittelemaan BITMAPFILEHEADER:in, täyttelemään BITMAPINFOHEADER:in ja muuta mukavaa...
Helpointa olisi varmaan käyttää GDI+:saa hoitamaan homma. Ei muistaakseni vaadi kauhean montaa riviä koodia.
Metabolix kirjoitti:
(08.02.2020 20:51:51): Viestini ensimmäinen linkki vie suoraan koodiin...
Minulla on mozilla firefox. Voisiko se ehdottaa jotain toista sivua ensimmäiseksi, mitä sivua tarkoitat, koska sivulla ei ole mitään järkevää vihjettä?
Väännetään nyt vielä rautalangasta:
Metabolix kirjoitti:
Tähän löytyy hyvinkin ⇒ ⇒ ⇒ koodeja ⇐ ⇐ ⇐ esim. hakusanoilla WinAPI save BMP.
Yllä nuolilla merkitty linkki vie suoraan kohteeseen. Olet sikäli oikeassa, että sivulta ei löydy ”järkevää vihjettä” vaan koko pitkä tallennuskoodi, jota pitää sitten vielä osata käyttää.
Itse olen joskus käyttänyt GDI+ Flat api:a kun piti saada kuva tallennettua png formaattiin.
Muistaakseni menee jotenkin:
GdiplusStartup
GdipCreateFromHDC
GdipCreateBitmapFromGraphics
GdipSaveImageToFile
GdiplusShutdown
Parametrit noihin saat hakea netin kautta itse...
Onpa mukavaa, että minäpä osaan, muta sinä et, häh, häh, hää. Onko se nyt ihan ylivoimaista kopioida funktion sisältö raameihin:
/*********************************************************************** * BMP kuva kirjoitetaan tiedostonNimi -binääritiedostoon * * leveys on BMP kuvan leveys alkaen positiosta 0 * * korkeus on BMP kuvan korkeus alkaen positiosta 0 * * bittitarkkuus voi olla 1, 2, 4, 8, 16 ja 24-bittinen RGB-värisyvyys. * * Itse käytän 24-bittistä värisyvyyttä. * ***********************************************************************/ void saveBMP(char *tiedostonNimi, int leveys, int korkeus, int bittitarkkuus)
Ei minun pelin oleellisin asia ole BMP-tiedoston kirjoittaminen kovalevylle, mutta se on oleellinen apufunktio.
Varsinkin, jos tietää, millainen tuo funktion sisältö on, ja jos se käy suunnilleen kopioi - liitä toiminnolla, ihmettelen suuresti tämän sivuston tarkoitusta.
Mitä järkeä on kysyä yhtään mitään ohjelmointiongelmiin liittyvää, jos vastauksena on pelkkiä ympäripyöreitä linkkejä, että kaiva se oleellinen asia sieltä sotkun seasta.
Tekisi mieli sanoa ruma sana. Ja miksi koneen boottauksen jälkeen joutuu aina luomaan uuden käyttäjätunnuksen. Varmaan siksi, että tunnus vaatii niin monimutkaisen salasanan.
rannekello kirjoitti:
Varsinkin, jos tietää, millainen tuo funktion sisältö on, ja jos se käy suunnilleen kopioi - liitä toiminnolla, ihmettelen suuresti tämän sivuston tarkoitusta.
Mistä päättelet että kenelläkään täällä vastanneella olisi ollut käytössään jotain kuvaamasi tyylistä funktiota?
Ensinnäkin voi olla ettei täällä ole lisäksesi muita masokisteja (jotka siis haluaisivat koodata suoraan WinAPIlla)
Toisekseen vaikka joku olisi jotain koodannutkin niin on aika epätodennäköistä, että kellään sattuisi vaan olemaan koodi joka kopioi näyttöpinnalta 0,0 - 1023,1023 alueelta kuvan bittikartaksi ja tallentaa sen. (Kuten tarpeesi alkuperäisessä viestissä kuvailit)
Ohessa on netistä löytämäni esimerkki, joka tallentaa koko näytön bitmapiksi. Siitä luulisi olevan aika helppo soveltaa: (Kuten ehkä huomaat niin tuossa on mukana ne Metabolixin aikaisemmin laittamat koodit lähes sellaisinaan. Tässä vaan on vielä lisäksi käytännön esimerkki miten niitä käytetään)
#include <Windows.h> #include <stdio.h> #include <assert.h> /* forward declarations */ PBITMAPINFO CreateBitmapInfoStruct(HBITMAP); void CreateBMPFile(LPTSTR pszFile, HBITMAP hBMP); int main(int argc, char **argv); PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp) { BITMAP bmp; PBITMAPINFO pbmi; WORD cClrBits; // Retrieve the bitmap color format, width, and height. assert(GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)); // Convert the color format to a count of bits. cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); if (cClrBits == 1) cClrBits = 1; else if (cClrBits <= 4) cClrBits = 4; else if (cClrBits <= 8) cClrBits = 8; else if (cClrBits <= 16) cClrBits = 16; else if (cClrBits <= 24) cClrBits = 24; else cClrBits = 32; // Allocate memory for the BITMAPINFO structure. (This structure // contains a BITMAPINFOHEADER structure and an array of RGBQUAD // data structures.) if (cClrBits < 24) pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< cClrBits)); // There is no RGBQUAD array for these formats: 24-bit-per-pixel or 32-bit-per-pixel else pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER)); // Initialize the fields in the BITMAPINFO structure. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = bmp.bmWidth; pbmi->bmiHeader.biHeight = bmp.bmHeight; pbmi->bmiHeader.biPlanes = bmp.bmPlanes; pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; if (cClrBits < 24) pbmi->bmiHeader.biClrUsed = (1<<cClrBits); // If the bitmap is not compressed, set the BI_RGB flag. pbmi->bmiHeader.biCompression = BI_RGB; // Compute the number of bytes in the array of color // indices and store the result in biSizeImage. // The width must be DWORD aligned unless the bitmap is RLE // compressed. pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 * pbmi->bmiHeader.biHeight; // Set biClrImportant to 0, indicating that all of the // device colors are important. pbmi->bmiHeader.biClrImportant = 0; return pbmi; } void CreateBMPFile(LPTSTR pszFile, HBITMAP hBMP) { HANDLE hf; // file handle BITMAPFILEHEADER hdr; // bitmap file-header PBITMAPINFOHEADER pbih; // bitmap info-header LPBYTE lpBits; // memory pointer DWORD dwTotal; // total count of bytes DWORD cb; // incremental count of bytes BYTE *hp; // byte pointer DWORD dwTmp; PBITMAPINFO pbi; HDC hDC; hDC = CreateCompatibleDC(GetWindowDC(GetDesktopWindow())); SelectObject(hDC, hBMP); pbi = CreateBitmapInfoStruct(hBMP); pbih = (PBITMAPINFOHEADER) pbi; lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); assert(lpBits) ; // Retrieve the color table (RGBQUAD array) and the bits // (array of palette indices) from the DIB. assert(GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, DIB_RGB_COLORS)); // Create the .BMP file. hf = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, (DWORD) 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); assert(hf != INVALID_HANDLE_VALUE) ; hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" // Compute the size of the entire file. hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih->biSizeImage); hdr.bfReserved1 = 0; hdr.bfReserved2 = 0; // Compute the offset to the array of color indices. hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof (RGBQUAD); // Copy the BITMAPFILEHEADER into the .BMP file. assert(WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL)); // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. assert(WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof (RGBQUAD), (LPDWORD) &dwTmp, ( NULL))); // Copy the array of color indices into the .BMP file. dwTotal = cb = pbih->biSizeImage; hp = lpBits; assert(WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)); // Close the .BMP file. assert(CloseHandle(hf)); // Free memory. GlobalFree((HGLOBAL)lpBits); } int main(int argc, char **argv) { HWND hwnd; HDC hdc[2]; HBITMAP hbitmap; RECT rect; hwnd = GetDesktopWindow(); GetClientRect(hwnd, &rect); hdc[0] = GetWindowDC(hwnd); hbitmap = CreateCompatibleBitmap(hdc[0], rect.right, rect.bottom); hdc[1] = CreateCompatibleDC(hdc[0]); SelectObject(hdc[1], hbitmap); BitBlt ( hdc[1], 0, 0, rect.right, rect.bottom, hdc[0], 0, 0, SRCCOPY ); CreateBMPFile("bitmap.bmp", hbitmap); return 0; }
rannekello kirjoitti:
Mitä järkeä on kysyä yhtään mitään ohjelmointiongelmiin liittyvää, jos vastauksena on pelkkiä ympäripyöreitä linkkejä, että kaiva se oleellinen asia sieltä sotkun seasta.
Sille ei varmaan hirveästi mitään voi, että puhtaalla WinAPIlla koodatessa yksinkertaisenkin asian tekeminen on enemmän tai vähemmän sotku.
Metabolixin linkkaamalla sivulla oli 138 riviä koodia (jonka tarvitset kokonaan) ja lisäksi noin 12 riviä tekstiä. Koodit oli vielä laatikoissa joiden kulmissa oli "Copy" panikkeet. Jos se koodi "kaivaminen" sieltä tosiaan oli ihan ylivoimaista niin aika paljon kädestä pitämistä tarvitset.
rannekello kirjoitti:
Onpa mukavaa, että minäpä osaan, muta sinä et, häh, häh, hää. Onko se nyt ihan ylivoimaista kopioida funktion sisältö raameihin:
Minusta ei ole kohtuutonta, että porukka ei jaksa alkaa tehdä sinun hommaasi puolestasi, eli soveltaa tuolta linkistä löytyvää koodia sinun käyttötarkoitukseesi. Sellainen on triviaalia, mutta työlästä eikä tuo juurikaan lisäarvoa tänne foorumille.
Metabolixin vastaus oli oikein hyvä, hän osoitti juuri siihen resurssiin jota tarvitset toteuttaaksesi tallennuksen ja lisäksi mainitsi, että homman voi tehdä helpomminkin. Ei foorumin tarkoitus ole tehdä sinulle koodejasi valmiiksi.
Aihe on jo aika vanha, joten et voi enää vastata siihen.