Сохранение битмапа - еще короче !!!
От: Hollander Беларусь http://blogs.rsdn.org/ikemefula
Дата: 29.11.01 19:09
Оценка: 13 (4)
Привет !

Откопал случайно в заголовочном файле функцию. В MSDN у меня недокументировано ничего — апрельский этого года. А заголовочный файл от 4.24.98 !!!

Эта функция может, по идее, сохранять все то, что загружает OleLoadPicture — BMP, GIF, JPEG, ICO, WMF, и EMF



WINOLECTLAPI OleSavePictureFile(LPDISPATCH lpdispPicture,
    BSTR bstrFileName);


итак :


BOOL SaveBitmap(HBITMAP hBitmap,HPALETTE hPal,LPCTSTR szPath)
{
    PICTDESC pDesc;
    
    pDesc.cbSizeofstruct = sizeof(PICTDESC);
    pDesc.bmp.hbitmap = hBitmap;
    pDesc.bmp.hpal = hPal;
    pDesc.picType =  PICTYPE_BITMAP;

    return SavePictureIndirect(pDesc,szPath);
}

BOOL SavePictureIndirect(PICTDESC pDesc,LPCTSTR szPath)
{
    IPicture* pPicture = NULL;
    BOOL bResult = TRUE;

    OleCreatePictureIndirect(&pDesc,&IID_IPicture,FALSE,(void**)&pPicture);
    if(pPicture == NULL)
        bResult = FALSE;
    else
        bResult = SavePicture(pPicture,szPath);
    if(pPicture != NULL)
        pPicture->lpVtbl->Release(pPicture);
    return bResult;
}


BOOL SavePicture(IPicture* pPicture,LPCTSTR szPath)
{
    HRESULT hr;
    int size = strlen(szPath);
    BSTR bstrPath = SysAllocStringByteLen(szPath,size*2);

    MultiByteToWideChar(CP_ACP,0,szPath,size, bstrPath, size*2);


    hr = OleSavePictureFile((LPDISPATCH)pPicture,bstrPath);

    SysFreeString(bstrPath);

    return SUCCEEDED(hr);
}
Re: Сохранение битмапа - еще короче !!!
От: Alex Fedotov США  
Дата: 29.11.01 19:27
Оценка: +1
Здравствуйте Hollander, Вы писали:

H>Привет !


H>Откопал случайно в заголовочном файле функцию. В MSDN у меня недокументировано ничего — апрельский этого года. А заголовочный файл от 4.24.98 !!!


H>Эта функция может, по идее, сохранять все то, что загружает OleLoadPicture — BMP, GIF, JPEG, ICO, WMF, и EMF



H>WINOLECTLAPI OleSavePictureFile(LPDISPATCH lpdispPicture,
H>    BSTR bstrFileName);


H>итак :


И опять есть к чему придраться.

H>BOOL SaveBitmap(HBITMAP hBitmap,HPALETTE hPal,LPCTSTR szPath)
H>{
H>    PICTDESC pDesc;
H>    
H>    pDesc.cbSizeofstruct = sizeof(PICTDESC);
H>    pDesc.bmp.hbitmap = hBitmap;
H>    pDesc.bmp.hpal = hPal;
H>    pDesc.picType =  PICTYPE_BITMAP;

H>    return SavePictureIndirect(pDesc,szPath);
H>}

H>BOOL SavePictureIndirect(PICTDESC pDesc,LPCTSTR szPath)
H>{
H>    IPicture* pPicture = NULL;
H>    BOOL bResult = TRUE;

H>    OleCreatePictureIndirect(&pDesc,&IID_IPicture,FALSE,(void**)&pPicture);
H>    if(pPicture == NULL)
H>        bResult = FALSE;
H>    else
H>        bResult = SavePicture(pPicture,szPath);

// Возможно, это дело вкуса, но я не понимаю, зачем еще раз проверять 
// pPicture на NULL, когда мы только что это сделали. Впрочем, оптимизатор
// должен разобраться и сделать как надо.

H>    if(pPicture != NULL)
H>        pPicture->lpVtbl->Release(pPicture);
H>    return bResult;
H>}


