Blame tests/ppm2rgb3.c

Packit caffb5
/*
Packit caffb5
 * Copyright (c) 2014, Mathieu Malaterre <mathieu.malaterre@voxxl.com>
Packit caffb5
 * All rights reserved.
Packit caffb5
 *
Packit caffb5
 * Redistribution and use in source and binary forms, with or without
Packit caffb5
 * modification, are permitted provided that the following conditions
Packit caffb5
 * are met:
Packit caffb5
 * 1. Redistributions of source code must retain the above copyright
Packit caffb5
 *    notice, this list of conditions and the following disclaimer.
Packit caffb5
 * 2. Redistributions in binary form must reproduce the above copyright
Packit caffb5
 *    notice, this list of conditions and the following disclaimer in the
Packit caffb5
 *    documentation and/or other materials provided with the distribution.
Packit caffb5
 *
Packit caffb5
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
Packit caffb5
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit caffb5
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit caffb5
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
Packit caffb5
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit caffb5
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit caffb5
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit caffb5
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Packit caffb5
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit caffb5
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit caffb5
 * POSSIBILITY OF SUCH DAMAGE.
Packit caffb5
 */
Packit caffb5
Packit caffb5
/*
Packit caffb5
 * Technically on UNIX, one can simply call `ppmtorgb3`, but on my system it
Packit caffb5
 * did not work. So I had to write my own.
Packit caffb5
 */
Packit caffb5
Packit caffb5
#include <stdio.h>  /* fprintf */
Packit caffb5
#include <string.h> /* strcmp */
Packit caffb5
#include <stdlib.h> /* malloc */
Packit caffb5
Packit caffb5
static const char magic[] = "P6";
Packit caffb5
Packit caffb5
static int readheader( FILE *ppm, int *X, int *Y, int *bpp )
Packit caffb5
{
Packit caffb5
  char buffer[256];
Packit caffb5
  char strbuffer[256];
Packit caffb5
  char *line;
Packit caffb5
  int n;
Packit caffb5
Packit caffb5
  *X = *Y = *bpp = 0;
Packit caffb5
Packit caffb5
  line = fgets(buffer, sizeof(buffer), ppm);
Packit caffb5
  if( !line ) return 0;
Packit caffb5
  n = sscanf(buffer, "%255[^\r\n]", strbuffer);
Packit caffb5
  if( n != 1 ) return 0;
Packit caffb5
  if( strcmp(strbuffer, magic ) != 0 ) return 0;
Packit caffb5
Packit caffb5
  /* skip comments */
Packit caffb5
  while( fgets(buffer, sizeof(buffer), ppm) && *buffer == '#' )
Packit caffb5
    {
Packit caffb5
    }
Packit caffb5
  n = sscanf(buffer, "%d %d", X,Y);
Packit caffb5
  if( n != 2 ) return 0;
Packit caffb5
  line = fgets(buffer, sizeof(buffer), ppm);
Packit caffb5
  if( !line ) return 0;
Packit caffb5
  n = sscanf(buffer, "%d", bpp);
Packit caffb5
  if( n != 1 ) return 0;
Packit caffb5
  if( *bpp != 255 ) return 0;
Packit caffb5
Packit caffb5
  return 1;
Packit caffb5
}
Packit caffb5
Packit caffb5
static int writeoutput( const char *fn, FILE *ppm, int X, int Y, int bpp )
Packit caffb5
{
Packit caffb5
  FILE *outf[] = {NULL, NULL, NULL};
Packit caffb5
  int i, x, y = 0;
Packit caffb5
  char outfn[256];
Packit caffb5
  static const char *exts[3] = {
Packit caffb5
    "red",
Packit caffb5
    "grn",
Packit caffb5
    "blu"
Packit caffb5
  };
Packit caffb5
  char *image_line = NULL;
Packit caffb5
  int ok = 0;
Packit caffb5
Packit caffb5
  /* write single comp as PGM: P5 */
Packit caffb5
  for( i = 0; i < 3; ++i )
Packit caffb5
    {
Packit caffb5
#ifdef _MSC_VER
Packit caffb5
#define snprintf _snprintf /* Visual Studio */
Packit caffb5
#endif
Packit caffb5
    snprintf( outfn, sizeof(outfn), "%s.%s.pgm", fn, exts[i] );
Packit caffb5
    outf[i] = fopen( outfn, "wb" );
Packit caffb5
    if( !outf[i] ) goto cleanup;
Packit caffb5
    /* write header */
Packit caffb5
    fprintf( outf[i], "P5\n" );
Packit caffb5
    fprintf( outf[i], "%d %d\n", X, Y );
Packit caffb5
    fprintf( outf[i], "%d\n", bpp );
Packit caffb5
    }
Packit caffb5
Packit caffb5
  /* write pixel data */
Packit caffb5
  image_line = (char*)malloc( (size_t)X * 3 * sizeof(char) );
Packit caffb5
  if( !image_line ) goto cleanup;
Packit caffb5
  while( fread(image_line, sizeof(char), (size_t)X * 3, ppm) == (size_t)X * 3 )
Packit caffb5
    {
Packit caffb5
    for( x = 0; x < X; ++x )
Packit caffb5
      for( i = 0; i < 3; ++i )
Packit caffb5
        if( fputc( image_line[3*x+i], outf[i] ) == EOF ) goto cleanup;
Packit caffb5
    ++y;
Packit caffb5
    }
Packit caffb5
  if( y == Y )
Packit caffb5
    ok = 1;
Packit caffb5
cleanup:
Packit caffb5
  free(image_line);
Packit caffb5
  for( i = 0; i < 3; ++i )
Packit caffb5
    if( outf[i] ) fclose( outf[i] );
Packit caffb5
Packit caffb5
  return ok;
Packit caffb5
}
Packit caffb5
Packit caffb5
int main(int argc, char *argv[])
Packit caffb5
{
Packit caffb5
  const char *fn;
Packit caffb5
  FILE *ppm = NULL;
Packit caffb5
  int X, Y, bpp;
Packit caffb5
  int ok = 0;
Packit caffb5
Packit caffb5
  if( argc < 2 )
Packit caffb5
    {
Packit caffb5
    fprintf( stderr, "%s input.ppm\n", argv[0] );
Packit caffb5
    goto cleanup;
Packit caffb5
    }
Packit caffb5
  fn = argv[1];
Packit caffb5
  ppm = fopen( fn, "rb" );
Packit caffb5
Packit caffb5
  if( !readheader( ppm, &X, &Y, &bpp ) ) goto cleanup;
Packit caffb5
Packit caffb5
  if( !writeoutput(fn, ppm, X, Y, bpp ) ) goto cleanup;
Packit caffb5
Packit caffb5
  ok = 1;
Packit caffb5
cleanup:
Packit caffb5
  if(ppm) fclose(ppm);
Packit caffb5
  return ok ? EXIT_SUCCESS : EXIT_FAILURE;
Packit caffb5
}