الحصول على قيم RGB لكل بكسل من صورة نقطية 24 بت في الثانية للتحويل إلى تنسيق GBA في C

StackOverflow https://stackoverflow.com/questions/1531268

  •  20-09-2019
  •  | 
  •  

سؤال

أريد قراءة قيم RGB لكل بكسل من ملف .bmp الملف حتى أتمكن من تحويله bmp إلى تنسيق مناسب لـ GBA (GameBoy Advance).

أحتاج إلى الحصول على RGB فقط لكل بكسل ثم كتابة هذه المعلومات في ملف.

أحاول استخدام <windows.h> الهياكل:

typedef struct
{
    char signature[2];
    unsigned int fileSize;
    unsigned int reserved;
    unsigned int offset;
}BmpHeader;

typedef struct
{
    unsigned int headerSize;
    unsigned int width;
    unsigned int height;
    unsigned short planeCount;
    unsigned short bitDepth;
    unsigned int compression;
    unsigned int compressedImageSize;
    unsigned int horizontalResolution;
    unsigned int verticalResolution;
    unsigned int numColors;
    unsigned int importantColors;

}BmpImageInfo;

typedef struct
{
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    unsigned char reserved;
}Rgb;

typedef struct
{
    BmpHeader header;
    BmpImageInfo info;
    Rgb colors[256];
    unsigned short image[1];
}BmpFile;

لكني بحاجة فقط إلى بنية RGB.لنفترض أنني قرأت "in.bmp":

FILE *inFile, *outFile;
inFile = fopen("C://in.bmp", "rb");

Rgb Palette[256];
for(i=0;i<256;i++)
{
   fread(&Palette[i],sizeof(Rgb),1,inFile);
}

fclose(inFile);

هل هذا صحيح؟كيف أكتب معلومات RGB فقط إلى ملف؟

هل كانت مفيدة؟

المحلول

تحتاج أولا إلى الحصول على عدد الألوان المتوفرة في لوحة Embedded. هذا متاح في رأس DIB.

ثم يمكنك قراءة جميع مكونات الألوان التي تحتوي على لوحة.

يمكنك رؤية جميع معلومات الرأس مثل الإزاحة لمعرفة ما تبحث عنه: http://en.wikipedia.org/wiki/bmp_file_format..

يجب أن يعمل هذا: (تحرير: إضافة رمز إلى الكتابة في الملف)

FILE *inFile, *outFile;
BMPHeader header;
BMPImageInfo info;
RGB *palette, *p;
int i = 0;

inFile = fopen("C://in.bmp", "rb");
if( !inFile )
   return;

if( fread(&header, sizeof(BMPHeader), 1, inFile) != 1 )
   return; // Manage error and close file

if( fread&info, sizeof(BMPImageInfo), 1, inFile) != 1 )
   return; // Manage error and close file

if( info.numColors > 0 )
{
   palette = (RGB*)malloc(sizeof(RGB) * info.numColors);
   if( fread(palette, sizeof(RGB), info.numColors, inFile) != info.numColors )
      return; // manage error and close file
}

fclose(inFile)

// Binary method => if read later by another computer
outFile = fopen("path", "wb");
if( !outFile )
   return;

if( fwrite(&info.numColors, sizeof(unsigned int), 1, outFile) != 1 )
   return; // Manage Error and close file

if( fwrite(&palette, sizeof(RGB), info.numColors, outFile) != info.numColors )
   return; // Manage error and close file

fclose(outFile);

// Text method => if read later by human
outFile = fopen("path", "w");
if( !outFile )
   return;

for( i=0; i<info.numColors; ++i )
{
   p = &palette[i];
   if( fprintf(outFile, "R:%d, G:%d, B:%d\n", p->red, p->green, p->blue) < 0 )
      return; // Manage error and close file
}

fclose(outFile);

نصائح أخرى

إذا كنت على Windows، يمكنك استخدام loadbitmap. وظيفة من Win32.

ثم إعطاء المقبض تحويله إلى صورة نقطية DIB والوصول إلى البكسل بهذه الطريقة

فعلت القليل من الاختبار وبرنامج Patrice الموسعة قليلا. أنا لست مبرمج جيد ج جيد، لذلك يذهب جميع الائتمان إليه ولم تكن أجنبي أنيقة مثله - آسف لذلك.

تحذير: شفرة مصدر ضخمة إلى الأمام.

#include <stdio.h>
#pragma pack(2)


typedef struct
{
    char signature[2];
    unsigned int fileSize;
    unsigned int reserved;
    unsigned int offset;
} BmpHeader;

typedef struct
{
    unsigned int headerSize;
    unsigned int width;
    unsigned int height;
    unsigned short planeCount;
    unsigned short bitDepth;
    unsigned int compression;
    unsigned int compressedImageSize;
    unsigned int horizontalResolution;
    unsigned int verticalResolution;
    unsigned int numColors;
    unsigned int importantColors;

} BmpImageInfo;

