С++, jpeglib: Помогите плиз :)

0000

Уже три часа туплю :(
Предыстория.
Хочется грузить jpeg в своей программе для КПК. Т.е. нужна процедурка, получающая на вход имя файла, а на выходе HBITMAP.
Стандартный загрузчик справляется удивительно медленно, потому решил воспользоваться сторонней библиотекой - jpeglib. Поправленные исходники для WinCE нашлись (изменений то 5коп тока вот проблемы с прикручиванием.

extern "C" {
#include "jpeglib/jpeglib.h"
}
...
FILE* pFile = _tfopen(FilePathW, TEXT("rb";
if (pFile == NULL)
return NULL;

struct jpeg_error_mgr jpegErr;
struct jpeg_decompress_struct jpegInfo;

jpegInfo.err = jpeg_std_error(&jpegErr);
jpeg_create_decompress(&jpegInfo);
jpeg_stdio_src(&jpegInfo, pFile);
jpeg_read_header(&jpegInfo, true);
jpeg_start_decompress(&jpegInfo);

int Width = jpegInfo.output_width;
int Height = jpegInfo.output_height;

JSAMPARRAY pBuffer = (*jpegInfo.mem->alloc_sarrayj_common_ptr) & jpegInfo, JPOOL_IMAGE, Width * jpegInfo.output_components, 1);

while (jpegInfo.output_scanline < jpegInfo.output_height)
{
jpeg_read_scanlines(&jpegInfo, pBuffer, 1);
// Здесь хотелось бы получить данные из pBuffer в формате - для каждой точки получить значения R, G и B
}
jpeg_finish_decompress(&jpegInfo);
jpeg_destroy_decompress(&jpegInfo);
fclose(pFile);

JSAMPARRAY определен как

typedef unsigned char JSAMPLE;
typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */
typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */

NataNata

факт, что оно прикручивается. когда-то я такое делал. поищу в старых кодах.
а что, собственно, именно не работает?

0000

Хочется, данные получить в виде RGB-массива. Я просто не пойму как :(

byte R = pBuffer[0][0]
byte G = pBuffer[0][1]
byte B = pBuffer[0][2]

не прокатывает (эксперимент провожу на картинке полностью одного цвета)

lurgi48

как я понимаю двойной массив в результате дает пиксель, вохможно все RGB в один байт запиханы?

lurgi48

Нашел в инете некий jpeglib.h http://www.pocketpcdn.com/articles/jpeglib.html
typedef JSAMPLE FAR *JSAMPROW;	/* ptr to one image row of pixel samples. */
typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */

т.е. JSAMPIMAGE нужен тогда первый(или последний) индекс как раз цвет

/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
EXTERN(JDIMENSION) jpeg_read_raw_data JPPj_decompress_ptr cinfo,
JSAMPIMAGE data,
JDIMENSION max_lines;

0000

Это она. Ее можно отчасти стандартом считать (не развивается с 1998года, т.е. весь формат jpeg реализует видимо).
В один байт запихать RGB невероятно - это всего 256 цветов получается. Просто может я не так что понял и там структура похитрее возвращается :(

lurgi48

Просто может я не так что понял и там структура похитрее возвращается
второй пост написана функция которую можно использовать для получения RAW данных

0000

RAW данные это не RGB мне кажется. Обычно используют ту, что я написал. Просто мне не просто надо закопировать данные, а перекинуть их в уже имеющуюся 16-ти битную структуру для вывода на экран.
P.S. Статью видел.

lurgi48

RAW данные это не RGB мне кажется.
ну если raw имеется в виду раскодированные то имхо как раз rgb.
я бы попробовал

0000

Вообщем почти подкрался к реализации

...
jpeg_start_decompress(&jpegInfo);

int Width = jpegInfo.output_width;
int Height = jpegInfo.output_height;

BYTE* RGBData = (BYTE*) new BYTE[Width * 3 * Height];
JSAMPARRAY Buffer = (*jpegInfo.mem->alloc_sarrayj_common_ptr) &jpegInfo, JPOOL_IMAGE, Width * jpegInfo.output_components, 1);

while (jpegInfo.output_scanline < Height && jpegInfo.output_components == 3)
{
(void) jpeg_read_scanlines(&jpegInfo, Buffer, 1);
int offset = (jpegInfo.output_scanline - 1) * Width * 3;
for (int Count = 0; Count < Width; Count++)
{
*(RGBData + offset + Count * 3 + 0) = *(Buffer[0] + Count * 3 + 0);
*(RGBData + offset + Count * 3 + 1) = *(Buffer[0] + Count * 3 + 1);
*(RGBData + offset + Count * 3 + 2) = *(Buffer[0] + Count * 3 + 2);
}
}

Беда в том, что получается BGR набор (излечимо просто) и перевернутая картинка (то ж излечимо, тока не совсем понятно как просто сделать).
Код своровал отсюда - http://www.gamedev.ru/code/forum/?id=51252

0000

Тайна Египетских пирамид раскрыта. Вот собственно искомый код

...
jpeg_start_decompress(&jpegInfo);

int Width = jpegInfo.output_width;
int Height = jpegInfo.output_height;

BYTE* RGBData = (BYTE*) new BYTE[Width * 3 * Height];
JSAMPARRAY Buffer = (*jpegInfo.mem->alloc_sarrayj_common_ptr) &jpegInfo, JPOOL_IMAGE, Width * jpegInfo.output_components, 1);

while (jpegInfo.output_scanline < Height && jpegInfo.output_components == 3)
{
(void) jpeg_read_scanlines(&jpegInfo, Buffer, 1);
int offset = (Height - jpegInfo.output_scanline - 1) * Width * 3;
for (int Count = 0; Count < Width; Count++)
{
*(RGBData + offset + Count * 3 + 2) = *(Buffer[0] + Count * 3 + 0);
*(RGBData + offset + Count * 3 + 1) = *(Buffer[0] + Count * 3 + 1);
*(RGBData + offset + Count * 3 + 0) = *(Buffer[0] + Count * 3 + 2);
}
}

:)

lurgi48

В виндоуззз (да и наверно не только) стандартные картинки всегда храняться в bgr формате и в системе координат, где вертикальная ось направлена вверх, т.е. против пикселей. Поэтому стандартные средства вывода изображений в виндоуз правильно отображают такие картинки.
Ну и еще если у тебя width не кратно 4, то могут быть проблемы, потому что общепринято, что размер строчки изображения доводится до кратного 4м пустыми байтами.

0000

BGR и ориентация только к bmp-формату вроде как относится.
Выравнивание уже есть, в модуле отвечающим выводом на экран.

lurgi48

BGR и ориентация только к bmp-формату вроде как относится.
Выравнивание уже есть, в модуле отвечающим выводом на экран.
Ну модули вывода на экран обычно такой формат и требуют, так что переводить и переворачивать имхо лишнее. Про выравнивание не знаю, в обычной винде приходилось самостоятельно об этом думать.

vall

у жпега в хедерах нет флагов поворота?

0000

У меня не стандартный вывод на экран (GDI на КПК это убийство, потому приходится использовать библиотеки с непосредственным доступом к видеопамяти - GAPI/PocketHAL. Я разумеется враппер чужой использую, который может любую из двух использовать).
2
Может и есть :) Я проблему у себя решил, просто числа переставив.

0000

Кстати, а никто не знает как отлавливать ошибки, возникающие при вызове jpeg-функций? Че та там какой то менеджер ошибок...

vall

а ты не мог тупо поискать код который эту либу использует, раз уж документации нет?

0000

Документация есть, тока там слишком много курить надо :(
Эту либу ругают за то, что она сложная для новичков (к коим я себя отношу).
Код поискал. Ни в одном обработок ошибок не нашел. а что есть - только инициализация менеджера ошибок.
Кстати говоря, скорость загрузки jpeg на порядок выше чем стандартной функцией SHLoadImageFile :)

0000

Видимо опять сам разобрался (скопировал с исходников HaaliReader). Вот что получилось

...
struct my_error_mgr
{
struct jpeg_error_mgr pub;
jmp_buf jb;
};

METHODDEF(void) je_error_exit(j_common_ptr cinfo) {
my_error_mgr *mgr=(my_error_mgr*)cinfo->err;
(*cinfo->err->output_message) (cinfo);
jpeg_destroy(cinfo);
longjmp(mgr->jb,1);
}
...
struct my_error_mgr jpegErr;
struct jpeg_decompress_struct jpegInfo;

jpegInfo.err = jpeg_std_error(&jpegErr.pub);
jpegErr.pub.error_exit = je_error_exit;
if (setjmp(jpegErr.jb
{
return NULL;
}
jpeg_create_decompress(&jpegInfo);

Если кто то пояснит, как это работает - буду благодарен.
Оставить комментарий
Имя или ник:
Комментарий: