Commit message: Avoid heap buffer overflow in function pnmtoimage of convert.c, and unsigned integer overflow in opj_image_create() (CVE-2016-9118, #861)
CVE: CVE-2018-16375
CWE: CWE-787
Vulnerability description: An issue was discovered in OpenJPEG 2.3.0. Missing checks for header_info.height and header_info.width in the function pnmtoimage in bin/jpwl/convert.c can lead to a heap-based buffer overflow.

Project: openjpeg
File: image.c

void opj_copy_image_header(const opj_image_t* p_image_src,
                           opj_image_t* p_image_dest)
{
    OPJ_UINT32 compno;

    /* preconditions */
    assert(p_image_src != 00);
    assert(p_image_dest != 00);

    p_image_dest->x0 = p_image_src->x0;
    p_image_dest->y0 = p_image_src->y0;
    p_image_dest->x1 = p_image_src->x1;
    p_image_dest->y1 = p_image_src->y1;

    if (p_image_dest->comps) {
        for (compno = 0; compno < p_image_dest->numcomps; compno++) {
            opj_image_comp_t *image_comp = &(p_image_dest->comps[compno]);
            if (image_comp->data) {
                opj_free(image_comp->data);
            }
        }
        opj_free(p_image_dest->comps);
        p_image_dest->comps = NULL;
    }

    p_image_dest->numcomps = p_image_src->numcomps;

    p_image_dest->comps = (opj_image_comp_t*) opj_malloc(p_image_dest->numcomps *
                          sizeof(opj_image_comp_t));
    if (!p_image_dest->comps) {
        p_image_dest->comps = NULL;
        p_image_dest->numcomps = 0;
        return;
    }

    for (compno = 0; compno < p_image_dest->numcomps; compno++) {
        memcpy(&(p_image_dest->comps[compno]),
               &(p_image_src->comps[compno]),
               sizeof(opj_image_comp_t));
        p_image_dest->comps[compno].data = NULL;
    }

    p_image_dest->color_space = p_image_src->color_space;
    p_image_dest->icc_profile_len = p_image_src->icc_profile_len;

    if (p_image_dest->icc_profile_len) {
        p_image_dest->icc_profile_buf = (OPJ_BYTE*)opj_malloc(
                                            p_image_dest->icc_profile_len);
        if (!p_image_dest->icc_profile_buf) {
            p_image_dest->icc_profile_buf = NULL;
            p_image_dest->icc_profile_len = 0;
            return;
        }
        memcpy(p_image_dest->icc_profile_buf,
               p_image_src->icc_profile_buf,
               p_image_src->icc_profile_len);
    } else {
        p_image_dest->icc_profile_buf = NULL;
    }

    return;
}

Project: openjpeg
File: image.c

opj_image_t* OPJ_CALLCONV opj_image_tile_create(OPJ_UINT32 numcmpts,
        opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc)
{
    OPJ_UINT32 compno;
    opj_image_t *image = 00;

    image = (opj_image_t*) opj_calloc(1, sizeof(opj_image_t));
    if (image) {

        image->color_space = clrspc;
        image->numcomps = numcmpts;

        /* allocate memory for the per-component information */
        image->comps = (opj_image_comp_t*)opj_calloc(image->numcomps,
                       sizeof(opj_image_comp_t));
        if (!image->comps) {
            opj_image_destroy(image);
            return 00;
        }

        /* create the individual image components */
        for (compno = 0; compno < numcmpts; compno++) {
            opj_image_comp_t *comp = &image->comps[compno];
            comp->dx = cmptparms[compno].dx;
            comp->dy = cmptparms[compno].dy;
            comp->w = cmptparms[compno].w;
            comp->h = cmptparms[compno].h;
            comp->x0 = cmptparms[compno].x0;
            comp->y0 = cmptparms[compno].y0;
            comp->prec = cmptparms[compno].prec;
            comp->sgnd = cmptparms[compno].sgnd;
            comp->data = 0;
        }
    }

    return image;
}

Project: openjpeg
File: convert.c

static unsigned short get_ushort(const unsigned char *data)
{
    unsigned short val = *(const unsigned short *)data;
#ifdef OPJ_BIG_ENDIAN
    val = ((val & 0xffU) << 8) | (val >> 8);
#endif
    return val;
}

Project: openjpeg
File: convert.c

static void convert_2u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst,
                              OPJ_SIZE_T length)
{
    OPJ_SIZE_T i;
    for (i = 0; i < (length & ~(OPJ_SIZE_T)3U); i += 4U) {
        OPJ_UINT32 val = *pSrc++;
        pDst[i + 0] = (OPJ_INT32)(val >> 6);
        pDst[i + 1] = (OPJ_INT32)((val >> 4) & 0x3U);
        pDst[i + 2] = (OPJ_INT32)((val >> 2) & 0x3U);
        pDst[i + 3] = (OPJ_INT32)(val & 0x3U);
    }
    if (length & 3U) {
        OPJ_UINT32 val = *pSrc++;
        length = length & 3U;
        pDst[i + 0] = (OPJ_INT32)(val >> 6);

        if (length > 1U) {
            pDst[i + 1] = (OPJ_INT32)((val >> 4) & 0x3U);
            if (length > 2U) {
                pDst[i + 2] = (OPJ_INT32)((val >> 2) & 0x3U);

            }
        }
    }
}