typedef struct
{
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    //unsigned char reserved; Removed for convenience in fread; info.bitDepth/8 doesn't seem to work for some reason
} Rgb;


int main( int argc, char **argv ) {

    FILE *inFile;
    BmpHeader header;
    BmpImageInfo info;
    Rgb *palette;
    int i = 0;

    printf( "Opening file %s for reading.\n", argv[1] );

    inFile = fopen( argv[1], "rb" );
    if( !inFile ) {
        printf( "Error opening file %s.\n", argv[1] );
        return -1;
    }

    if( fread(&header, 1, sizeof(BmpHeader), inFile) != sizeof(BmpHeader) ) {
        printf( "Error reading bmp header.\n" );
        return -1;
    }

    if( fread(&info, 1, sizeof(BmpImageInfo), inFile) != sizeof(BmpImageInfo) ) {
        printf( "Error reading image info.\n" );
        return -1;
    }

    if( info.numColors > 0 ) {
        printf( "Reading palette.\n" );
        palette = (Rgb*)malloc(sizeof(Rgb) * info.numColors);
        if( fread(palette, sizeof(Rgb), info.numColors, inFile) != (info.numColors * sizeof(Rgb)) ) {
            printf( "Error reading palette.\n" );
            return -1; // error
        }
    }

    printf( "Opening file %s for writing.\n", argv[2] );
    FILE *outFile = fopen( argv[2], "wb" );
    if( !outFile ) {
        printf( "Error opening outputfile.\n" );
        return -1;
    }
    Rgb *pixel = (Rgb*) malloc( sizeof(Rgb) );
    int read, j;
    for( j=0; j<info.height; j++ ) {
        printf( "------ Row %d\n", j+1 );
        read = 0;
        for( i=0; i<info.width; i++ ) {
            if( fread(pixel, 1, sizeof(Rgb), inFile) != sizeof(Rgb) ) {
                printf( "Error reading pixel!\n" );
                return -1;
            }
            read += sizeof(Rgb);
            printf( "Pixel %d: %3d %3d %3d\n", i+1, pixel->red, pixel->green, pixel->blue );
        }
        if( read % 4 != 0 ) {
            read = 4 - (read%4);
            printf( "Padding: %d bytes\n", read );
            fread( pixel, read, 1, inFile );
        }
    }

    printf( "Done.\n" );
    fclose(inFile);
    fclose(outFile);

    printf( "\nBMP-Info:\n" );
    printf( "Width x Height: %i x %i\n", info.width, info.height );
    printf( "Depth: %i\n", (int)info.bitDepth );

    return 0;

}

يقرأ هذا البرنامج معلومات البكسل المخزنة في الملف. يستغرق الحشو في الاعتبار، ولكن يعمل فقط مع BMPs مع BITS مع 24 بت لكل عمق لون بكسل (إذا كنت بحاجة إلى أعماق أخرى، فسيتعين عليك تخصيص بنية RGB). آمل أن يساعدك هذا، ولكن كما قلت، إنه مجرد امتداد لقانون باتريس.

إليك إخراج عينة من TestFile:

$ ./a.out test.bmp out.txt
Opening file test.bmp for reading.
Opening file out.txt for writing.
------ Row 1
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3:   0   0   0
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 2
Pixel 1:   0   0   0
Pixel 2: 232  33  33
Pixel 3:   0   0   0
Pixel 4: 232  33  33
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 3
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3: 232  33  33
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 4
Pixel 1:   0   0   0
Pixel 2: 232  33  33
Pixel 3:   0   0   0
Pixel 4: 232  33  33
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 5
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3:   0   0   0
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
Done.

BMP-Info:
Width x Height: 5 x 5
Depth: 24

تحرير: نعم، صورتي تعرض صليب أحمر. لاحظ أن الصورة مخزنة رأسا على عقب حتى الصف 1 من الملف هو في الواقع صف 5 من الصورة. نسيت أن أكتب شيئا ما لتقديم الشفرة يفتح، ولكن يتم ترك هذا كإزالة لك؛).

إذا كنت مضمونا لأن الصورة النقطية غير المضغوطة 24BPP وعرضها قابل للقسمة بنسبة 4، فهذا أمر بسيط نسبيا:

  1. اقرأ BmpHeader في بداية الملف.
  2. دون البحث، اقرأ BmpImageInfo.
  3. تسعى إلى BmpHeaderoffset بايت من بداية الملف. وبعد لاحظ أنه لا توجد لوحة (على الأقل، وليس المرء الذي نهتم به) في الصور النقطية 24 بت!
  4. قراءة ثلاثة توائم Triplets (في هذا الطلب، وليس هناك reserved عضو غير مستخدم هنا). سيكون هنالك (BmpImageInfoالأعضاء) width * abs(height) ثلاثة توائم. كما أتذكر، إذا height هو إيجابي (الحالة القياسية)، والسطر الأول من اللون الذي تقرأه سيكون هو الأسفل خط الصورة، الصعود من هناك. لو height هو سلبي، على الرغم من أن السطر الأول من اللون في الملف هو أعلى من الصورة، النزول من هناك.

