Конвертация изображений из формата RAW в JPEG
Модераторы: Duncon, Hawk, Romeo, Eugie
Всем привет. Сможет ли кто подсказать, как мне в своей программе сконвертировать файлы изображений оригинальных RAW-форматов цифровых камер Canon, Nikon, Sony и др. в обычный формат типа JPEG? Желательно чтобы можно было ещё задавать размер изображения на выходе.
Поумнеть несложно, куда труднее от дури избавиться.
Различия RAW формата камер разных производителей настолько велики, что единой спецификации не существует. Даже не залезая в гугл я могу по пальцам сосчитать с десяток различных спецификаций RAW, хотя по факту их намного больше. Компания Adobe предложила производителям единый формат DNG, но пока что поддержка этого формата наблюдается у 5-7 фотиков. Если "своя программа" не является конвертером графических файлов, то писать собственные фильтры - не к чему. Стоит воспользоваться технологией плагинов для любого более-менее популярного редактора или вьювера. Как правило плагин - это DLL с парой/тройкой экспортируемых функций, служащих для перевода данных из одного формата в другой. Подключив их к своей программе и зная декларацию этих функций можно получить полноценную конвертацию
It's a long way to the top if you wanna rock'n'roll
Это можно сделать достаточно легко с помощью системного интерфейса ITranscodeImage и нескольких вспомогательных функций Shell API. Данный интерфейс имеет метод
TranscodeImage, у которого на выходе будет изображение в формате Bitmap или JPEG. На входе у него может быть любой файл графического формата, который поддерживается Windows. Что же касается RAW-файлов с цифровых фотокамер, то для них нужно устанавливать специальный пакет кодеков, он так и называется: Microsoft camera codec pack http://www.microsoft.com/ru-ru/download ... x?id=26829
Скачиваешь его, устанавливаешь и Windows после этого сможет работать с данными форматами файлов. Для Windows 8 ничего дополнительно устанавливать не нужно, там эти компоненты уже присутствуют.
TranscodeImage, у которого на выходе будет изображение в формате Bitmap или JPEG. На входе у него может быть любой файл графического формата, который поддерживается Windows. Что же касается RAW-файлов с цифровых фотокамер, то для них нужно устанавливать специальный пакет кодеков, он так и называется: Microsoft camera codec pack http://www.microsoft.com/ru-ru/download ... x?id=26829
Скачиваешь его, устанавливаешь и Windows после этого сможет работать с данными форматами файлов. Для Windows 8 ничего дополнительно устанавливать не нужно, там эти компоненты уже присутствуют.
Дистрибутив с кодеками я скачал, установил. Теперь изображения с фотокамер просматриваются штатными просмотрщиками Windows и в файловом проводнике отображаются в виде миниатюрных картинок. А вот как мне теперь их сконвертировать в JPEG? Имеется ли какой-нибудь простой пример использования интерфейса ITranscodeImage для преобразования картинок?
Поумнеть несложно, куда труднее от дури избавиться.
Тогда уж не забудь распространять его в составе своей программы.Дистрибутив с кодеками я скачал, установил
Что-то не нашел. Стоит подумать о целесообразности использования метода, который не используют другие программисты. Особенно, если от пользователя потребуется установка дополнительных компонент. Будет проще использовать LibRaw (http://www.libraw.su).Имеется ли какой-нибудь простой пример использования интерфейса ITranscodeImage для преобразования картинок?
It's a long way to the top if you wanna rock'n'roll
Могу предложить уже готовый вариант функции с использованием этого интерфейса.
В параметры функции передаёшь имя входного файла, потом имя выходного файла, максимальную ширину и максимальную высоту изображения. При масштабировании картинки сохраняются её пропорции.
Поскольку функция использует СОМ-интерфейсы, то в клиентском приложении нужно будет вызвать функции CoInitialize() и CoUninitialize(); Вот примерно так...
Входные параметры функции в данном примере я захардкодил для наглядности, но в реальном проекте можешь получать их из командной строки через параметры argv[1], argv[2], и т.д.
Код: Выделить всё
#include "stdafx.h"
#include <Shlobj.h>
#include <ImageTranscode.h>
HRESULT TranscodeImage(LPCTSTR szFileIn, LPCTSTR szFileOut, UINT uiWidth, UINT uiHeight)
{
// Полный путь к файлу...
TCHAR szFullPath[MAX_PATH] = _T("");
::GetFullPathName(szFileIn, _countof(szFullPath), szFullPath, NULL);
// Создание ShellItem
HRESULT hr = E_INVALIDARG;
CComPtr<IShellItem> pShellItem;
hr = ::SHCreateItemFromParsingName(szFullPath, NULL, IID_IShellItem, (LPVOID*)&pShellItem);
if (pShellItem != NULL)
{
// Удаление существующего файла
if (::PathFileExists(szFileOut))
{
: :D eleteFile(szFileOut);
}
// Поток записи данных...
CComPtr<IStream> pStream;
hr = ::SHCreateStreamOnFileEx(szFileOut, STGM_WRITE, 0, TRUE, NULL, &pStream);
if (pStream != NULL)
{
// Транскодинг изображения...
CComPtr<ITranscodeImage> pTranscoder;
hr = pTranscoder.CoCreateInstance(__uuidof(ImageTranscode));
if (pTranscoder != NULL)
{
hr = pTranscoder->TranscodeImage(pShellItem, uiWidth, uiHeight, TI_JPEG, pStream, NULL, NULL);
}
}
}
return hr;
}
Поскольку функция использует СОМ-интерфейсы, то в клиентском приложении нужно будет вызвать функции CoInitialize() и CoUninitialize(); Вот примерно так...
Код: Выделить всё
struct CO_INITIALIZE
{
CO_INITIALIZE()
{
::CoInitialize(NULL);
}
~CO_INITIALIZE()
{
::CoUninitialize();
}
} co_init;
int _tmain(int argc, _TCHAR* argv[])
{
LPCTSTR szInputFile = _T("IMG_1234.NEF"); // Камера NIKON
// Перекодирование изображения...
HRESULT hr = TranscodeImage(szInputFile, _T("output.jpg"), 1200, 800);
if (SUCCEEDED(hr))
{
_tcprintf(_T("%s\n"), _T("Завершено успешно."));
} else
{
_tcprintf(_T("%s\n"), _T("Возникла ошибка."));
}
_gettch();
return 0;
}
Входные параметры функции в данном примере я захардкодил для наглядности, но в реальном проекте можешь получать их из командной строки через параметры argv[1], argv[2], и т.д.
Вот не пойму, зачем нужно было в TranscodeImage делать ShellItem, а не Stream? При том, что вывод идет в Stream - в чем логика?
It's a long way to the top if you wanna rock'n'roll
А ведь и правда всё отлично работает!
Одна небольшая функция, набор кодеков - и вот тебе готовый конвертор.
WinMain, спасибо огромное!
Одна небольшая функция, набор кодеков - и вот тебе готовый конвертор.
WinMain, спасибо огромное!
Поумнеть несложно, куда труднее от дури избавиться.
Через IStream на входе можно получить лишь поток бинарных данных из файла, но при этом не будет никакой информации о том, что это за файл и как с ним работать.somewhere писал(а):Вот не пойму, зачем нужно было в TranscodeImage делать ShellItem, а не Stream? При том, что вывод идет в Stream - в чем логика?
Вся сопутствующая информация о типе данного файла (определяется по расширению файла) содержится в системном реестре. Там же содержится информация и о том, какие программные компоненты нужны для работы с данным типом файла. Ну а для сохранения в файл перекодированного изображения требуется только открытый на запись файловый поток и ничего больше.