Как выполнить действие 'SKIP'/'SEEK' в libpng с патчем apng

Я пытаюсь портировать libpng/apng на платформу Android, используя libpng с патчем apng для чтения анимированного файла png.

Мой вопрос в том, что я не нашел никакого метода пропуска, объявленного в png.h. То, что я хочу сделать, это как перейти непосредственно к конкретному кадру. Но я не могу получить правильный результат, если я не читаю с самого начала и не выполняю png_read_frame_head() и png_read_image() для каждого кадра впереди.

Есть ли способ, с помощью которого можно перейти к определенному кадру, указав индекс, не прочитав всю информацию о кадре / данные впереди?

Следующий код взят из примера apng http://littlesvr.ca/apng/tutorial/x57.html Вы можете видеть, что он читает файл apng в цикле. И кажется, что вам нужно вызвать png_read_frame_head() и png_read_image(), чтобы обновить внутреннюю информацию в png_ptr_read и info_ptr_read. Итак, если есть какой-либо способ просто изменить эти две структуры, чтобы исправить информацию, подготовленную для чтения конкретного кадра, мой вопрос решен.

for(count = 0; count < png_get_num_frames(png_ptr_read, info_ptr_read); count++)
{
    sprintf(filename, "extracted-%02d.png", count);
    newImage = fopen(filename, "wb");
    if(newImage == NULL)
        fatalError("couldn't create png for writing");

    writeSetup(newImage, &png_ptr_write, &info_ptr_write);
    if(setjmp(png_ptr_write->jmpbuf))
        fatalError("something didn't work, jump 2");

    png_read_frame_head(png_ptr_read, info_ptr_read);

    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_fcTL))
    {
        png_get_next_frame_fcTL(png_ptr_read, info_ptr_read,
                                &next_frame_width, &next_frame_height,
                                &next_frame_x_offset, &next_frame_y_offset,
                                &next_frame_delay_num, &next_frame_delay_den,
                                &next_frame_dispose_op, &next_frame_blend_op);
    }
    else
    {
        /* the first frame doesn't have an fcTL so it's expected to be hidden, 
        * but we'll extract it anyway */
        next_frame_width = png_get_image_width(png_ptr_read, info_ptr_read);
        next_frame_height = png_get_image_height(png_ptr_read, info_ptr_read);
    }

    writeSetup2(png_ptr_read, info_ptr_read, png_ptr_write, info_ptr_write,
                next_frame_width, next_frame_height);

    png_write_info(png_ptr_write, info_ptr_write);

    png_read_image(png_ptr_read, rowPointers);

    png_write_image(png_ptr_write, rowPointers);

    png_write_end(png_ptr_write, NULL);

    png_destroy_write_struct(&png_ptr_write, &info_ptr_write);

    fclose(newImage);

    printf("extracted frame %d into %s\n", count, filename);
}

1 ответ

Ты не можешь libpng был разработан для обработки данных PNG как потока, поэтому он последовательно декодирует фрагменты, один за другим. Не уверен, почему вам нужно пропустить кадры APNG. Как и в видеоформатах, один кадр может быть сохранен как "то, что изменилось после предыдущего кадра", а не как полный кадр, поэтому вам также могут понадобиться предыдущие кадры.

Эти примеры кода могут быть полезны: https://sourceforge.net/projects/apng/files/libpng/examples/

Другие вопросы по тегам