إذا لم تتمكن من تقديم تلك الضمانات، فحصل الأمور على صفقة جيدة أكثر تعقيدا.

إخلاء المسئولية: أنا في تفتيش القرن الخاص بي هنا. منذ سنوات كتبت فائدة صغيرة (ملف مصدر واحد) للقيام بالضبط ما تتحدث عنه، بطريقة محمولة (100٪ ANSI C) بطريقة: glbmp. libbmepread.. وبعد قد يلقي مصدرها بعض الضوء على مشكلتك - إنه يتعامل مع الصور النقطية غير القابلة للالكتب الصغيرة من أي عمق بعض الشيء، ويجب أن تعمل بشكل جيد على GBA.

انظر صفحة ويكيبيديا لتنسيق ملف .bmp الذي يوفر الكثير من المعلومات حول بنية الملف وينبغي أن تساعدك على تحليله.

http://en.wikipedia.org/wiki/bmp_file_format.

في الكود الخاص بك، عليك أولا قراءة عنوان بدء البيانات (المحدد في رأس الملف) وارتفاع الصورة. ثم تسعى إلى هذا الموقف. بعد أن قرأت في صف واحد بكسل بواسطة Pixel (يحدد الرأس عدد البتات لكل بكسل) وعليه العناية بالحصانة 32 بت في نهاية ذلك. لاحظ أنه في صورة 24 بت (RGB) يتم تخزين المعلومات في ترتيب BGR. أيضا إذا كانت قيمة الارتفاع ليست سلبية، يتم تخزين الصورة رأسا على عقب.

لست على دراية بتنسيق ملف BMP، لكن ألا تحتاج إلى قراءة معلومات الرأس أولاً؟شيء مثل:

BmpHeader header;
fread(&header,sizeof(BmpHeader),1,inFile);

واقرأ معلومات الصورة التفصيلية التي ستحتاج إليها:

BmpImageInfo info;
fread(&info,sizeof(BmpImageInfo),1,inFile);

وقراءة المعلومات في لوحة الألوان أيضًا.

بمجرد حصولك على ذلك ستعرف حجم الملف وإزاحة البيانات.يمكنك تخصيص مساحة كافية مسبقًا وقراءة كل شيء مرة واحدة، وهو ما قد يكون أبسط.وبدلاً من ذلك، يمكنك القراءة على أجزاء والتحليل أثناء التقدم (يقلل من فرصة عدم وجود ذاكرة كافية، ولكن التحليل أكثر تعقيدًا).

ستعرف أيضًا من قسم المعلومات ما إذا كان الضغط ممكّنًا، وأبعاد الصورة وما إلى ذلك.

إذا كنت تقرأ كل البيانات مرة واحدة، فانتقل إلى إزاحة البيانات، وافعل شيئًا مثل:

Rgb* rgb = offset;
blueVal = rgb->blue;
greenVal = rgb->green;
redVal = rgb->red;
rgb += sizeof( Rgb );

وما إلى ذلك وهلم جرا.من الواضح أن هذا الرمز لا يتحقق من الأخطاء، ونهاية المخزن المؤقت، وما إلى ذلك، لذلك ستحتاج إلى القيام بذلك.ربما يتعين عليك أيضًا قراءة معلومات اللوحة لفهم بيانات الصورة.

أو، كما قال شخص آخر، انظر إلى مواصفات التنسيق على ويكيبيديا

إذا كان ملف BMP لديه لوحة ثم الرمز أدناه ينبغي الشغل:

  FILE *inFile, *outFile;
  inFile = fopen("C:/in.bmp", "rb");
  Rgb Palette[256];
  if ( inFile ) {
    // Bypass headers
    fseek(inFile, sizeof(BmpHeader) + sizeof(BmpImageInfo), SEEK_SET);
    // Load the whole palette
    fread(Palette, sizeof(Palette), 1, inFile);
    fclose(inFile);
  }

قد تجد أنه من المفيد أن ننظر إلى بعض كود C كتبت منذ سنوات عديدة لقراءة وكتابة ملفات BMP، الموجودة في:

http://david.treble.com/src/bmp/bmp.html.

أعتقد أنه يعالج أحجام البكسل المختلفة (1/2/4/8/24) بالإضافة إلى ضغط RLL.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top