2011-04-22 18 views
5

मैं सी ++ (विंडोज़ पर) कोड लिख रहा हूं और मैं ग्रेस्केल बीएमपी के पिक्सेल मान निकालने की कोशिश कर रहा हूं। मुझे मेटाडेटा में से कोई भी रखने की परवाह नहीं है, और बस पिक्सेल मान को चार सरणी में स्टोर करना चाहते हैं। मैं इसे मैन्युअल रूप से करने का मानक या "सामान्य" तरीका नहीं ढूंढ पा रहा हूं, इसलिए मैं सोच रहा हूं कि शायद एक साधारण लाइब्रेरी है जो लोग स्मृति में बिटमैप्स लोड करने के लिए उपयोग करते हैं।मैं बीएमपी पिक्सेल मानों को सरणी में कैसे पढ़ सकता हूं?

अग्रिम धन्यवाद!

उत्तर

5

स्मृति में पूरी फ़ाइल पढ़ें। मोर्चे पर एक छोटा हेडर होगा, और बाकी का पिक्सेल मान होगा।

पहला भाग BITMAPFILEHEADER संरचना होगी। एकमात्र भाग जिसे आप परवाह करते हैं वह bfOffBits है, जो फ़ाइल की शुरुआत से पिक्सेल मानों तक बाइट्स की संख्या देता है।

BITMAPFILEHEADER के बाद अगला भाग BITMAPINFOHEADER होगा। यह पिक्सेल के प्रारूप को निर्धारित करने के लिए उपयोगी होगा।

इसके बाद एक पैलेट के बाद, यदि बिट गहराई को एक की आवश्यकता होती है।

पिक्सेल मानों के साथ कुछ मिलचास हैं। पहला यह है कि आदेश (नीला, हरा, लाल) है, जिस तरह से हर कोई इसे करता है। दूसरा यह है कि पंक्तियां छवि के नीचे से ऊपर तक जाती हैं, फिर से हर किसी से पीछे की तरफ। अंत में, पंक्ति में बाइट्स की संख्या हमेशा 4 के अगले एकाधिक तक पैड की जाएगी।

मैं लगभग उल्लेख करना भूल गया था, एक जेपीईजी या पीएनजी फ़ाइल को बीएमपी के रूप में एन्कोड किया जा सकता है, लेकिन यह है आम नहीं। BITMAPINFOHEADER के द्विपक्षीय क्षेत्र पर नज़र डालें, यदि यह कुछ भी है लेकिन BI_RGB आपको थोड़ी और मदद की आवश्यकता होगी।

2

वहां निश्चित रूप से पुस्तकालय हैं (अन्य उत्तरों देखें), लेकिन एक जफ़ी में, यह स्पष्ट रूप से एक मस्तिष्क-मृत सरल फ़ाइल प्रारूप है जिसे आप आसानी से पार्स कर सकते हैं। विवरण यहां हैं:

http://www.fileformat.info/format/bmp/egff.htm