H>BOOL SavePicture(IPicture* pPicture,LPCTSTR szPath)
H>{
H>    HRESULT hr;

// Вот здесь начинается что-то странное. На вход дается строка LPCTSTR, 
// ее длина определяется с помощью strlen, что не будет компилироваться
// в Unicode. Кроме того, вызов MultiByteToWideChar нужен только в
// Unicode-компиляции, а вместо SysAllocStringByteLen стоит использоват
// SysAllocStringLen.
//
// Проверку на успешность выделения памяти тоже не мешает добавить.

H>    int size = strlen(szPath);
H>    BSTR bstrPath = SysAllocStringByteLen(szPath,size*2);

// Последний параметр для MultiByteToWideChar указан неправильно. Это 
// количество символов, так что умножать на два не надо.

H>    MultiByteToWideChar(CP_ACP,0,szPath,size, bstrPath, size*2);

// В итоге получается

#ifdef _UNICODE
        BSTR bstrPath = SysAllocString(szPath);
        if (bstrPath == NULL)
            return FALSE;
#else
        int len = ltrlenA(szPath);
        BSTR bstrPath = SysAllocStringLen(NULL, len);
        if (bstrPath == NULL)
            return FALSE;

        MultiByteToWideChar(CP_ACP, 0, szPath, -1, bstrPath, len + 1);
#endif

H>    hr = OleSavePictureFile((LPDISPATCH)pPicture,bstrPath);

H>    SysFreeString(bstrPath);

H>    return SUCCEEDED(hr);
H>}
-- Alex Fedotov
Re[2]: Сохранение битмапа - еще короче !!!
От: Hollander Беларусь http://blogs.rsdn.org/ikemefula
Дата: 30.11.01 07:29
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>И опять есть к чему придраться.


А кроме этого тичего не можешь сказать ? Оцени решение — стоит ли пользоваться и насколько универсально оно.
Этот код я набрал только для того, чтобы проверить. Наспех — потому и коряво. А проверки лишние — это другойй код совсем был — кое-что забыл убрать.
Re[3]: Сохранение битмапа - еще короче !!!
От: Alex Fedotov США  
Дата: 30.11.01 08:08
Оценка:
Здравствуйте Hollander, Вы писали:

H>А кроме этого тичего не можешь сказать ? Оцени решение — стоит ли пользоваться и насколько универсально оно.


Вот так значит вопрос стоит. Я не знаю, я начал бы пользоваться, посмотрел бы, как эта функция ведет себя в разных ситуациях. Например, как она сохраняет DIB sections. Надеюсь, она не пытается привести их к формату экрана?

H>Этот код я набрал только для того, чтобы проверить. Наспех — потому и коряво. А проверки лишние — это другойй код совсем был — кое-что забыл убрать.


Предупреждать надо.
-- Alex Fedotov
Re[4]: Сохранение битмапа - еще короче !!!
От: Hollander Беларусь http://blogs.rsdn.org/ikemefula
Дата: 30.11.01 08:16
Оценка:
Здравствуйте Alex Fedotov, Вы писали:


AF>Вот так значит вопрос стоит. Я не знаю, я начал бы пользоваться, посмотрел бы, как эта функция ведет себя в разных ситуациях. Например, как она сохраняет DIB sections. Надеюсь, она не пытается привести их к формату экрана?


А как это проверить можно ?
Re[5]: Сохранение битмапа - еще короче !!!
От: Alex Fedotov США  
Дата: 30.11.01 08:19
Оценка:
Здравствуйте Hollander, Вы писали:

AF>>Вот так значит вопрос стоит. Я не знаю, я начал бы пользоваться, посмотрел бы, как эта функция ведет себя в разных ситуациях. Например, как она сохраняет DIB sections. Надеюсь, она не пытается привести их к формату экрана?


H>А как это проверить можно ?


Сделать DIB-секцию, формат которой (глубина цвета) не совпадает с форматом экрана, и сохранить с помощью этой функции. А потом посмотреть, сколько цветов получилось в файле.
-- Alex Fedotov
Re[6]: Сохранение битмапа - еще короче !!!
От: Hollander Беларусь http://blogs.rsdn.org/ikemefula
Дата: 30.11.01 08:55
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

H>>А как это проверить можно ?


AF>Сделать DIB-секцию, формат которой (глубина цвета) не совпадает с форматом экрана, и сохранить с помощью этой функции. А потом посмотреть, сколько цветов получилось в файле.


Эта функция работает с IPicture* . Dib создастся чз OleCreatePictureIndirect — здесь могут быть проблемы.
Re[7]: Сохранение битмапа - еще короче !!!
От: Alex Fedotov США  
Дата: 30.11.01 08:58
Оценка:
Здравствуйте Hollander, Вы писали:

AF>>Сделать DIB-секцию, формат которой (глубина цвета) не совпадает с форматом экрана, и сохранить с помощью этой функции. А потом посмотреть, сколько цветов получилось в файле.


H>Эта функция работает с IPicture* . Dib создастся чз OleCreatePictureIndirect — здесь могут быть проблемы.


