سؤال

لدي مجموعة بايت [] تلقيها في عميل TCP. يحتوي Array على ملف Bitmap RGB 24 بت. كيفية إنشاء ملف صورة نقطية مع عرض معين، الارتفاع والبيانات؟

في C ++ أنا استخدم هذا

int WriteBitmapFile(const char *filename, int width, int height, unsigned char *imageData)
{
FILE             *filePtr;        // file pointer
BITMAPFILEHEADER bitmapFileHeader;    // bitmap file header
BITMAPINFOHEADER bitmapInfoHeader;    // bitmap info header
DWORD                 imageIdx;    // used for swapping RGB->BGR
unsigned char     tempRGB;            // used for swapping

// 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 = 32;                        // 24-bit
bitmapInfoHeader.biCompression = BI_RGB;                // no compression
bitmapInfoHeader.biSizeImage = width * abs(height) * 4;    // 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

// switch the image data from RGB to BGR
for(imageIdx = 0; imageIdx < bitmapInfoHeader.biSizeImage; imageIdx+=4)
{
    tempRGB = imageData[imageIdx];
    imageData[imageIdx] = imageData[imageIdx + 2];
    imageData[imageIdx + 2] = tempRGB;
}

// 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);

// Success
return 1;
}

كيف يمكنني أن أفعل ذلك في C #؟

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

المحلول

إذا كانت الصفيف يحتوي بالفعل على ملف صورة نقطية، فيمكنك فقط حفظ البايت كملف:

File.WriteAllBytes(fileName, imageData);

إذا كان الصفيف يحتوي على بيانات البكسل الخام فقط، فيمكنك إنشاء كائن نقطي باستخدام البيانات:

unsafe {
   fixed (byte* ptr = imageData) {
      using (Bitmap image = new Bitmap(width, height, stride, PixelFormat.Format24bppRgb, new IntPtr(ptr))) {
         image.Save(fileName);
      }
   }
}

ال stride القيمة هي عدد البايتات بين خطوط المسح الضوئي. إذا لم يكن هناك حشوة بين خطوط المسح، فهي width * 3 لتنسيق 24BPP.

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

إذا تم تخزين بيانات الصورة النقطية رأسا على عقب في الصفيف، stride يجب أن تكون القيمة سلبية، وينبغي أن يكون المؤشر هو بداية خط الفحص الأخير في الذاكرة (ptr + stride * (height - 1)).

نصائح أخرى

لا يمكنني اختباره باستخدام الدفق الذي ستتلقى فيه، ولكن هذا يجب أن يعمل.

int WriteBitmapFile(string filename, int width, int height, byte[] imageData)
{
  using (var stream = new MemoryStream(imageData))
  using (var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb))
  {
    BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0,
                                                    bmp.Width,
                                                    bmp.Height),
                                      ImageLockMode.WriteOnly,
                                      bmp.PixelFormat);

    Marshal.Copy(imageData, 0, bmpData.Scan0, imageData.Length);

    bmp.UnlockBits(bmpData);

    bmp.Save(filename);
  }

  return 1;
}

أوصي بإجراء صورة نقطية في C #، واسمحوا ذلك بإنقاذ نفسه.

مثال على سبيل المثال، انظر هذا المشنور. (خاصة، الرد الأخير صحيح.)

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

public Bitmap ShowImage(byte[] sender, EventImageParams e)
    {
        Bitmap bitmap = new Bitmap(e.width, e.height, PixelFormat.Format24bppRgb);
        BitmapData bmData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                            ImageLockMode.ReadWrite, bitmap.PixelFormat);
        IntPtr pNative = bmData.Scan0;

        Marshal.Copy(sender, 0, pNative, (e.width  * e.height * 3));
     //    
        bitmap.UnlockBits(bmData);

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