(मैं एक कुछ वर्षों के लिए Win32 से बाहर किया गया है, लेकिन LoadImage समारोह एक BMP फ़ाइल से आप एक HBITMAP प्राप्त कर सकते हैं मुझे लगता है कि चालू करने के लिए कैसे में निश्चित नहीं हूँ। एक पिक्सेल सारणी सीधे, लेकिन मैं वहाँ है कि आप मूल्यों को आकर्षित करते हैं जाएगा एक डीसी के साथ कुछ विकृति है कल्पना http://support.microsoft.com/kb/158898

अधिक संकेत:। http://alexkr.com/source-code/26/accessing-bitmap-pixels-in-gdi/)

2

आप 2 अच्छा विकल्प हैं:

  1. लोड और बीएमपी खुद फ़ाइल को पार्स। बीएमपी फाइलें बिटमैपफील्डर के साथ शुरू होती हैं, इसके बाद बिटमैपिनफोइडर होता है, इसके बाद 0 या अधिक आरजीबीक्वैड (पैलेट एंट्री) होता है। पिक्सेल डेटा से ऑफसेट बिटमैपफील्डर में है, लेकिन आपको यह सुनिश्चित करने के लिए बिटमैपिनफ़ोएडर की जांच करनी चाहिए कि छवि प्रारूप वह है जिसे आप उम्मीद करते हैं/समर्थन करते हैं।

  2. कॉल लोड इमेज() एपीआई एलआर_CREATEDIBSECTION ध्वज के साथ, यह एक डीआईबी अनुभाग में एक हैंडल वापस कर देगा। इसके बाद आप वापस किए गए हैंडल में गुजरने वाले GetObject() को डायबिसेक्शन संरचना में पॉइंटर कहते हैं। फिर आप बिटमैप आकार, प्रारूप, पॉइंटर डेटा पिक्सेल डेटा आदि के लिए DIBSECTION संरचना पढ़ते हैं।

विकल्प 2 क्योंकि शायद LoadImage() आप के लिए अमान्य फ़ाइल स्वरूपों के लिए जाँच करता है, और सिर्फ बीएमपी फ़ाइलों की तुलना में अधिक लोड कर सकते हैं, यदि आप Windows पर हैं बेहतर है।

विंडोज बीएमपी पिक्सल तक पहुंचने पर, याद रखें कि रेखाएं हमेशा डीडब्ल्यूओआर-गठबंधन होती हैं।

+0

जानकारी के लिए धन्यवाद! –

12

और कोड, जी के साथ परीक्षण किया जाने के लिए तैयार ++ (नहीं विंडोज, लेकिन मदद मिल सकती है किसी को):

#pragma pack(1) 

#include <iostream> 
#include <fstream> 
#include <vector> 

using namespace std; 

#include "bmp.h" 

vector<char> buffer; 
PBITMAPFILEHEADER file_header; 
PBITMAPINFOHEADER info_header; 

void fill() { 
    std::ifstream file("data.bmp"); 

    if (file) { 
     file.seekg(0,std::ios::end); 
     streampos length = file.tellg(); 
     file.seekg(0,std::ios::beg); 

     buffer.resize(length); 
     file.read(&buffer[0],length); 

     file_header = (PBITMAPFILEHEADER)(&buffer[0]); 
     info_header = (PBITMAPINFOHEADER)(&buffer[0] + sizeof(BITMAPFILEHEADER)); 
    } 
} 

int main() { 
    fill(); 

    cout << buffer[0] << buffer[1] << endl; 
    cout << file_header->bfSize << endl; 
    cout << info_header->biWidth << " " << info_header->biHeight << endl; 

    return 0; 
} 

bmp.hi में परिभाषित किया है संरचनाओं:

#pragma once 

typedef int LONG; 
typedef unsigned short WORD; 
typedef unsigned int DWORD; 

typedef struct tagBITMAPFILEHEADER { 
    WORD bfType; 
    DWORD bfSize; 
    WORD bfReserved1; 
    WORD bfReserved2; 
    DWORD bfOffBits; 
} BITMAPFILEHEADER, *PBITMAPFILEHEADER; 

typedef struct tagBITMAPINFOHEADER { 
    DWORD biSize; 
    LONG biWidth; 
    LONG biHeight; 
    WORD biPlanes; 
    WORD biBitCount; 
    DWORD biCompression; 
    DWORD biSizeImage; 
    LONG biXPelsPerMeter; 
    LONG biYPelsPerMeter; 
    DWORD biClrUsed; 
    DWORD biClrImportant; 
} BITMAPINFOHEADER, *PBITMAPINFOHEADER; 
+0

# शामिल "bmp.h"? यह एक मानक फ़ाइल शामिल नहीं है। –

+0

@Alexey Frunze, bmp.h जोड़ा – Yola

+1

मुझे यह भी लगता है कि ओपी पिक्सेल रंगों की एक सरणी चाहता था, सभी फ़ाइल बाइट्स की सरणी नहीं। –

4

अगर दृश्य स्टूडियो में कोडिंग , अपने टैग BITMAPFILEHEADER और टैग BITMAPINFOHEADER structs (योल की प्रतिक्रिया में दिखाया गया) घोषित करने से पहले "#pragma पैक (2)" को शामिल करना सुनिश्चित करें। इसके बाद संरचना अगले 2 बाइट सीमा के बजाय अगले 4 बाइट सीमा तक गद्दी होगी, और डेटा कचरा होगा।

संदर्भ http://tipsandtricks.runicsoft.com/Cpp/BitmapTutorial.html

2

Yola क्या लिखा विस्तार करते हुए, इस में एक फ़ाइल पढ़ सकते हैं और उत्पादन के लिए सक्षम होना चाहिए। यह अच्छी तरह से परीक्षण नहीं है, लेकिन काम करने लगता है। यह उस फ़ाइल के प्रारूप का उपयोग करता है जो इसे आउटपुट करते समय पढ़ता है।

#include <iostream> 
#include <unistd.h> 
#include <fstream> 

using std::cout; 
using std::endl; 
using std::ofstream; 
using std::ifstream; 

#pragma pack(1) 
#pragma once 

typedef int LONG; 
typedef unsigned short WORD; 
typedef unsigned int DWORD; 

typedef struct tagBITMAPFILEHEADER { 
    WORD bfType; 
    DWORD bfSize; 
    WORD bfReserved1; 
    WORD bfReserved2; 
    DWORD bfOffBits; 
} BITMAPFILEHEADER, *PBITMAPFILEHEADER; 

typedef struct tagBITMAPINFOHEADER { 
    DWORD biSize; 
    LONG biWidth; 
    LONG biHeight; 
    WORD biPlanes; 
    WORD biBitCount; 
    DWORD biCompression; 
    DWORD biSizeImage; 
    LONG biXPelsPerMeter; 
    LONG biYPelsPerMeter; 
    DWORD biClrUsed; 
    DWORD biClrImportant; 
} BITMAPINFOHEADER, *PBITMAPINFOHEADER; 

unsigned char** reds; 
unsigned char** greens; 
unsigned char** blues; 
int rows; 
int cols; 

void ColorTest() { 
    // Makes Red Rectangle in top left corner. Rectangle stretches to right alot 
    for (int i = rows/10; i < 3 * rows/10; i++) 
     for (int j = cols/10; j < 7 * cols/10; j++) 
      reds[i][j] = 0xff; 

// Makes small green box in bottom right 
    for (int i = 8 * rows/10; i < rows; i++) 
     for (int j = 8 * cols/10; j < cols; j++) 
      greens[i][j] = 0xff; 

// Makes White box in the middle of the screeene  
    for (int i = rows * 4/10; i < rows * 6/10; i++) 
     for (int j = cols * 4/10; j < cols * 6/10; j++) { 
      greens[i][j] = 0xff; 
      reds[i][j] = 0xff; 
      blues[i][j] = 0xff; 
     } 

// Blue verticle rectangle bottom left 
    for (int i = rows * 6/10; i < rows; i++) 
     for (int j = cols * 0; j < cols * 1/10; j++) 
      blues[i][j] = 0xff; 
} 

void RGB_Allocate(unsigned char**& dude) { 
    dude = new unsigned char*[rows]; 
    for (int i = 0; i < rows; i++) 
     dude[i] = new unsigned char[cols]; 
} 

bool FillAndAllocate(char*& buffer, const char* Picture, int& rows, int& cols, int& BufferSize) { //Returns 1 if executed sucessfully, 0 if not sucessfull 
    std::ifstream file(Picture); 

    if (file) { 
     file.seekg(0, std::ios::end); 
     std::streampos length = file.tellg(); 
     file.seekg(0, std::ios::beg); 

     buffer = new char[length]; 
     file.read(&buffer[0], length); 

     PBITMAPFILEHEADER file_header; 
     PBITMAPINFOHEADER info_header; 

     file_header = (PBITMAPFILEHEADER) (&buffer[0]); 
     info_header = (PBITMAPINFOHEADER) (&buffer[0] + sizeof(BITMAPFILEHEADER)); 
     rows = info_header->biHeight; 
     cols = info_header->biWidth; 
     BufferSize = file_header->bfSize; 
     return 1; 
    } 
    else { 
     cout << "File" << Picture << " don't Exist!" << endl; 
     return 0; 
    } 
} 

void GetPixlesFromBMP24(unsigned char** reds, unsigned char** greens, unsigned char** blues, int end, int rows, int cols, char* FileReadBuffer) { // end is BufferSize (total size of file) 
    int count = 1; 
int extra = cols % 4; // The nubmer of bytes in a row (cols) will be a multiple of 4. 
    for (int i = 0; i < rows; i++){ 
count += extra; 
    for (int j = cols - 1; j >= 0; j--) 
     for (int k = 0; k < 3; k++) { 
       switch (k) { 
       case 0: 
        reds[i][j] = FileReadBuffer[end - count++]; 
        break; 
       case 1: 
        greens[i][j] = FileReadBuffer[end - count++]; 
        break; 
       case 2: 
        blues[i][j] = FileReadBuffer[end - count++]; 
        break; 
       } 
      } 
      } 
} 

void WriteOutBmp24(char* FileBuffer, const char* NameOfFileToCreate, int BufferSize) { 
    std::ofstream write(NameOfFileToCreate); 
    if (!write) { 
     cout << "Failed to write " << NameOfFileToCreate << endl; 
     return; 
    } 
    int count = 1; 
    int extra = cols % 4; // The nubmer of bytes in a row (cols) will be a multiple of 4. 
    for (int i = 0; i < rows; i++){ 
     count += extra; 
     for (int j = cols - 1; j >= 0; j--) 
      for (int k = 0; k < 3; k++) { 
       switch (k) { 
       case 0: //reds 
        FileBuffer[BufferSize - count] = reds[i][j]; 
        break; 
       case 1: //green 
        FileBuffer[BufferSize - count] = greens[i][j]; 
        break; 
       case 2: //blue 
        FileBuffer[BufferSize - count] = blues[i][j]; 
        break; 
       } 
       count++; 
      } 
      } 
    write.write(FileBuffer, BufferSize); 
} 


int main(int args, char** cat) { 
char* FileBuffer; int BufferSize; 

#define Picture "ReadInPicture.bmp" 
if (!FillAndAllocate(FileBuffer, Picture, rows, cols, BufferSize)){cout << "File read error" << endl; return 0;} 
cout << "Rows: " << rows << " Cols: " << cols << endl; 

RGB_Allocate(reds); 
RGB_Allocate(greens); 
RGB_Allocate(blues); 
GetPixlesFromBMP24(reds, greens, blues,BufferSize, rows, cols, FileBuffer); 
ColorTest(); 
#define WriteOutFile "OutputPicture.bmp" 
WriteOutBmp24(FileBuffer, WriteOutFile,BufferSize); 
    return 1; 
} 
संबंधित मुद्दे

 संबंधित मुद्दे