Вот как раз эти проблемы и хотелось бы изучить.
-- Alex Fedotov
Re[8]: Сохранение битмапа - еще короче !!!
От: Hollander Беларусь http://blogs.rsdn.org/ikemefula
Дата: 30.11.01 09:10
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>>>Сделать DIB-секцию, формат которой (глубина цвета) не совпадает с форматом экрана, и сохранить с помощью этой функции. А потом посмотреть, сколько цветов получилось в файле.


H>>Эта функция работает с IPicture* . Dib создастся чз OleCreatePictureIndirect — здесь могут быть проблемы.


AF>Вот как раз эти проблемы и хотелось бы изучить.


Проверил — сграбил экран в клипборд — потом в файл — стало TrueColor (хотя экран 16 бит)
Потом вырезал из Паинта монохромное — все кул — сохранил как монохром
Re[2]: Сохранение битмапа - еще короче !!!
От: scopr21  
Дата: 30.11.01 09:14
Оценка:
Здравствуйте Alex Fedotov, Вы писали:


WINOLECTLAPI OleSavePictureFile(LPDISPATCH lpdispPicture, BSTR bstrFileName);




H>>BOOL SavePictureIndirect(PICTDESC pDesc,LPCTSTR szPath)
H>>{
H>>    IPicture* pPicture = NULL;
H>>    BOOL bResult = TRUE;

H>>    OleCreatePictureIndirect(&pDesc,&IID_IPicture,FALSE,(void**)&pPicture);
H>>    if(pPicture == NULL)
H>>        bResult = FALSE;
H>>    else
H>>        bResult = SavePicture(pPicture,szPath);

H>>    if(pPicture != NULL)
H>>        pPicture->lpVtbl->Release(pPicture);
H>>    return bResult;
H>>}


Чего-то я недопонял. В описании функции — 2 параметра, при вызове — 3
All we are is dust in the wind...
Re[3]: Сохранение битмапа - еще короче !!!
От: Alex Fedotov США  
Дата: 30.11.01 09:19
Оценка:
Здравствуйте scopr21, Вы писали:

S>WINOLECTLAPI OleSavePictureFile(LPDISPATCH lpdispPicture, BSTR bstrFileName);


H>>>BOOL SavePictureIndirect(PICTDESC pDesc,LPCTSTR szPath)
H>>>{
H>>>    IPicture* pPicture = NULL;
H>>>    BOOL bResult = TRUE;

H>>>    OleCreatePictureIndirect(&pDesc,&IID_IPicture,FALSE,(void**)&pPicture);
H>>>    if(pPicture == NULL)
H>>>        bResult = FALSE;
H>>>    else
H>>>        bResult = SavePicture(pPicture,szPath);

H>>>    if(pPicture != NULL)
H>>>        pPicture->lpVtbl->Release(pPicture);
H>>>    return bResult;
H>>>}


S>Чего-то я недопонял. В описании функции — 2 параметра, при вызове — 3


Почему же три? Четыре! Hint: это разные функции.
-- Alex Fedotov
Re[4]: Сохранение битмапа - еще короче !!!
От: scopr21  
Дата: 30.11.01 09:40
Оценка: +1
AF>Почему же три? Четыре! Hint: это разные функции.
Сорри, я гоню
All we are is dust in the wind...
Re: Сохранение битмапа - еще короче !!!
От: MaxS Удмуртия http://www.sautin.com
Дата: 26.06.03 15:11
Оценка:
Здравствуйте, Hollander, Вы писали:

H>Привет !


H>Откопал случайно в заголовочном файле функцию. В MSDN у меня недокументировано ничего — апрельский этого года. А заголовочный файл от 4.24.98 !!!


H>Эта функция может, по идее, сохранять все то, что загружает OleLoadPicture — BMP, GIF, JPEG, ICO, WMF, и EMF


Да, функция достаточна интересная, мне как раз нужно что-то подобное. Мне необходимо открыть gif или jpg и сохранить в wmf.

Как можно это сделать с помощью OleLoadPicture и OleSavePictureFile?
Трудно ничего не делать, но мы не боимся трудностей.
Re[2]: Сохранение битмапа - еще короче !!!
От: algol Россия about:blank
Дата: 27.06.03 23:21
Оценка: 2 (1)
Здравствуйте, MaxS, Вы писали:

MS>Да, функция достаточна интересная, мне как раз нужно что-то подобное. Мне необходимо открыть gif или jpg и сохранить в wmf.


MS>Как можно это сделать с помощью OleLoadPicture и OleSavePictureFile?


А никак. OleSavePictureFile сохраняет только в BMP. А чтобы сконвертить GIF или JPG в WMF можно например пойти на CodeProject и взять там CxImage class.
Re[3]: Сохранение битмапа - еще короче !!!
От: MaxS Удмуртия http://www.sautin.com
Дата: 28.06.03 03:44
Оценка:
Здравствуйте, algol

А какова глубина цвета будет в BMP при использовании OleSavePictureFile , если gif был 256 цветов?
Трудно ничего не делать, но мы не боимся трудностей.
Re[3]: Сохранение битмапа - еще короче !!!
От: Блудов Павел Россия  
Дата: 30.06.03 01:44
Оценка:
Господа, чего вы так носитесь с этой ::OleSavePictureFile()?
У объекта IPicture есть интерфейс IPersistStream (причем IPersist'а нету!)
В MSDN об этом четко и ясно написано:

[msdn]
The picture object also supports IPersistStream so it can save and load itself from an instance of IStream. An object that uses a picture object internally would normally save and load the picture as part of the object's own persistence handling. The function OleLoadPicture simplifies the creation of a picture object based on stream contents.
[/msdn]

Здравствуйте, algol, Вы писали:
A>OleSavePictureFile сохраняет только в BMP.

А знаете почему? Потому что ::OleSavePictureFile()
просто вызывает IPicture::SaveAsFile() на потоке,
созданном с файла. И тут возможны только BMP и WMF

Вот если бы она использовала для этого интерфейс IPersistStream,
то формат зависел бы от свойства IPicture::KeepOriginalFormat().
Если оно выставлено в true, то картитка будет созранена
в том формате, в каком она была до загрузки.

Другое дело, что если при объект IPicture создавался с BMP,
то его можно сохранить только в BMP. Пожать в GIF не получится.

Павел.
Re[2]: Сохранение битмапа - еще короче !!!
От: Vinni-puh Россия  
Дата: 29.04.04 11:32
Оценка:
Несколько замечаний к приведённому коду:
1. Не знаю, как в других компиляторах, а в VC 2003 атрибута lpVtbl нет.
2. Такой функции как ltrlenA я не нашёл.
В итоге, код, котовый к вставке в программу (проверено на VC 2003, он же 7.1):

BOOL SaveBitmap(HBITMAP hBitmap,HPALETTE hPal,LPCTSTR szPath)
{ PICTDESC pDesc;
  pDesc.cbSizeofstruct = sizeof(PICTDESC);
  pDesc.bmp.hbitmap = hBitmap;
  pDesc.bmp.hpal = hPal;
  pDesc.picType =  PICTYPE_BITMAP;
  return SavePictureIndirect(pDesc,szPath);
}
BOOL SavePictureIndirect(PICTDESC pDesc,LPCTSTR szPath)
{ IPicture* pPicture = NULL;
  BOOL bResult = TRUE;
  OleCreatePictureIndirect(&pDesc,IID_IPicture,FALSE,(void**)&pPicture);
  if(pPicture == NULL) bResult = FALSE;
    else bResult = SavePicture(pPicture,szPath);
  if(pPicture != NULL) pPicture->Release();
  return bResult;
}
BOOL SavePicture(IPicture* pPicture,LPCTSTR szPath)
{ HRESULT hr; int size = strlen(szPath);
 #ifdef _UNICODE
  BSTR bstrPath = SysAllocString(szPath);
  if (bstrPath == NULL) return FALSE;
 #else
  int len = strlen(szPath);
  BSTR bstrPath = SysAllocStringLen(NULL, len);
  if (bstrPath == NULL) return FALSE;
  MultiByteToWideChar(CP_ACP, 0, szPath, -1, bstrPath, len + 1);
 #endif
  hr = OleSavePictureFile((LPDISPATCH)pPicture,bstrPath);
  SysFreeString(bstrPath);
  return SUCCEEDED(hr);
}

Можно вызвать SaveBitmap, положив hPal=NULL, в этом случае будет использована палитра экрана.
Re[3]: Сохранение битмапа - еще короче !!!
От: Plutonia Experiment Беларусь http://blogs.rsdn.org/ikemefula
Дата: 30.04.04 10:35
Оценка:
Здравствуйте, Vinni-puh, Вы писали:

VP>Несколько замечаний к приведённому коду:

VP>1. Не знаю, как в других компиляторах, а в VC 2003 атрибута lpVtbl нет.

Это для языка С, а не С++. Сделай расширение файла С и все пучком.

VP>2. Такой функции как ltrlenA я не нашёл.


Это обычный lstrlen.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.