Project: openjpeg
File: image.c

void OPJ_CALLCONV opj_image_destroy(opj_image_t *image)
{
    if (image) {
        if (image->comps) {
            OPJ_UINT32 compno;

            /* image components */
            for (compno = 0; compno < image->numcomps; compno++) {
                opj_image_comp_t *image_comp = &(image->comps[compno]);
                if (image_comp->data) {
                    opj_free(image_comp->data);
                }
            }
            opj_free(image->comps);
        }

        if (image->icc_profile_buf) {
            opj_free(image->icc_profile_buf);
        }

        opj_free(image);
    }
}

Project: openjpeg
File: convert.c

static int imagetoraw_common(opj_image_t * image, const char *outfile,
                             OPJ_BOOL big_endian)
{
    FILE *rawFile = NULL;
    size_t res;
    unsigned int compno;
    int w, h, fails;
    int line, row, curr, mask;
    int *ptr;
    unsigned char uc;
    (void)big_endian;

    if ((image->numcomps * image->x1 * image->y1) == 0) {
        fprintf(stderr, "\nError: invalid raw image parameters\n");
        return 1;
    }

    rawFile = fopen(outfile, "wb");
    if (!rawFile) {
        fprintf(stderr, "Failed to open %s for writing !!\n", outfile);
        return 1;
    }

    fails = 1;
    fprintf(stdout, "Raw image characteristics: %d components\n", image->numcomps);

    for (compno = 0; compno < image->numcomps; compno++) {
        fprintf(stdout, "Component %u characteristics: %dx%dx%d %s\n", compno,
                image->comps[compno].w,
                image->comps[compno].h, image->comps[compno].prec,
                image->comps[compno].sgnd == 1 ? "signed" : "unsigned");

        w = (int)image->comps[compno].w;
        h = (int)image->comps[compno].h;

        if (image->comps[compno].prec <= 8) {
            if (image->comps[compno].sgnd == 1) {
                mask = (1 << image->comps[compno].prec) - 1;
                ptr = image->comps[compno].data;
                for (line = 0; line < h; line++) {
                    for (row = 0; row < w; row++)    {
                        curr = *ptr;
                        if (curr > 127) {
                            curr = 127;
                        } else if (curr < -128) {
                            curr = -128;
                        }
                        uc = (unsigned char)(curr & mask);
                        res = fwrite(&uc, 1, 1, rawFile);
                        if (res < 1) {
                            fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
                            goto fin;
                        }
                        ptr++;
                    }
                }
            } else if (image->comps[compno].sgnd == 0) {
                mask = (1 << image->comps[compno].prec) - 1;
                ptr = image->comps[compno].data;
                for (line = 0; line < h; line++) {
                    for (row = 0; row < w; row++)    {
                        curr = *ptr;
                        if (curr > 255) {
                            curr = 255;
                        } else if (curr < 0) {
                            curr = 0;
                        }
                        uc = (unsigned char)(curr & mask);
                        res = fwrite(&uc, 1, 1, rawFile);
                        if (res < 1) {
                            fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
                            goto fin;
                        }
                        ptr++;
                    }
                }
            }
        } else if (image->comps[compno].prec <= 16) {
            if (image->comps[compno].sgnd == 1) {
                union {
                    signed short val;
                    signed char vals[2];
                } uc16;
                mask = (1 << image->comps[compno].prec) - 1;
                ptr = image->comps[compno].data;
                for (line = 0; line < h; line++) {
                    for (row = 0; row < w; row++)    {
                        curr = *ptr;
                        if (curr > 32767) {
                            curr = 32767;
                        } else if (curr < -32768) {
                            curr = -32768;
                        }
                        uc16.val = (signed short)(curr & mask);
                        res = fwrite(uc16.vals, 1, 2, rawFile);
                        if (res < 2) {
                            fprintf(stderr, "failed to write 2 byte for %s\n", outfile);
                            goto fin;
                        }
                        ptr++;
                    }
                }
            } else if (image->comps[compno].sgnd == 0) {
                union {
                    unsigned short val;
                    unsigned char vals[2];
                } uc16;
                mask = (1 << image->comps[compno].prec) - 1;
                ptr = image->comps[compno].data;
                for (line = 0; line < h; line++) {
                    for (row = 0; row < w; row++)    {
                        curr = *ptr;
                        if (curr > 65535) {
                            curr = 65535;
                        } else if (curr < 0) {
                            curr = 0;
                        }
                        uc16.val = (unsigned short)(curr & mask);
                        res = fwrite(uc16.vals, 1, 2, rawFile);
                        if (res < 2) {
                            fprintf(stderr, "failed to write 2 byte for %s\n", outfile);
                            goto fin;
                        }
                        ptr++;
                    }
                }
            }
        } else if (image->comps[compno].prec <= 32) {
            fprintf(stderr, "More than 16 bits per component no handled yet\n");
            goto fin;
        } else {
            fprintf(stderr, "Error: invalid precision: %d\n", image->comps[compno].prec);
            goto fin;
        }
    }
    fails = 0;
fin:
    fclose(rawFile);
    return fails;
}

