about summary refs log tree commit diff
path: root/editor/pnmpaste.c
diff options
context:
space:
mode:
Diffstat (limited to 'editor/pnmpaste.c')
-rw-r--r--editor/pnmpaste.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/editor/pnmpaste.c b/editor/pnmpaste.c
new file mode 100644
index 00000000..38b316c6
--- /dev/null
+++ b/editor/pnmpaste.c
@@ -0,0 +1,185 @@
+/* pnmpaste.c - paste a rectangle into a portable anymap
+**
+** Copyright (C) 1989 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation.  This software is provided "as is" without express or
+** implied warranty.
+*/
+
+#include "pm_c_util.h"
+#include "pnm.h"
+
+int
+main( argc, argv )
+    int argc;
+    char* argv[];
+    {
+    FILE* ifp1;
+    FILE* ifp2;
+    register xel* xelrow1;
+    register xel* xelrow2;
+    register xel* x1P;
+    register xel* x2P;
+    xelval maxval1, maxval2, newmaxval;
+    int argn, rows1, cols1, format1, x, y;
+    int rows2, cols2, format2, newformat, row;
+    register int col;
+    char function;
+    const char* const usage = "[-replace|-or|-and|-xor] frompnmfile x y [intopnmfile]";
+
+    pnm_init( &argc, argv );
+
+    argn = 1;
+    function = 'r';
+
+    /* Check for flags. */
+    if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
+	{
+	if ( pm_keymatch( argv[argn], "-replace", 2 ) )
+	    function = 'r';
+	else if ( pm_keymatch( argv[argn], "-or", 2 ) )
+	    function = 'o';
+	else if ( pm_keymatch( argv[argn], "-and", 2 ) )
+	    function = 'a';
+	else if ( pm_keymatch( argv[argn], "-xor", 2 ) )
+	    function = 'x';
+	else
+	    pm_usage( usage );
+	++argn;
+	}
+
+    if ( argn == argc )
+	pm_usage( usage );
+    ifp1 = pm_openr( argv[argn] );
+    ++argn;
+
+    if ( argn == argc )
+	pm_usage( usage );
+    if ( sscanf( argv[argn], "%d", &x ) != 1 )
+	pm_usage( usage );
+    ++argn;
+    if ( argn == argc )
+	pm_usage( usage );
+    if ( sscanf( argv[argn], "%d", &y ) != 1 )
+	pm_usage( usage );
+    ++argn;
+
+    if ( argn != argc )
+	{
+	ifp2 = pm_openr( argv[argn] );
+	++argn;
+	}
+    else
+	ifp2 = stdin;
+
+    if ( argn != argc )
+	pm_usage( usage );
+
+    pnm_readpnminit( ifp1, &cols1, &rows1, &maxval1, &format1 );
+    xelrow1 = pnm_allocrow(cols1);
+    pnm_readpnminit( ifp2, &cols2, &rows2, &maxval2, &format2 );
+    xelrow2 = pnm_allocrow(cols2);
+
+    if ( x <= -cols2 )
+	pm_error(
+	    "x is too negative -- the second anymap has only %d cols",
+	    cols2 );
+    else if ( x >= cols2 )
+	pm_error(
+	    "x is too large -- the second anymap has only %d cols",
+	    cols2 );
+    if ( y <= -rows2 )
+	pm_error(
+	    "y is too negative -- the second anymap has only %d rows",
+	    rows2 );
+    else if ( y >= rows2 )
+	pm_error(
+	    "y is too large -- the second anymap has only %d rows",
+	    rows2 );
+
+    if ( x < 0 )
+	x += cols2;
+    if ( y < 0 )
+	y += rows2;
+
+    if ( x + cols1 > cols2 )
+	pm_error( "x + width is too large by %d pixels", x + cols1 - cols2 );
+    if ( y + rows1 > rows2 )
+	pm_error( "y + height is too large by %d pixels", y + rows1 - rows2 );
+
+    newformat = MAX( PNM_FORMAT_TYPE(format1), PNM_FORMAT_TYPE(format2) );
+    newmaxval = MAX( maxval1, maxval2 );
+
+    if ( function != 'r' && newformat != PBM_TYPE )
+	pm_error( "no logical operations allowed for non-bitmaps" );
+
+    pnm_writepnminit( stdout, cols2, rows2, newmaxval, newformat, 0 );
+
+    for ( row = 0; row < rows2; ++row )
+	{
+	pnm_readpnmrow( ifp2, xelrow2, cols2, maxval2, format2 );
+	pnm_promoteformatrow( xelrow2, cols2, maxval2, format2,
+	    newmaxval, newformat );
+
+	if ( row >= y && row < y + rows1 )
+	    {
+	    pnm_readpnmrow( ifp1, xelrow1, cols1, maxval1, format1 );
+	    pnm_promoteformatrow( xelrow1, cols1, maxval1, format1,
+		newmaxval, newformat );
+	    for ( col = 0, x1P = xelrow1, x2P = &(xelrow2[x]);
+		  col < cols1; ++col, ++x1P, ++x2P )
+		{
+		register xelval b1, b2;
+
+		switch ( function )
+		    {
+		    case 'r':
+		    *x2P = *x1P;
+		    break;
+
+		    case 'o':
+		    b1 = PNM_GET1( *x1P );
+		    b2 = PNM_GET1( *x2P );
+		    if ( b1 != 0 || b2 != 0 )
+			PNM_ASSIGN1( *x2P, newmaxval );
+		    else
+			PNM_ASSIGN1( *x2P, 0 );
+		    break;
+
+		    case 'a':
+		    b1 = PNM_GET1( *x1P );
+		    b2 = PNM_GET1( *x2P );
+		    if ( b1 != 0 && b2 != 0 )
+			PNM_ASSIGN1( *x2P, newmaxval );
+		    else
+			PNM_ASSIGN1( *x2P, 0 );
+		    break;
+
+		    case 'x':
+		    b1 = PNM_GET1( *x1P );
+		    b2 = PNM_GET1( *x2P );
+		    if ( ( b1 != 0 && b2 == 0 ) || ( b1 == 0 && b2 != 0 ) )
+			PNM_ASSIGN1( *x2P, newmaxval );
+		    else
+			PNM_ASSIGN1( *x2P, 0 );
+		    break;
+
+		    default:
+		    pm_error( "can't happen" );
+		    }
+		}
+	    }
+
+	pnm_writepnmrow( stdout, xelrow2, cols2, newmaxval, newformat, 0 );
+	}
+    
+    pm_close( ifp1 );
+    pm_close( ifp2 );
+    pm_close( stdout );
+
+    exit( 0 );
+    }