tools/pngtotex.c
static int run_dxtcomp(const uint8_t *src, unsigned int width,
                       unsigned int height, unsigned int type, uint8_t *dest)
{
    const unsigned int bpp = (type==1 ? 4 : 8);
    char dir[1000], infile[1009], outfile[1009];

    /* Create a temporary directory for the dxtcomp input/output files.
     * We ignore a value of $TMPDIR containing an apostrophe because it'll
     * wreak havoc with our command line below. */
    const char *tmpdir = getenv("TMPDIR");
    if (!tmpdir || strchr(tmpdir, '\'') != NULL) {
        tmpdir = "/tmp";
    }
    if (snprintf(dir, sizeof(dir), "%s/pngtotexXXXXXX",
                 tmpdir) >= (int)sizeof(dir)) {
        fprintf(stderr, "Buffer overflow on temporary directory\n");
        goto error_return;
    }
    if (!mkdtemp(dir)) {
        fprintf(stderr, "Failed to create temporary directory (%s): %s\n",
                dir, strerror(errno));
        goto error_return;
    }
    /* These are guaranteed to fit. */
    snprintf(infile, sizeof(infile), "%s/in.rgba", dir);
    snprintf(outfile, sizeof(outfile), "%s/out.dxt", dir);

    /* Create a temporary buffer, expanding (with repetition) to the
     * minimum size for the selected format and forcing the alpha bytes to
     * full opacity if using DXT1 compression. */
    const unsigned int dxt_width = lbound(width, 4);
    const unsigned int dxt_height = lbound(height, 4);
    uint8_t *tempbuf = malloc(dxt_width * dxt_height * 4);
    if (!tempbuf) {
        fprintf(stderr, "Failed to allocate temporary buffer (%u bytes)\n",
                dxt_width * dxt_height * 4);
        goto error_rmdir;
    }
    if (width != dxt_width || height != dxt_height) {
        uint8_t *out = tempbuf;
        for (unsigned int y = 0; y < dxt_height; y++) {
            const uint8_t *row = src + (y % height) * width * 4;
            for (unsigned int x = 0; x < dxt_width; x++, out += 4) {
                const uint8_t r = row[(x % width) * 4 + 0];
                const uint8_t g = row[(x % width) * 4 + 1];
                const uint8_t b = row[(x % width) * 4 + 2];
                const uint8_t a = row[(x % width) * 4 + 3];
                out[0] = b;
                out[1] = g;
                out[2] = r;
                out[3] = (type==1 ? 255 : a);
            }
        }
    } else if (type == 1) {
        for (unsigned int i = 0; i < width*height*4; i += 4) {
            const uint8_t r = src[i+0];
            const uint8_t g = src[i+1];
            const uint8_t b = src[i+2];
            tempbuf[i+0] = b;
            tempbuf[i+1] = g;
            tempbuf[i+2] = r;
            tempbuf[i+3] = 255;
        }
        spread_border(tempbuf, width, height);
    } else {
        memcpy(tempbuf, src, width*height*4);
    }

    /* Write the pixel data as a raw RGBA file. */
    FILE *f = fopen(infile, "wb");
    if (!f) {
        fprintf(stderr, "Failed to create %s: %s\n", infile, strerror(errno));
        goto error_free_tempbuf;
    }
    if (fwrite(tempbuf, dxt_width*dxt_height*4, 1, f) != 1) {
        fprintf(stderr, "Failed to write data to %s: %s\n", infile,
                strerror(errno));
        fclose(f);
        goto error_remove_infile;
    }
    if (fclose(f) != 0) {
        fprintf(stderr, "Failed to close %s: %s\n", infile, strerror(errno));
        goto error_remove_infile;
    }

    /* Call out to dxtcomp. */
    char cmdbuf[4000];  // Long enough to avoid truncation.
    snprintf(cmdbuf, sizeof(cmdbuf), "dxtcomp -%d '%s' '%s' %u %u",
             type, infile, outfile, dxt_width, dxt_height);
    if (verbose) {
        fprintf(stderr, "Executing: %s\n", cmdbuf);
    }
    if (system(cmdbuf) != 0) {
        fprintf(stderr, "dxtcomp call failed\n");
        goto error_remove_outfile;
    }

    /* Read the compressed pixel data from the output file. */
    f = fopen(outfile, "r");
    if (!f) {
        fprintf(stderr, "Failed to open %s: %s\n", outfile, strerror(errno));
        goto error_remove_outfile;
    }
    if (fread(dest, (dxt_width * dxt_height * bpp) / 8, 1, f) != 1) {
        fprintf(stderr, "Failed to read data from %s\n", outfile);
        fclose(f);
        goto error_remove_outfile;
    }
    fclose(f);

    /* All done!  Clean up our files/buffers and return. */
    remove(outfile);
    remove(infile);
    rmdir(dir);
    free(tempbuf);
    return 1;

    /* Handle all error returns here so we don't leave junk behind. */
  error_remove_outfile:
    remove(outfile);
  error_remove_infile:
    remove(infile);
  error_free_tempbuf:
    free(tempbuf);
  error_rmdir:
    rmdir(dir);
  error_return:
    return 0;
}
/**
 * run_dxtcomp:  Run the external dxtcomp program (assumed to be in the
 * executable path) to compress pixel data.  Note that DXTn data has a
 * minimum encoded size of 4x4, regardless of the actual image size, and
 * the caller must ensure enough output buffer space is available.
 *
 * [Parameters]
 *     src: Input pixel data, in RGBA8888 format (destroyed).
 *     width: Texture width, in pixels.
 *     height: Texture height, in pixels.
 *     type: DXTn compression type (1, 3, or 5).
 *     dest: Output data pointer.
 * [Return value]
 *     True on success, false on error.
 */