Project: openjpeg
File: convert.c

static int tga_readheader(FILE *fp, unsigned int *bits_per_pixel,
                          unsigned int *width, unsigned int *height, int *flip_image)
{
    int palette_size;
    unsigned char tga[TGA_HEADER_SIZE];
    unsigned char id_len, /*cmap_type,*/ image_type;
    unsigned char pixel_depth, image_desc;
    unsigned short /*cmap_index,*/ cmap_len, cmap_entry_size;
    unsigned short /*x_origin, y_origin,*/ image_w, image_h;

    if (!bits_per_pixel || !width || !height || !flip_image) {
        return 0;
    }

    if (fread(tga, TGA_HEADER_SIZE, 1, fp) != 1) {
        fprintf(stderr,
                "\nError: fread return a number of element different from the expected.\n");
        return 0 ;
    }
    id_len = tga[0];
    /*cmap_type = tga[1];*/
    image_type = tga[2];
    /*cmap_index = get_ushort(&tga[3]);*/
    cmap_len = get_ushort(&tga[5]);
    cmap_entry_size = tga[7];


#if 0
    x_origin = get_ushort(&tga[8]);
    y_origin = get_ushort(&tga[10]);
#endif
    image_w = get_ushort(&tga[12]);
    image_h = get_ushort(&tga[14]);
    pixel_depth = tga[16];
    image_desc  = tga[17];

    *bits_per_pixel = (unsigned int)pixel_depth;
    *width  = (unsigned int)image_w;
    *height = (unsigned int)image_h;

    /* Ignore tga identifier, if present ... */
    if (id_len) {
        unsigned char *id = (unsigned char *) malloc(id_len);
        if (id == 0) {
            fprintf(stderr, "tga_readheader: memory out\n");
            return 0;
        }
        if (!fread(id, id_len, 1, fp)) {
            fprintf(stderr,
                    "\nError: fread return a number of element different from the expected.\n");
            free(id);
            return 0 ;
        }
        free(id);
    }

    /* Test for compressed formats ... not yet supported ...
    // Note :-  9 - RLE encoded palettized.
    //         10 - RLE encoded RGB. */
    if (image_type > 8) {
        fprintf(stderr, "Sorry, compressed tga files are not currently supported.\n");
        return 0 ;
    }

    *flip_image = !(image_desc & 32);

    /* Palettized formats are not yet supported, skip over the palette, if present ... */
    palette_size = cmap_len * (cmap_entry_size / 8);

    if (palette_size > 0) {
        fprintf(stderr, "File contains a palette - not yet supported.");
        fseek(fp, palette_size, SEEK_CUR);
    }
    return 1;
}

Project: openjpeg
File: convert.c

opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters,
                        raw_cparameters_t *raw_cp)
{
    return rawtoimage_common(filename, parameters, raw_cp, OPJ_TRUE);
}

Project: openjpeg
File: image.c

opj_image_t* OPJ_CALLCONV opj_image_create(OPJ_UINT32 numcmpts,
        opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc)
{
    OPJ_UINT32 compno;
    opj_image_t *image = NULL;

    image = (opj_image_t*) opj_calloc(1, sizeof(opj_image_t));
    if (image) {
        image->color_space = clrspc;
        image->numcomps = numcmpts;
        /* allocate memory for the per-component information */
        image->comps = (opj_image_comp_t*)opj_calloc(1,
                       image->numcomps * sizeof(opj_image_comp_t));
        if (!image->comps) {
            /* TODO replace with event manager, breaks API */
            /* fprintf(stderr,"Unable to allocate memory for image.\n"); */
            opj_image_destroy(image);
            return NULL;
        }
        /* create the individual image components */
        for (compno = 0; compno < numcmpts; compno++) {
            opj_image_comp_t *comp = &image->comps[compno];
            comp->dx = cmptparms[compno].dx;
            comp->dy = cmptparms[compno].dy;
            comp->w = cmptparms[compno].w;
            comp->h = cmptparms[compno].h;
            comp->x0 = cmptparms[compno].x0;
            comp->y0 = cmptparms[compno].y0;
            comp->prec = cmptparms[compno].prec;
            comp->bpp = cmptparms[compno].bpp;
            comp->sgnd = cmptparms[compno].sgnd;
            if (comp->h != 0 && (OPJ_SIZE_T)comp->w > SIZE_MAX / comp->h) {
                // TODO event manager
                opj_image_destroy(image);
                return NULL;
            }
            comp->data = (OPJ_INT32*) opj_calloc((OPJ_SIZE_T)comp->w * comp->h,
                                                 sizeof(OPJ_INT32));
            if (!comp->data) {
                /* TODO replace with event manager, breaks API */
                /* fprintf(stderr,"Unable to allocate memory for image.\n"); */
                opj_image_destroy(image);
                return NULL;
            }
        }
    }

    return image;
}

Project: openjpeg
File: convert.c

int imagetotga(opj_image_t * image, const char *outfile)
{
    int width, height, bpp, x, y;
    OPJ_BOOL write_alpha;
    unsigned int i;
    int adjustR, adjustG, adjustB, fails;
    unsigned int alpha_channel;
    float r, g, b, a;
    unsigned char value;
    float scale;
    FILE *fdest;
    size_t res;
    fails = 1;

    fdest = fopen(outfile, "wb");
    if (!fdest) {
        fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
        return 1;
    }

    for (i = 0; i < image->numcomps - 1; i++) {
        if ((image->comps[0].dx != image->comps[i + 1].dx)
                || (image->comps[0].dy != image->comps[i + 1].dy)
                || (image->comps[0].prec != image->comps[i + 1].prec)) {
            fclose(fdest);
            fprintf(stderr,
                    "Unable to create a tga file with such J2K image charateristics.");
            return 1;
        }
    }

    width  = (int)image->comps[0].w;
    height = (int)image->comps[0].h;

    /* Mono with alpha, or RGB with alpha. */
    write_alpha = (image->numcomps == 2) || (image->numcomps == 4);

    /* Write TGA header  */
    bpp = write_alpha ? 32 : 24;

    if (!tga_writeheader(fdest, bpp, width, height, OPJ_TRUE)) {
        goto fin;
    }

    alpha_channel = image->numcomps - 1;

    scale = 255.0f / (float)((1 << image->comps[0].prec) - 1);

    adjustR = (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
    adjustG = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
    adjustB = (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);

    for (y = 0; y < height; y++) {
        unsigned int index = (unsigned int)(y * width);

        for (x = 0; x < width; x++, index++) {
            r = (float)(image->comps[0].data[index] + adjustR);

            if (image->numcomps > 2) {
                g = (float)(image->comps[1].data[index] + adjustG);
                b = (float)(image->comps[2].data[index] + adjustB);
            } else {
                /* Greyscale ... */
                g = r;
                b = r;
            }

            /* TGA format writes BGR ... */
            if (b > 255.) {
                b = 255.;
            } else if (b < 0.) {
                b = 0.;
            }
            value = (unsigned char)(b * scale);
            res = fwrite(&value, 1, 1, fdest);

            if (res < 1) {
                fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
                goto fin;
            }
            if (g > 255.) {
                g = 255.;
            } else if (g < 0.) {
                g = 0.;
            }
            value = (unsigned char)(g * scale);
            res = fwrite(&value, 1, 1, fdest);

            if (res < 1) {
                fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
                goto fin;
            }
            if (r > 255.) {
                r = 255.;
            } else if (r < 0.) {
                r = 0.;
            }
            value = (unsigned char)(r * scale);
            res = fwrite(&value, 1, 1, fdest);

            if (res < 1) {
                fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
                goto fin;
            }

            if (write_alpha) {
                a = (float)(image->comps[alpha_channel].data[index]);
                if (a > 255.) {
                    a = 255.;
                } else if (a < 0.) {
                    a = 0.;
                }
                value = (unsigned char)(a * scale);
                res = fwrite(&value, 1, 1, fdest);

                if (res < 1) {
                    fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
                    goto fin;
                }
            }
        }
    }
    fails = 0;
fin:
    fclose(fdest);

    return fails;
}

Project: openjpeg
File: image.c

opj_image_t* opj_image_create0(void)
{
    opj_image_t *image = (opj_image_t*)opj_calloc(1, sizeof(opj_image_t));
    return image;
}

Project: openjpeg
File: convert.c

int imagetopnm(opj_image_t * image, const char *outfile, int force_split)
{
    int *red, *green, *blue, *alpha;
    int wr, hr, max;
    int i;
    unsigned int compno, ncomp;
    int adjustR, adjustG, adjustB, adjustA;
    int fails, two, want_gray, has_alpha, triple;
    int prec, v;
    FILE *fdest = NULL;
    const char *tmp = outfile;
    char *destname;

    alpha = NULL;

    if ((prec = (int)image->comps[0].prec) > 16) {
        fprintf(stderr, "%s:%d:imagetopnm\n\tprecision %d is larger than 16"
                "\n\t: refused.\n", __FILE__, __LINE__, prec);
        return 1;
    }
    two = has_alpha = 0;
    fails = 1;
    ncomp = image->numcomps;

    while (*tmp) {
        ++tmp;
    }
    tmp -= 2;
    want_gray = (*tmp == 'g' || *tmp == 'G');
    ncomp = image->numcomps;

    if (want_gray) {
        ncomp = 1;
    }

    if ((force_split == 0) && ncomp >= 2 &&
            are_comps_similar(image)) {
        fdest = fopen(outfile, "wb");

        if (!fdest) {
            fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
            return fails;
        }
        two = (prec > 8);
        triple = (ncomp > 2);
        wr = (int)image->comps[0].w;
        hr = (int)image->comps[0].h;
        max = (1 << prec) - 1;
        has_alpha = (ncomp == 4 || ncomp == 2);

        red = image->comps[0].data;

        if (triple) {
            green = image->comps[1].data;
            blue = image->comps[2].data;
        } else {
            green = blue = NULL;
        }

        if (has_alpha) {
            const char *tt = (triple ? "RGB_ALPHA" : "GRAYSCALE_ALPHA");

            fprintf(fdest, "P7\n# OpenJPEG-%s\nWIDTH %d\nHEIGHT %d\nDEPTH %u\n"
                    "MAXVAL %d\nTUPLTYPE %s\nENDHDR\n", opj_version(),
                    wr, hr, ncomp, max, tt);
            alpha = image->comps[ncomp - 1].data;
            adjustA = (image->comps[ncomp - 1].sgnd ?
                       1 << (image->comps[ncomp - 1].prec - 1) : 0);
        } else {
            fprintf(fdest, "P6\n# OpenJPEG-%s\n%d %d\n%d\n",
                    opj_version(), wr, hr, max);
            adjustA = 0;
        }
        adjustR = (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);

        if (triple) {
            adjustG = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
            adjustB = (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
        } else {
            adjustG = adjustB = 0;
        }

        for (i = 0; i < wr * hr; ++i) {
            if (two) {
                v = *red + adjustR;
                ++red;
                if (v > 65535) {
                    v = 65535;
                } else if (v < 0) {
                    v = 0;
                }

                /* netpbm: */
                fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);

                if (triple) {
                    v = *green + adjustG;
                    ++green;
                    if (v > 65535) {
                        v = 65535;
                    } else if (v < 0) {
                        v = 0;
                    }

                    /* netpbm: */
                    fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);

                    v =  *blue + adjustB;
                    ++blue;
                    if (v > 65535) {
                        v = 65535;
                    } else if (v < 0) {
                        v = 0;
                    }

                    /* netpbm: */
                    fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);

                }/* if(triple) */

                if (has_alpha) {
                    v = *alpha + adjustA;
                    ++alpha;
                    if (v > 65535) {
                        v = 65535;
                    } else if (v < 0) {
                        v = 0;
                    }

                    /* netpbm: */
                    fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
                }
                continue;

            }   /* if(two) */

            /* prec <= 8: */
            v = *red++;
            if (v > 255) {
                v = 255;
            } else if (v < 0) {
                v = 0;
            }

            fprintf(fdest, "%c", (unsigned char)v);
            if (triple) {
                v = *green++;
                if (v > 255) {
                    v = 255;
                } else if (v < 0) {
                    v = 0;
                }

                fprintf(fdest, "%c", (unsigned char)v);
                v = *blue++;
                if (v > 255) {
                    v = 255;
                } else if (v < 0) {
                    v = 0;
                }

                fprintf(fdest, "%c", (unsigned char)v);
            }
            if (has_alpha) {
                v = *alpha++;
                if (v > 255) {
                    v = 255;
                } else if (v < 0) {
                    v = 0;
                }

                fprintf(fdest, "%c", (unsigned char)v);
            }
        }   /* for(i */

        fclose(fdest);
        return 0;
    }

    /* YUV or MONO: */

    if (image->numcomps > ncomp) {
        fprintf(stderr, "WARNING -> [PGM file] Only the first component\n");
        fprintf(stderr, "           is written to the file\n");
    }
    destname = (char*)malloc(strlen(outfile) + 8);
    if (destname == NULL) {
        fprintf(stderr, "imagetopnm: memory out\n");
        return 1;
    }
    for (compno = 0; compno < ncomp; compno++) {
        if (ncomp > 1) {
            /*sprintf(destname, "%d.%s", compno, outfile);*/
            const size_t olen = strlen(outfile);
            const size_t dotpos = olen - 4;

            strncpy(destname, outfile, dotpos);
            sprintf(destname + dotpos, "_%u.pgm", compno);
        } else {
            sprintf(destname, "%s", outfile);
        }

        fdest = fopen(destname, "wb");
        if (!fdest) {
            fprintf(stderr, "ERROR -> failed to open %s for writing\n", destname);
            free(destname);
            return 1;
        }
        wr = (int)image->comps[compno].w;
        hr = (int)image->comps[compno].h;
        prec = (int)image->comps[compno].prec;
        max = (1 << prec) - 1;

        fprintf(fdest, "P5\n#OpenJPEG-%s\n%d %d\n%d\n",
                opj_version(), wr, hr, max);

        red = image->comps[compno].data;
        adjustR =
            (image->comps[compno].sgnd ? 1 << (image->comps[compno].prec - 1) : 0);

        if (prec > 8) {
            for (i = 0; i < wr * hr; i++) {
                v = *red + adjustR;
                ++red;
                if (v > 65535) {
                    v = 65535;
                } else if (v < 0) {
                    v = 0;
                }

                /* netpbm: */
                fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);

                if (has_alpha) {
                    v = *alpha++;
                    if (v > 65535) {
                        v = 65535;
                    } else if (v < 0) {
                        v = 0;
                    }

                    /* netpbm: */
                    fprintf(fdest, "%c%c", (unsigned char)(v >> 8), (unsigned char)v);
                }
            }/* for(i */
        } else { /* prec <= 8 */
            for (i = 0; i < wr * hr; ++i) {
                v = *red + adjustR;
                ++red;
                if (v > 255) {
                    v = 255;
                } else if (v < 0) {
                    v = 0;
                }

                fprintf(fdest, "%c", (unsigned char)v);
            }
        }
        fclose(fdest);
    } /* for (compno */
    free(destname);

    return 0;
}/* imagetopnm() */

