2012-05-05 3 views
1

Я хочу создать HBITMAP из массива байтов в формате JPEG.Создайте HBITMAP из буфера памяти jpeg?

Я искал, но я могу только создать его из растрового файла в

HBITMAP hbm = (HBITMAP)LoadImage(NULL,"fileName",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION); 

Может кто-то показать мне, как это сделать?

+1

Вы используете библиотеку, такую ​​как MFC? Если это так, вероятно, есть удобный метод, который сделает это для вас легко. В противном случае вам придется написать код. –

+0

да, я использую MFC libary. Пожалуйста, помогите мне. Благодарю. – TTGroup

+1

Насколько я помню, не вся библиотека поддерживает загрузку JPEG, но по крайней мере GDI + делает это –

ответ

4

Просто используйте GDIplus. Он поддерживает загрузку в формате JPEG, а также некоторые другие вещи, чувствует себя гораздо более логично

http://msdn.microsoft.com/en-us/library/ms533830%28v=vs.85%29.aspx

Использование класса «Bitmap». Когда у вас есть jpeg в буфере, вам нужно прочитать его потоком.

+0

Можете ли вы дать мне функцию сделать это? Спасибо! – TTGroup

+2

Изображение :: FromStream(). Те же требования, что и CImage :: Load (IStream) –

2

MFC предоставляет CImage class, который обертывает растровый объект. Он предоставляет удобные методы для загрузки и сохранения изображений в целом ряде форматов, включая JPEG, GIF, BMP и PNG.

Таким образом, первый коммерческий объект получает объект CImage, представляющий ваш HBITMAP. Вы можете сделать это, вызвав Attach method и передав дескриптор.

Но в этом случае вы можете пропустить это полностью и просто иметь объект CImage загрузить ваше изображение из файла напрямую. Используйте для этого Load method.

Как только у вас есть объект CImage, представляющий ваше изображение, просто вызовите метод Save и укажите нужное имя файла с соответствующим расширением. В соответствии с документацией:

Если параметр guidFileType не включен, расширение файла имени файла будет использоваться для определения формата изображения. Если расширение не предусмотрено, изображение будет сохранено в формате BMP.

Пример кода:

CImage img; 
img.Load(TEXT("fileName.bmp")); // load a bitmap (BMP) 
img.Save(TEXT("fileName.jpg")); // and save as a JPEG (JPG) 

Вы также можете изменить эту картину, используя метод Load для загрузки файлов JPEG и Save способ сохранения BMP файлов.

+0

Спасибо, но мне нужно создать HBITMAP из jpeg-буфера (а не из файла). У меня есть буфер jpeg, и я хочу создать HBITMAP из этого буфера. Я не хочу сохранять этот буфер в файл. Спасибо! – TTGroup

+2

Вам необходимо создать IStream, чтобы вы могли использовать метод CImage :: Load (IStream) и загружать изображение из «буфера». Не совсем ясно, как выглядит этот буфер, CImage :: Load может работать только в том случае, если у него есть правильный заголовок файла JPEG. CreateStreamOnHGlobal() является удобной функцией, если буфер был фактически создан с помощью GlobalAlloc(). –

+0

У меня это есть! большое спасибо! – TTGroup

0

Я нашел следующий код // http://katahiromz.web.fc2.com/win32/loadjpeg.html

красный и синий поменялись местами, так вот исправленная версия с цветами исправленных. Он использует jpeglib, поэтому сначала вы должны скомпилировать это. Если вам нужно только преобразовать буфер, вы можете пропустить строку, которая загружает файл - детали конвертации должны быть одинаковыми.

extern "C" {   
#include <jpeglib.h> 
#include <jerror.h> 
} 
#pragma comment(lib, "jpeg.lib") 
HBITMAP LoadJpegAsBitmap(const std::string & filename) 
{ 

    struct jpeg_decompress_struct decomp{}; 
    struct jpeg_error_mgr jerror{}; 
    BITMAPINFO bi = {}; 
    LPBYTE lpBuf, pb = NULL; 
    HBITMAP hbm{}; 
    JSAMPARRAY buffer{}; 
    INT row = 0; 

    decomp.err = jpeg_std_error(&jerror); 
    jpeg_create_decompress(&decomp); 
    FILE* file = fopen(filename.c_str(), "rb"); 
    if (file == nullptr) 
    { 
     return NULL; 
    } 

    jpeg_stdio_src(&decomp, file); 

    jpeg_read_header(&decomp, TRUE); // read jpeg file header 
    jpeg_start_decompress(&decomp); // decompress the file 

    row = ((decomp.output_width * 3 + 3) & ~3); 
    buffer = (*decomp.mem->alloc_sarray)((j_common_ptr)&decomp, JPOOL_IMAGE, 
     row, 1); 

    ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER)); 
    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    bi.bmiHeader.biWidth = decomp.output_width; 
    bi.bmiHeader.biHeight = decomp.output_height; 
    bi.bmiHeader.biPlanes = 1; 
    bi.bmiHeader.biBitCount = 24; 
    bi.bmiHeader.biCompression = BI_RGB; 
    bi.bmiHeader.biSizeImage = row * decomp.output_height; 

    hbm = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&lpBuf, NULL, 0); 
    if (hbm == NULL) 
    { 
     jpeg_destroy_decompress(&decomp); 
     fclose(file); 
     return NULL; 
    } 

    pb = lpBuf + row * decomp.output_height; 
    while (decomp.output_scanline < decomp.output_height) 
    { 
     pb -= row; 
     jpeg_read_scanlines(&decomp, buffer, 1); 

     if (decomp.out_color_components == 1) 
     { 
      UINT i; 
      LPBYTE p = (LPBYTE)buffer[0]; 
      for (i = 0; i < decomp.output_width; i++) 
      {  
       pb[3 * i + 0] = p[i]; 
       pb[3 * i + 1] = p[i]; 
       pb[3 * i + 2] = p[i]; 
      } 
     } 
     else if (decomp.out_color_components == 3) 
     { 
      // There was talk on Internet about one being RGB and another BGR. 
      // If colors appear swapped, then swap the bytes, and update this comment. 
      //CopyMemory(pb, buffer[0], row); 

      // Updated color correction 
      UINT i; 
      LPBYTE p = (LPBYTE)buffer[0]; 
      for (i = 0; i < row; i += 3) 
      { 
       pb[i + 0] = p[i + 2]; // Blue 
       pb[i + 1] = p[i + 1]; // Green 
       pb[i +2] = p[i + 0]; // Red  
      } 
     } 
     else 
     { 
      jpeg_destroy_decompress(&decomp); 
      fclose(file); 
      DeleteObject(hbm); 
      return NULL; 
     } 
    } 

    SetDIBits(NULL, hbm, 0, decomp.output_height, lpBuf, &bi, DIB_RGB_COLORS); 

    jpeg_finish_decompress(&decomp); 
    jpeg_destroy_decompress(&decomp); 

    fclose(file); 

    return hbm; 
} 
Смежные вопросы