/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF.  The full HDF copyright notice, including       *
 * terms governing use, modification, and redistribution, is contained in    *
 * the COPYING file, which can be found at the root of the source code       *
 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*
 *  hdfcomp.c
 *  Re-compress Raster-8 HDF file
 */
#include "hdf.h"

uint8 *space;
uint8  palette[768];
int32  xdim, ydim;
int    ispal;

int
main(int argc, char *argv[])
{
    int       i;
    char     *outfile;
    intn      jpeg_qual = 75; /* JPEG quality factor */
    uint16    prevref, writeref, compress = (uint16)0;
    comp_info cinfo;        /* compression structure */
    int32     out_fid;      /* file ID for the output file */
    intn      copy_flabel,  /* flag to indicate to copy file labels */
        copy_fdesc,         /* flag to indicate to copy file descriptions */
        copy_ilabel,        /* flag to indicate to copy image labels */
        copy_idesc;         /* flag to indicate to copy image descriptions */
    char *annbuf    = NULL; /* buffer to store annotations in */
    int32 annbuflen = 0;    /* length of the annotation buffer */

    if (argc < 3) {
        printf("%s,  version: 1.3   date: October 15, 1994\n", argv[0]);
        printf("  This utility will read in raster-8 images from an\n");
        printf("  HDF file and create a new HDF containing the\n");
        printf("  images in a compressed format.  Images will be\n");
        printf("  appended to outfile, if it exists.\n\n");
        printf("Usage:\n");
        printf(" hdfcomp outfile {[-c],[-r],[-i],[-j<quality>]} imagefile ...\n");
        printf("                 {[-c],[-r],[-i],[-j<quality>]} imagefile\n");
        printf("         -r: Store without compression (default)\n");
        printf("         -c: Store using RLE compression\n");
        printf("         -i: Store using IMCOMP compression (requires a");
        printf(" palette in the HDF file)\n");
        printf("         -j<quality>: Store using JPEG compression\n");
        printf("            with a quality factor from 1-100, 75 default\n");
        exit(1);
    }

    outfile = argv[1];

    /* open the output file so that we can write Annotations into it easily */
    if ((out_fid = Hopen(outfile, DFACC_ALL, 0)) == FAIL) {
        printf("Error opening output file: %s\n", outfile);
        exit(1);
    } /* end if */

    for (i = 2; i < argc; i++) {
        /* turn all the flags on (default settings) */
        copy_flabel = copy_fdesc = copy_ilabel = copy_idesc = TRUE;

        if (*argv[i] == '-') {
            switch (argv[i][1]) {
                case 'r': /* raster */
                    compress = (uint16)0;
                    break;
                case 'c': /* RLE */
                    compress = COMP_RLE;
                    break;
                case 'i': /* IMCOMP */
                    compress = COMP_IMCOMP;
                    break;
                case 'j': /* JPEG */
                    compress = COMP_JPEG;
                    if ((jpeg_qual = atoi(&argv[i][2])) <= 0 || jpeg_qual > 100) {
                        printf("Bad JPEG quality setting, should be between\n");
                        printf("1 and 100, using default value of 75\n");
                        jpeg_qual = 75;
                    }                                      /* end if */
                    cinfo.jpeg.quality        = jpeg_qual; /* set JPEG parameters */
                    cinfo.jpeg.force_baseline = TRUE;
                    break;
                default:
                    printf("Illegal option: %s, skipping....\n", argv[i]);
                    break;
            }
        }
        else { /* file name */
            /* copy the file annotations and labels over */
            if (copy_flabel == TRUE || copy_fdesc == TRUE) {
                intn  isfirst; /* flip-flop for first image */
                int32 annlen;  /* length of the annotation to copy */
                int32 old_fid; /* file ID for the old and new files */

                if ((old_fid = Hopen(argv[i], DFACC_READ, 0)) == FAIL) {
                    printf("Error opening input file: %s, skipping to next file\n", argv[i]);
                    continue;
                } /* end if */
                if (copy_flabel == TRUE) {
                    isfirst = 1;
                    while ((annlen = DFANgetfidlen(old_fid, isfirst)) != FAIL) {
                        if (annbuflen == 0 || annlen > annbuflen) {
                            if (annbuflen != 0)
                                free(annbuf);
                            if ((annbuf = (char *)malloc(annlen)) == NULL) {
                                printf("Error allocating buffer for annotation, aborting!\n");
                                exit(1);
                            } /* end if */
                            annbuflen = annlen;
                        } /* end if */
                        if (DFANgetfid(old_fid, annbuf, annbuflen, isfirst) == FAIL)
                            printf("Error reading file annotation from file:%s, continuing\n", argv[i]);
                        else {
                            if (DFANaddfid(out_fid, annbuf) == FAIL)
                                printf("Error wriring annotation to file:%s, continuing\n", outfile);
                        }            /* end else */
                        isfirst = 0; /* get the next label from the file */
                    }                /* end while */
                }                    /* end if */
                if (copy_fdesc == TRUE) {
                    isfirst = 1;
                    while ((annlen = DFANgetfdslen(old_fid, isfirst)) != FAIL) {
                        if (annbuflen == 0 || annlen > annbuflen) {
                            if (annbuflen != 0)
                                free(annbuf);
                            if ((annbuf = (char *)malloc(annlen)) == NULL) {
                                printf("Error allocating buffer for annotation, aborting!\n");
                                exit(1);
                            } /* end if */
                            annbuflen = annlen;
                        } /* end if */
                        if (DFANgetfds(old_fid, annbuf, annbuflen, isfirst) == FAIL)
                            printf("Error reading file annotation from file:%s, continuing\n", argv[i]);
                        else {
                            if (DFANaddfds(out_fid, annbuf, annlen) == FAIL)
                                printf("Error wriring annotation to file:%s, continuing\n", outfile);
                        }            /* end else */
                        isfirst = 0; /* get the next label from the file */
                    }                /* end while */
                }                    /* end if */
                Hclose(old_fid);     /* remember to close the file */
            }                        /* end if */

            /* copy the images over */
            while (DFR8getdims(argv[i], &xdim, &ydim, &ispal) >= 0) {
                prevref = DFR8lastref();
                if ((space = (uint8 *)malloc((size_t)(xdim * ydim))) == NULL) {
                    printf("Not enough memory to convert image");
                    exit(1);
                }

                if (DFR8getimage(argv[i], space, xdim, ydim, palette) < 0) {
                    printf("Error reading image from file %s\n", argv[i]);
                    exit(1);
                }
                if (ispal)
                    DFR8setpalette((uint8 *)palette);
                else if (compress == DFTAG_IMC) {
                    printf("Couldn't find palette for IMCOMP compression\n");
                    exit(1);
                }

                writeref = Hnewref(out_fid);
                DFR8writeref(outfile, writeref);

                if (compress)
                    DFR8setcompress((int32)compress, &cinfo);
                if (DFR8addimage(outfile, (void *)space, xdim, ydim, compress) < 0) {
                    printf("Error writing image to file %s\n", outfile);
                    exit(1);
                }

                /* sequence through the annotations for this image */
                if (copy_ilabel == TRUE || copy_idesc == TRUE) {
                    uint16 image_tag = DFTAG_RIG; /* tag to look for image annotations with */
                    int32  annlen;                /* length of the annotation to copy */

                    if (copy_ilabel == TRUE) {
                        if ((annlen = DFANgetlablen(argv[i], image_tag, prevref)) != FAIL) {
                            if (annbuflen == 0 || annlen > annbuflen) {
                                if (annbuflen != 0)
                                    free(annbuf);
                                if ((annbuf = (char *)malloc(annlen)) == NULL) {
                                    printf("Error allocating buffer for annotation, aborting!\n");
                                    exit(1);
                                } /* end if */
                                annbuflen = annlen;
                            } /* end if */
                            if (DFANgetlabel(argv[i], image_tag, prevref, annbuf, annbuflen) == FAIL)
                                printf("Error reading annotation from file:%s, continuing\n", argv[i]);
                            else if (DFANputlabel(outfile, image_tag, writeref, annbuf) == FAIL)
                                printf("Error writing annotation to file:%s, continuing\n", outfile);
                        } /* end if */
                    }     /* end if */
                    if (copy_idesc == TRUE) {
                        if ((annlen = DFANgetdesclen(argv[i], image_tag, prevref)) != FAIL) {
                            if (annbuflen == 0 || annlen > annbuflen) {
                                if (annbuflen != 0)
                                    free(annbuf);
                                if ((annbuf = (char *)malloc(annlen)) == NULL) {
                                    printf("Error allocating buffer for annotation, aborting!\n");
                                    exit(1);
                                } /* end if */
                                annbuflen = annlen;
                            } /* end if */
                            if (DFANgetdesc(argv[i], image_tag, prevref, annbuf, annbuflen) == FAIL)
                                printf("Error reading annotation from file:%s, continuing\n", argv[i]);
                            else if (DFANputdesc(outfile, image_tag, writeref, annbuf, annlen) == FAIL)
                                printf("Error writing annotation to file:%s, continuing\n", outfile);
                        } /* end if */
                    }     /* end if */
                }         /* end if */

                /* sequence past this image */
                DFR8readref(argv[i], prevref);
                DFR8getdims(argv[i], &xdim, &ydim, &ispal);

                free(space);
            }
        }
    }

    Hclose(out_fid);    /* remember to close the file */
    if (annbuflen != 0) /* and free the buffer space */
        free(annbuf);

    return (0);
}