Project: openjpeg
File: image.c

void opj_image_comp_header_update(opj_image_t * p_image_header,
                                  const struct opj_cp * p_cp)
{
    OPJ_UINT32 i, l_width, l_height;
    OPJ_UINT32 l_x0, l_y0, l_x1, l_y1;
    OPJ_UINT32 l_comp_x0, l_comp_y0, l_comp_x1, l_comp_y1;
    opj_image_comp_t* l_img_comp = NULL;

    l_x0 = opj_uint_max(p_cp->tx0, p_image_header->x0);
    l_y0 = opj_uint_max(p_cp->ty0, p_image_header->y0);
    l_x1 = p_cp->tx0 + (p_cp->tw - 1U) *
           p_cp->tdx; /* validity of p_cp members used here checked in opj_j2k_read_siz. Can't overflow. */
    l_y1 = p_cp->ty0 + (p_cp->th - 1U) * p_cp->tdy; /* can't overflow */
    l_x1 = opj_uint_min(opj_uint_adds(l_x1, p_cp->tdx),
                        p_image_header->x1); /* use add saturated to prevent overflow */
    l_y1 = opj_uint_min(opj_uint_adds(l_y1, p_cp->tdy),
                        p_image_header->y1); /* use add saturated to prevent overflow */

    l_img_comp = p_image_header->comps;
    for (i = 0; i < p_image_header->numcomps; ++i) {
        l_comp_x0 = opj_uint_ceildiv(l_x0, l_img_comp->dx);
        l_comp_y0 = opj_uint_ceildiv(l_y0, l_img_comp->dy);
        l_comp_x1 = opj_uint_ceildiv(l_x1, l_img_comp->dx);
        l_comp_y1 = opj_uint_ceildiv(l_y1, l_img_comp->dy);
        l_width   = opj_uint_ceildivpow2(l_comp_x1 - l_comp_x0, l_img_comp->factor);
        l_height  = opj_uint_ceildivpow2(l_comp_y1 - l_comp_y0, l_img_comp->factor);
        l_img_comp->w = l_width;
        l_img_comp->h = l_height;
        l_img_comp->x0 = l_comp_x0;
        l_img_comp->y0 = l_comp_y0;
        ++l_img_comp;
    }
}