From c7b646e23afd4875531b0f264aa47f9ee5b8d335 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Thu, 13 Mar 2014 09:57:20 +0000 Subject: [PATCH] [trunk] Add a small helper to spli ppm into 3 pgm files Update issue 235 --- tests/CMakeLists.txt | 2 + tests/ppm2rgb3.c | 132 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 tests/ppm2rgb3.c diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 625199f7..a62ceaf9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -98,3 +98,5 @@ if(BUILD_JPIP) -DEXPECTED_MD5=${md5} -P ${PROJECT_SOURCE_DIR}/cmake/JPIPTestDriver.cmake) endif() endif() + +add_executable(ppm2rgb3 ppm2rgb3.c) diff --git a/tests/ppm2rgb3.c b/tests/ppm2rgb3.c new file mode 100644 index 00000000..9d46f98e --- /dev/null +++ b/tests/ppm2rgb3.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2014, Mathieu Malaterre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Technically on UNIX, one can simply call `ppmtorgb3`, but on my system it + * did not work. So I had to write my own. + */ + +#include /* fprintf */ +#include /* strcmp */ +#include /* malloc */ + +static const char magic[] = "P6"; + +static int readheader( FILE *ppm, int *X, int *Y, int *bpp ) +{ + char buffer[256]; + char strbuffer[256]; + char *line; + int n; + + *X = *Y = *bpp = 0; + + line = fgets(buffer, sizeof(buffer), ppm); + if( !line ) return 0; + n = sscanf(buffer, "%255[^\r\n]", strbuffer); + if( n != 1 ) return 0; + if( strcmp(strbuffer, magic ) != 0 ) return 0; + + /* skip comments */ + while( fgets(buffer, sizeof(buffer), ppm) && *buffer == '#' ) + { + } + n = sscanf(buffer, "%d %d", X,Y); + if( n != 2 ) return 0; + line = fgets(buffer, sizeof(buffer), ppm); + if( !line ) return 0; + n = sscanf(buffer, "%d", bpp); + if( n != 1 ) return 0; + if( *bpp != 255 ) return 0; + + return 1; +} + +static int writeoutput( const char *fn, FILE *ppm, int X, int Y, int bpp ) +{ + FILE *outf[] = {NULL, NULL, NULL}; + int i, x, y = 0; + char outfn[256]; + static const char *exts[3] = { + "red", + "grn", + "blu" + }; + char *image_line = NULL; + int ok = 0; + + /* write single comp as PGM: P5 */ + for( i = 0; i < 3; ++i ) + { + snprintf( outfn, sizeof(outfn), "%s.%s.pgm", fn, exts[i] ); + outf[i] = fopen( outfn, "wb" ); + if( !outf[i] ) goto cleanup; + /* write header */ + fprintf( outf[i], "P5\n" ); + fprintf( outf[i], "%d %d\n", X, Y ); + fprintf( outf[i], "%d\n", bpp ); + } + + /* write pixel data */ + image_line = (char*)malloc( (size_t)X * 3 * sizeof(char) ); + if( !image_line ) goto cleanup; + while( fread(image_line, sizeof(char), (size_t)X * 3, ppm) == (size_t)X * 3 ) + { + for( x = 0; x < X; ++x ) + for( i = 0; i < 3; ++i ) + if( fputc( image_line[3*x+i], outf[i] ) == EOF ) goto cleanup; + ++y; + } + if( y == Y ) + ok = 1; +cleanup: + free(image_line); + for( i = 0; i < 3; ++i ) + if( outf[i] ) fclose( outf[i] ); + + return ok; +} + +int main(int argc, char *argv[]) +{ + const char *fn; + FILE *ppm = NULL; + int X, Y, bpp; + int ok = 0; + + if( argc < 2 ) goto cleanup; + fn = argv[1]; + ppm = fopen( fn, "rb" ); + + if( !readheader( ppm, &X, &Y, &bpp ) ) goto cleanup; + + if( !writeoutput(fn, ppm, X, Y, bpp ) ) goto cleanup; + + ok = 1; +cleanup: + if(ppm) fclose(ppm); + return ok ? EXIT_SUCCESS : EXIT_FAILURE; +}