Run the external dxtcomp program (assumed to be in the
executable path) to compress pixel data.  Note that DXTn data has a
minimum encoded size of 4x4, regardless of the actual image size, and
the caller must ensure enough output buffer space is available.

[Parameters]
src: Input pixel data, in RGBA8888 format (destroyed).
width: Texture width, in pixels.
height: Texture height, in pixels.
type: DXTn compression type (1, 3, or 5).
dest: Output data pointer.
[Return value]
True on success, false on error.
Run the external dxtcomp program ( assumed to be in the executable path ) to compress pixel data . Note that DXTn data has a minimum encoded size of 4x4 regardless of the actual image size and the caller must ensure enough output buffer space is available . [ Parameters ] src : Input pixel data in RGBA8888 format ( destroyed ) . width : Texture width in pixels . height : Texture height in pixels . type : DXTn compression type ( 1 3 or 5 ) . dest : Output data pointer . [ Return value ] True on success false on error .
static int run_dxtcomp(const uint8_t *src, unsigned int width,
                       unsigned int height, unsigned int type, uint8_t *dest)
{
    const unsigned int bpp = (type==1 ? 4 : 8);
    char dir[1000], infile[1009], outfile[1009];
    const char *tmpdir = getenv("TMPDIR");
    if (!tmpdir || strchr(tmpdir, '\'') != NULL) {
        tmpdir = "/tmp";
    }
    if (snprintf(dir, sizeof(dir), "%s/pngtotexXXXXXX",
                 tmpdir) >= (int)sizeof(dir)) {
        fprintf(stderr, "Buffer overflow on temporary directory\n");
        goto error_return;
    }
    if (!mkdtemp(dir)) {
        fprintf(stderr, "Failed to create temporary directory (%s): %s\n",
                dir, strerror(errno));
        goto error_return;
    }
    snprintf(infile, sizeof(infile), "%s/in.rgba", dir);
    snprintf(outfile, sizeof(outfile), "%s/out.dxt", dir);
    const unsigned int dxt_width = lbound(width, 4);
    const unsigned int dxt_height = lbound(height, 4);
    uint8_t *tempbuf = malloc(dxt_width * dxt_height * 4);
    if (!tempbuf) {
        fprintf(stderr, "Failed to allocate temporary buffer (%u bytes)\n",
                dxt_width * dxt_height * 4);
        goto error_rmdir;
    }
    if (width != dxt_width || height != dxt_height) {
        uint8_t *out = tempbuf;
        for (unsigned int y = 0; y < dxt_height; y++) {
            const uint8_t *row = src + (y % height) * width * 4;
            for (unsigned int x = 0; x < dxt_width; x++, out += 4) {
                const uint8_t r = row[(x % width) * 4 + 0];
                const uint8_t g = row[(x % width) * 4 + 1];
                const uint8_t b = row[(x % width) * 4 + 2];
                const uint8_t a = row[(x % width) * 4 + 3];
                out[0] = b;
                out[1] = g;
                out[2] = r;
                out[3] = (type==1 ? 255 : a);
            }
        }
    } else if (type == 1) {
        for (unsigned int i = 0; i < width*height*4; i += 4) {
            const uint8_t r = src[i+0];
            const uint8_t g = src[i+1];
            const uint8_t b = src[i+2];
            tempbuf[i+0] = b;
            tempbuf[i+1] = g;
            tempbuf[i+2] = r;
            tempbuf[i+3] = 255;
        }
        spread_border(tempbuf, width, height);
    } else {
        memcpy(tempbuf, src, width*height*4);
    }
    FILE *f = fopen(infile, "wb");
    if (!f) {
        fprintf(stderr, "Failed to create %s: %s\n", infile, strerror(errno));
        goto error_free_tempbuf;
    }
    if (fwrite(tempbuf, dxt_width*dxt_height*4, 1, f) != 1) {
        fprintf(stderr, "Failed to write data to %s: %s\n", infile,
                strerror(errno));
        fclose(f);
        goto error_remove_infile;
    }
    if (fclose(f) != 0) {
        fprintf(stderr, "Failed to close %s: %s\n", infile, strerror(errno));
        goto error_remove_infile;
    }
    char cmdbuf[4000];  
    snprintf(cmdbuf, sizeof(cmdbuf), "dxtcomp -%d '%s' '%s' %u %u",
             type, infile, outfile, dxt_width, dxt_height);
    if (verbose) {
        fprintf(stderr, "Executing: %s\n", cmdbuf);
    }
    if (system(cmdbuf) != 0) {
        fprintf(stderr, "dxtcomp call failed\n");
        goto error_remove_outfile;
    }
    f = fopen(outfile, "r");
    if (!f) {
        fprintf(stderr, "Failed to open %s: %s\n", outfile, strerror(errno));
        goto error_remove_outfile;
    }
    if (fread(dest, (dxt_width * dxt_height * bpp) / 8, 1, f) != 1) {
        fprintf(stderr, "Failed to read data from %s\n", outfile);
        fclose(f);
        goto error_remove_outfile;
    }
    fclose(f);
    remove(outfile);
    remove(infile);
    rmdir(dir);
    free(tempbuf);
    return 1;
  error_remove_outfile:
    remove(outfile);
  error_remove_infile:
    remove(infile);
  error_free_tempbuf:
    free(tempbuf);
  error_rmdir:
    rmdir(dir);
  error_return:
    return 0;
}
static int run_dxtcomp ( const uint8_t * src , unsigned int width , unsigned int height , unsigned int type , uint8_t * dest ) { const unsigned int bpp = ( type == 1 ? 4 : 8 ) ; char dir [ 1000 ] , infile [ 1009 ] , outfile [ 1009 ] ; const char * tmpdir = getenv ( " " ) ; if ( ! tmpdir || strchr ( tmpdir , ' \' ' ) != NULL ) { tmpdir = " " ; } if ( snprintf ( dir , sizeof ( dir ) , " " , tmpdir ) >= ( int ) sizeof ( dir ) ) { fprintf ( stderr , " \n " ) ; goto error_return ; } if ( ! mkdtemp ( dir ) ) { fprintf ( stderr , " \n " , dir , strerror ( errno ) ) ; goto error_return ; } snprintf ( infile , sizeof ( infile ) , " " , dir ) ; snprintf ( outfile , sizeof ( outfile ) , " " , dir ) ; const unsigned int dxt_width = lbound ( width , 4 ) ; const unsigned int dxt_height = lbound ( height , 4 ) ; uint8_t * tempbuf = malloc ( dxt_width * dxt_height * 4 ) ; if ( ! tempbuf ) { fprintf ( stderr , " \n " , dxt_width * dxt_height * 4 ) ; goto error_rmdir ; } if ( width != dxt_width || height != dxt_height ) { uint8_t * out = tempbuf ; for ( unsigned int y = 0 ; y < dxt_height ; y ++ ) { const uint8_t * row = src + ( y % height ) * width * 4 ; for ( unsigned int x = 0 ; x < dxt_width ; x ++ , out += 4 ) { const uint8_t r = row [ ( x % width ) * 4 + 0 ] ; const uint8_t g = row [ ( x % width ) * 4 + 1 ] ; const uint8_t b = row [ ( x % width ) * 4 + 2 ] ; const uint8_t a = row [ ( x % width ) * 4 + 3 ] ; out [ 0 ] = b ; out [ 1 ] = g ; out [ 2 ] = r ; out [ 3 ] = ( type == 1 ? 255 : a ) ; } } } else if ( type == 1 ) { for ( unsigned int i = 0 ; i < width * height * 4 ; i += 4 ) { const uint8_t r = src [ i + 0 ] ; const uint8_t g = src [ i + 1 ] ; const uint8_t b = src [ i + 2 ] ; tempbuf [ i + 0 ] = b ; tempbuf [ i + 1 ] = g ; tempbuf [ i + 2 ] = r ; tempbuf [ i + 3 ] = 255 ; } spread_border ( tempbuf , width , height ) ; } else { memcpy ( tempbuf , src , width * height * 4 ) ; } FILE * f = fopen ( infile , " " ) ; if ( ! f ) { fprintf ( stderr , " \n " , infile , strerror ( errno ) ) ; goto error_free_tempbuf ; } if ( fwrite ( tempbuf , dxt_width * dxt_height * 4 , 1 , f ) != 1 ) { fprintf ( stderr , " \n " , infile , strerror ( errno ) ) ; fclose ( f ) ; goto error_remove_infile ; } if ( fclose ( f ) != 0 ) { fprintf ( stderr , " \n " , infile , strerror ( errno ) ) ; goto error_remove_infile ; } char cmdbuf [ 4000 ] ; snprintf ( cmdbuf , sizeof ( cmdbuf ) , " " , type , infile , outfile , dxt_width , dxt_height ) ; if ( verbose ) { fprintf ( stderr , " \n " , cmdbuf ) ; } if ( system ( cmdbuf ) != 0 ) { fprintf ( stderr , " \n " ) ; goto error_remove_outfile ; } f = fopen ( outfile , " " ) ; if ( ! f ) { fprintf ( stderr , " \n " , outfile , strerror ( errno ) ) ; goto error_remove_outfile ; } if ( fread ( dest , ( dxt_width * dxt_height * bpp ) / 8 , 1 , f ) != 1 ) { fprintf ( stderr , " \n " , outfile ) ; fclose ( f ) ; goto error_remove_outfile ; } fclose ( f ) ; remove ( outfile ) ; remove ( infile ) ; rmdir ( dir ) ; free ( tempbuf ) ; return 1 ; error_remove_outfile : remove ( outfile ) ; error_remove_infile : remove ( infile ) ; error_free_tempbuf : free ( tempbuf ) ; error_rmdir : rmdir ( dir ) ; error_return : return 0 ; }
run_dxtcomp:  Run the external dxtcomp program (assumed to be in the
 executable path) to compress pixel data.
run_dxtcomp : Run the external dxtcomp program ( assumed to be in the executable path ) to compress pixel data .
/* Create a temporary directory for the dxtcomp input/output files.
     * We ignore a value of $TMPDIR containing an apostrophe because it'll
     * wreak havoc with our command line below. */ /* These are guaranteed to fit. */ /* Create a temporary buffer, expanding (with repetition) to the
     * minimum size for the selected format and forcing the alpha bytes to
     * full opacity if using DXT1 compression. */ /* Write the pixel data as a raw RGBA file. */ /* Call out to dxtcomp. */ // Long enough to avoid truncation. /* Read the compressed pixel data from the output file. */ /* All done!  Clean up our files/buffers and return. */ /* Handle all error returns here so we don't leave junk behind. */