static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
                                   opj_stream_private_t *stream,
                                   opj_event_mgr_t * p_manager
                                  )
{
    opj_jp2_img_header_writer_handler_t l_writers [4];
    opj_jp2_img_header_writer_handler_t * l_current_writer;

    OPJ_INT32 i, l_nb_pass;
    /* size of data for super box*/
    OPJ_UINT32 l_jp2h_size = 8;
    OPJ_BOOL l_result = OPJ_TRUE;

    /* to store the data of the super box */
    OPJ_BYTE l_jp2h_data [8];

    /* preconditions */
    assert(stream != 00);
    assert(jp2 != 00);
    assert(p_manager != 00);

    memset(l_writers, 0, sizeof(l_writers));

    if (jp2->bpc == 255) {
        l_nb_pass = 3;
        l_writers[0].handler = opj_jp2_write_ihdr;
        l_writers[1].handler = opj_jp2_write_bpcc;
        l_writers[2].handler = opj_jp2_write_colr;
    } else {
        l_nb_pass = 2;
        l_writers[0].handler = opj_jp2_write_ihdr;
        l_writers[1].handler = opj_jp2_write_colr;
    }

    if (jp2->color.jp2_cdef != NULL) {
        l_writers[l_nb_pass].handler = opj_jp2_write_cdef;
        l_nb_pass++;
    }

    /* write box header */
    /* write JP2H type */
    opj_write_bytes(l_jp2h_data + 4, JP2_JP2H, 4);

    l_current_writer = l_writers;
    for (i = 0; i < l_nb_pass; ++i) {
        l_current_writer->m_data = l_current_writer->handler(jp2,
                                   &(l_current_writer->m_size));
        if (l_current_writer->m_data == 00) {
            opj_event_msg(p_manager, EVT_ERROR,
                          "Not enough memory to hold JP2 Header data\n");
            l_result = OPJ_FALSE;
            break;
        }

        l_jp2h_size += l_current_writer->m_size;
        ++l_current_writer;
    }

    if (! l_result) {
        l_current_writer = l_writers;
        for (i = 0; i < l_nb_pass; ++i) {
            if (l_current_writer->m_data != 00) {
                opj_free(l_current_writer->m_data);
            }
            ++l_current_writer;
        }

        return OPJ_FALSE;
    }

    /* write super box size */
    opj_write_bytes(l_jp2h_data, l_jp2h_size, 4);

    /* write super box data on stream */
    if (opj_stream_write_data(stream, l_jp2h_data, 8, p_manager) != 8) {
        opj_event_msg(p_manager, EVT_ERROR,
                      "Stream error while writing JP2 Header box\n");
        l_result = OPJ_FALSE;
    }

    if (l_result) {
        l_current_writer = l_writers;
        for (i = 0; i < l_nb_pass; ++i) {
            if (opj_stream_write_data(stream, l_current_writer->m_data,
                                      l_current_writer->m_size, p_manager) != l_current_writer->m_size) {
                opj_event_msg(p_manager, EVT_ERROR,
                              "Stream error while writing JP2 Header box\n");
                l_result = OPJ_FALSE;
                break;
            }
            ++l_current_writer;
        }
    }

    l_current_writer = l_writers;

    /* cleanup */
    for (i = 0; i < l_nb_pass; ++i) {
        if (l_current_writer->m_data != 00) {
            opj_free(l_current_writer->m_data);
        }
        ++l_current_writer;
    }

    return l_result;
}