]> bicyclesonthemoon.info Git - ott/enhance/blobdiff - npb.c
makefile cleanup and safety (don't rm -rf)
[ott/enhance] / npb.c
diff --git a/npb.c b/npb.c
index 1c03b9916a330df42017befe2da5b4340f17f90c..d315afff67ef46818672c100703685b0f4bb356d 100644 (file)
--- a/npb.c
+++ b/npb.c
@@ -1,7 +1,7 @@
 /*
 npb.c
 Take a picture and add a newpixbot to it!
-29.11.2022
+05.12.2022
 
 Copyright (C) 2013 - 2015, 2022  Balthasar SzczepaƄski
 
@@ -28,6 +28,7 @@ on Pentium III libdevil must be recompiled with
 
 #include <stdint.h>
 #include <getopt.h>
+#include <errno.h>
 
 #include "core.h"
 #include "npb.h"
@@ -38,18 +39,33 @@ on Pentium III libdevil must be recompiled with
 #include "npb_ong1.h"
 #include "npb_403.h"
 
-#define NPB0_L  21
-#define NPB0_R 116
-#define NPB0_T 122
-#define NPB0_B 189
+#define NPB0_L      21
+#define NPB0_R     116
+#define NPB0_T     122
+#define NPB0_B     189
 
-#define NPB1_L  22
-#define NPB1_R 154
-#define NPB1_T  69
-#define NPB1_B 162
+#define NPB1_L      22
+#define NPB1_R     154
+#define NPB1_T      69
+#define NPB1_B     162
 
+#define NPB2_L      36
+#define NPB2_R     199
+#define NPB2_T     171
+#define NPB2_B     171
 
-char NPB_MISSING_ARGS[] = "Missing parameters.\nnpb [-o -4 -r -b -c] inPix outPix\n";
+#define NPB_ONG1_L -74
+#define NPB_ONG1_R 102
+#define NPB_ONG1_T  66
+#define NPB_ONG1_B  69
+
+#define NPB_403_L  224
+#define NPB_403_R  295
+#define NPB_403_T  261
+#define NPB_403_B  261
+
+
+char NPB_MISSING_ARGS[] = "Missing parameters.\nnpb [-o -4 -r -b -e -c] inPix outPix\n";
 
 int subtool_npb (int argc, char **argv, int argi, char **err)
 {
@@ -58,44 +74,61 @@ int subtool_npb (int argc, char **argv, int argi, char **err)
        uint_fast8_t corners = 0;
        uint_fast8_t fullsize = 0;
        uint_fast8_t fill_white = 0;
+       uint_fast8_t fill_white_all = 0;
+       uint_fast8_t npb_after = 0;
        uint_fast8_t expand_left = 0;
        uint_fast8_t expand_right = 0;
        uint_fast8_t expand_up = 0;
        uint_fast8_t expand_down = 0;
-       uint_fast8_t border_outside = 0;
+       uint_fast8_t fixed_frame = 0;
+       uint_fast8_t override_new_border = 0;
+       uint_fast8_t override_external_border = 0;
        
        ILuint cut_border = 0;
-       ILuint new_border = 2;
+       ILuint new_border;
+       ILuint external_border;
+       ILuint new_border_default = 2;
+       ILuint external_border_default = 0;
        ILuint max = 0xFF; //upscale_value(0xFF, info[0].image_bpc); // bpc=1
-       ILuint effective_width, effective_height;
+       ILint width_content, height_content, x0_content_own, y0_content_own, x0_content_global, y0_content_global;
+       ILint width_border, height_border, x0_border, y0_border;
+       ILint width_npb, height_npb, x0_npb, y0_npb;
+       ILint width_total, height_total;
        const uint8_t *npb_pix;
        uint_fast32_t npb_size;
-       ILuint x_l, x_r, y_t, y_b;
+       ILint space_l, space_r, space_t, space_b;
        
        struct ColorInfo color;
-       struct IL_full_info info[3];
-       FLAG_TYPE flags [3] = {
-               CANNOT_BE_GRAY | CANNOT_BE_INDEXED | NOT_WRITABLE,
-               CANNOT_BE_GRAY | CANNOT_BE_INDEXED | NOT_WRITABLE | MUST_HAVE_ALPHA,
-               CANNOT_BE_GRAY | CANNOT_BE_INDEXED | NOT_READABLE | MUST_HAVE_ALPHA,
-       }
-       ILuint x0[3];
-       ILuint y0[3];
+       struct IL_full_info info_content;
+       struct IL_full_info info_npb;
+       struct IL_full_info info_total;
+       FLAG_TYPE flags_content = CANNOT_BE_GRAY | CANNOT_BE_INDEXED | NOT_WRITABLE;
+       FLAG_TYPE flags_npb     = CANNOT_BE_GRAY | CANNOT_BE_INDEXED | NOT_WRITABLE | MUST_HAVE_ALPHA;
+       FLAG_TYPE flags_total   = CANNOT_BE_GRAY | CANNOT_BE_INDEXED                | MUST_HAVE_ALPHA;
+       
+       uint_fast16_t id[2];
+       FLAG_TYPE flags[2];
+       ILint x0[2];
+       ILint y0[2];
+       ILint f0[2] = {0, 0};
        
        struct option long_options[] = {
-               {"ong1",          no_argument,       NULL, 'o'},
-               {"403",           no_argument,       NULL, '4'},
-               {"remove-border", required_argument, NULL, 'r'},
-               {"new-border",    required_argument, NULL, 'b'},
-               {"corners",       no_argument,       NULL, 'c'},
-               {"help",          no_argument,       NULL, 'h'},
-               {0,               0,                 0,    0}
+               {"ong1",           no_argument,       NULL, 'o'},
+               {"403",            no_argument,       NULL, '4'},
+               {"remove-border",  required_argument, NULL, 'r'},
+               {"new-border",     required_argument, NULL, 'b'},
+               {"external-border",required_argument, NULL, 'e'},
+               {"corners",        no_argument,       NULL, 'c'},
+               {"help",           no_argument,       NULL, 'h'},
+               {0,                0,                 0,    0}
        };
-       char short_options[] = "o4r:b:ch";
+       char short_options[] = "o4r:b:e:ch0";
        
        int opt;
        int r;
        
+       /* we get options first */
+       
        optind = argi;
        while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1)
        {
@@ -108,11 +141,16 @@ int subtool_npb (int argc, char **argv, int argi, char **err)
                        t403 = 1;
                        break;
                case 'r':
-                       sscanf(optarg, "%lu, &cut_border);
+                       sscanf(optarg, "%u", &cut_border);
                        break;
                case 'b':
-                       sscanf(optarg, "%lu, &new_border);
+                       sscanf(optarg, "%u", &new_border);
                        fullsize = 1;
+                       override_new_border = 1;
+                       break;
+               case 'e':
+                       sscanf(optarg, "%u", &external_border);
+                       override_external_border = 1;
                        break;
                case 'c':
                        corners = 1;
@@ -129,369 +167,571 @@ int subtool_npb (int argc, char **argv, int argi, char **err)
                return EINVAL;
        }
        
-       r = reserve_pictures(1);
+       r = reserve_pictures(3);
        if (r)
        {
                *err = CREATE_FAILED;
                return r;
        }
        
-       r = load_picture(0, argv[optind], &(info[0]), &(flags[0]);
+       /* load content to insert to npb */
+       
+       r = load_picture(0, argv[optind], &(info_content), &(flags_content));
        if (r)
        {
                *err = LOAD_FAILED;
                return r;
        }
        
-       effective_width = (info[0].image_width > (2*cut_border)) ? (info[0].image_width - (2*cut_border)) : 0;
-       effective_height = (info[0].image_height > (2*cut_border)) ? (info[0].image_height - (2*cut_border)) : 0;
+       /* determine actually used rectangle without border */
+       
+       width_content = (info_content.image_width > (2*cut_border)) ? (info_content.image_width - (2*cut_border)) : 0;
+       height_content = (info_content.image_height > (2*cut_border)) ? (info_content.image_height - (2*cut_border)) : 0;
+       x0_content_own = cut_border;
+       y0_content_own = cut_border;
+       
+       /* select npb mode */
        
        if (t403)
        {
                npb_pix = npb_403;
                npb_size = npb_403_size;
+               space_l = NPB_403_L;
+               space_r = NPB_403_R;
+               space_t = NPB_403_T;
+               space_b = NPB_403_B;
+               expand_right = 1;
+               expand_up = 1;
+               new_border_default = 0;
+               external_border_default = 2;
+               fill_white_all = 1;
        }
        else if (ong1)
        {
                npb_pix = npb_ong1;
                npb_size = npb_ong1_size;
+               space_l = NPB_ONG1_L;
+               space_r = NPB_ONG1_R;
+               space_t = NPB_ONG1_T;
+               space_b = NPB_ONG1_B;
+               expand_left = 1;
+               expand_up = 1;
+               npb_after = 1;
        }
-       else if ((effective_width <= NPB0_X_MAX) && (effective_height <= NPB0_Y_MAX) && (!fullsize))
+       else if ((width_content <= (NPB0_R - NPB0_L + 1)) && (height_content <= (NPB0_B - NPB0_T + 1)) && (!fullsize))
        {
                npb_pix = npb0;
                npb_size = npb0_size;
+               space_l = NPB0_L;
+               space_r = NPB0_R;
+               space_t = NPB0_T;
+               space_b = NPB0_B;
                fill_white = 1;
+               override_new_border = 1;
                new_border = 0;
+               npb_after = 1;
+               fixed_frame = 1;
        }
-       else if ((effective_width <= NPB1_X_MAX) && (effective_height <= NPB1_Y_MAX) && (!fullsize))
+       else if ((width_content <= (NPB1_R - NPB1_L + 1)) && (height_content <= (NPB1_B - NPB1_T + 1)) && (!fullsize))
        {
                npb_pix = npb1;
                npb_size = npb1_size;
+               space_l = NPB1_L;
+               space_r = NPB1_R;
+               space_t = NPB1_T;
+               space_b = NPB1_B;
                fill_white = 1;
+               override_new_border = 1;
                new_border = 0;
+               npb_after = 1;
+               fixed_frame = 1;
        }
        else
        {
                npb_pix = npb2;
                npb_size = npb2_size;
+               space_l = NPB2_L;
+               space_r = NPB2_R;
+               space_t = NPB2_T;
+               space_b = NPB2_B;
+               expand_left = 1;
+               expand_up = 1;
+               npb_after = 1;
        }
-
-
-}
-
-#define INPIX_MUSTARD 1
-#define OUTPIX_MUSTARD 2
-#define NPBPIX_MUSTARD 3
-#define ARGUMENT_MUSTARD 4
-#define SEAISH_MUSTARD 5
-#define ANIMATED_MUSTARD 6
-#define FAIL 900
-#define OK 0
-
-#define NPBPIX0 "npb0.png"
-#define X0  411
-#define X01  21
-#define X02  96
-#define Y0  404
-#define Y01 214
-#define Y02  68
-
-#define NPBPIX1 "npb1.png"
-#define X1  411
-#define X11  22
-#define X12 133
-#define Y1  404
-#define Y11 241
-#define Y12  94
-
-#define NPBPIX2 "npb2.png"
-#define X2  411
-#define X21 213
-#define Y2  404
-#define Y21 234
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <IL/il.h>
-
-void mustard(int mustard);
-void loadnpb(const char *path);
-void npbottify0(const char *path);
-void npbottify1(const char *path);
-void npbottify2(const char *path);
-int main (int argc, const char *argv[]);
-
-ILuint inPix, outPix, npbPix;
-ILboolean q=true;
-ILboolean inH=false;
-ILboolean outH=false;
-ILboolean npbH=false;
-ILuint inX, inY, outX, outY;
-ILubyte *newdata;
-
-int main (int argc, const char *argv[])
-{
-       if(argc<3)
-               mustard(ARGUMENT_MUSTARD);
-       if (argc>=4)
+       
+       /* determine borders' sizes */
+       if (!override_new_border)
+               new_border = new_border_default;
+       if (!override_external_border)
+               external_border = external_border_default;
+       
+       /* load selected npb */
+       
+       r = load_picture_mem(1, npb_pix, npb_size, &(info_npb), &(flags_npb));
+       if (r)
        {
-               if (argv[3][0]=='q' || argv[3][0]=='Q')
-                       q=false;
+               *err = LOAD_FAILED;
+               return r;
        }
        
-       ilInit();
-       if(!ilEnable(IL_ORIGIN_SET))mustard(FAIL);
-       if(!ilEnable(IL_FILE_OVERWRITE))mustard(FAIL);
-       ilClearColour(255,255,0,0);
-       ilGenImages(1, &inPix);
-       inH=true;
-       ilBindImage(inPix);
-       if(!ilLoadImage(argv[1]))mustard(INPIX_MUSTARD);
-       if(!ilConvertImage(IL_RGBA,IL_UNSIGNED_BYTE))mustard(INPIX_MUSTARD);
-       //if(!ilConvertPal(IL_PAL_RGBA32))mustard(FAIL);
-       
-       inX=ilGetInteger(IL_IMAGE_WIDTH);
-       inY=ilGetInteger(IL_IMAGE_HEIGHT);
-       if(ilGetInteger(IL_NUM_IMAGES)>1)
-               mustard(ANIMATED_MUSTARD);
-       
-       if(inX<=X02&&inY<=Y02)
-               npbottify0(argv[2]);
-       else if(inX<=X12&&inY<=Y12)
-               npbottify1(argv[2]);
+       /* determine rectangle of content with new border */
+       
+       width_border = width_content + new_border * 2;
+       height_border = height_content + new_border * 2;
+       
+       /* npb rectangle too */
+       
+       width_npb = info_npb.image_width;
+       height_npb = info_npb.image_height;
+       x0_npb = 0;
+       y0_npb = 0;
+       
+       /* initial total size, to update later */
+       
+       width_total = width_npb;
+       height_total = height_npb;
+       
+       /* determine content border placement in full picture */
+       
+       if (expand_right && (width_border >= (space_r - space_l +1)))
+               x0_border = space_l;
+       else if (expand_left && (width_border >= (space_r - space_l +1)))
+               x0_border = space_r - width_border + 1;
        else
-               npbottify2(argv[2]);    
-       //ok
-       mustard(0);
-}
-
-void loadnpb(const char *path)
-{
-       ilGenImages(1, &npbPix);
-       npbH=true;
-       ilBindImage(npbPix);
-       if(!ilLoadImage(path))mustard(NPBPIX_MUSTARD);
-       if(!ilConvertImage(IL_RGBA,IL_UNSIGNED_BYTE))mustard(NPBPIX_MUSTARD);
-}
-
-void npbottify0(const char *path)
-{
-       //newdata= new ILubyte[X0*Y0*4];
-       ilGenImages(1, &outPix);
-       outH=true;
-       loadnpb(NPBPIX0);
-       ilBindImage(outPix);
-       if(!ilCopyImage(npbPix))mustard(FAIL);
-       //if(!ilTexImage(X0,Y0,1,4,IL_RGBA,IL_UNSIGNED_BYTE,NULL))mustard(OUTPIX_MUSTARD);
-       //if(!ilConvertImage(IL_RGBA,IL_UNSIGNED_BYTE))mustard(OUTPIX_MUSTARD);
-       newdata=ilGetData();
-       for(unsigned long i=0;i<X0;++i)
+               x0_border = (space_l + space_r + 1 - width_border) / 2;
+       
+       if (expand_down && (height_border >= (space_b - space_t +1)))
+               y0_border = space_t;
+       else if (expand_up && (height_border >= (space_b - space_t +1)))
+               y0_border = space_b - height_border + 1;
+       else
+               y0_border = (space_t + space_b + 1 - height_border) / 2;
+       
+       /* determine content placement in border in full picture */
+       
+       x0_content_global = x0_border + new_border;
+       y0_content_global = y0_border + new_border;
+       
+       /* adjust full picture size & offsets if content doesn't fit */
+       
+       if (width_total < (x0_border + width_border))
+               width_total = x0_border + width_border;
+       if (height_total < (y0_border + height_border))
+               height_total = y0_border + height_border;
+       if (x0_border < 0)
+       {
+               width_total -= x0_border;
+               x0_npb -= x0_border;
+               x0_content_global -= x0_border;
+               x0_border = 0;
+       }
+       if (y0_border < 0)
+       {
+               height_total -= y0_border;
+               y0_npb -= y0_border;
+               y0_content_global -= y0_border;
+               y0_border = 0;
+       }
+       
+       /* adjust for external border */
+       
+       if (external_border > 0)
+       {
+               width_total += 2 * external_border;
+               height_total += 2 * external_border;
+               x0_border += external_border;
+               y0_border += external_border;
+               x0_content_global += external_border;
+               y0_content_global += external_border;
+               x0_npb += external_border;
+               y0_npb += external_border;
+       }
+       
+       /* ok setup done, now perform actions */
+       
+       /* 1: create target picture */
+       
+       r = build_picture(2, width_total, height_total, 1, &info_total, &flags_total);
+       if (r!=0)
+       {
+               *err = LOAD_FAILED;
+               return r;
+       }
+       
+       /* 2: init background */
+       
+       color.red   = max;
+       color.green = max;
+       color.blue  = max;
+       color.alpha = fill_white_all ? max : 0;
+       
+       r = perform_action_1picture(
+               2, //id
+               external_border, //x0
+               external_border, //y0
+               0, //f0
+               (width_total - 2 * external_border), //width
+               (height_total - 2 * external_border), //height
+               1, //frames
+               &fill_color, //function
+               flags_total | IN_WINDOW | NOT_READABLE, //flags
+               &color //data
+       );
+       if (r!=0)
+       {
+               *err = CONVERT_FAILED;
+               return r;
+       }
+       
+       /* 3: draw border outside */
+       
+       if (external_border >0)
        {
-               for(unsigned long j=0;j<Y0;++j)
+               color.red   = 0;
+               color.green = 0;
+               color.blue  = 0;
+               color.alpha = max;
+               
+               r = perform_action_1picture( //top
+                       2, //id
+                       0, //x0
+                       0, //y0
+                       0, //f0
+                       width_total, //width
+                       external_border, //height
+                       1, //frames
+                       &fill_color, //function
+                       flags_total | IN_WINDOW | NOT_READABLE, //flags
+                       &color //data
+               );
+               if (r!=0)
+               {
+                       *err = CONVERT_FAILED;
+                       return r;
+               }
+               
+               r = perform_action_1picture( //bottom
+                       2, //id
+                       0, //x0
+                       height_total - external_border, //y0
+                       0, //f0
+                       width_total, //width
+                       external_border, //height
+                       1, //frames
+                       &fill_color, //function
+                       flags_total | IN_WINDOW | NOT_READABLE, //flags
+                       &color //data
+               );
+               if (r!=0)
+               {
+                       *err = CONVERT_FAILED;
+                       return r;
+               }
+               
+               r = perform_action_1picture( //left
+                       2, //id
+                       0, //x0
+                       external_border, //y0
+                       0, //f0
+                       external_border, //width
+                       height_total - 2*external_border, //height
+                       1, //frames
+                       &fill_color, //function
+                       flags_total | IN_WINDOW | NOT_READABLE, //flags
+                       &color //data
+               );
+               if (r!=0)
+               {
+                       *err = CONVERT_FAILED;
+                       return r;
+               }
+               
+               r = perform_action_1picture( //right
+                       2, //id
+                       width_total - external_border, //x0
+                       external_border, //y0
+                       0, //f0
+                       external_border, //width
+                       height_total - 2*external_border, //height
+                       1, //frames
+                       &fill_color, //function
+                       flags_total | IN_WINDOW | NOT_READABLE, //flags
+                       &color //data
+               );
+               if (r!=0)
+               {
+                       *err = CONVERT_FAILED;
+                       return r;
+               }
+               
+               if (corners)
                {
-                       if((i>=X01+(X02-inX)/2)&&
-                          (i< X01+(X02-inX)/2+inX)&&
-                          (j>=Y01+(Y02-inY)/2)&&
-                          (j< Y01+(Y02-inY)/2+inY))
+                       color.alpha = 0;
+                       
+                       r = perform_action_1picture_1pixel( //top-left
+                               2, //id
+                               0, //x0
+                               0, //y0
+                               0, //f0
+                               &fill_color, //function
+                               flags_total | IN_WINDOW | NOT_READABLE, //flags
+                               &color //data
+                       );
+                       if (r!=0)
+                       {
+                               *err = CONVERT_FAILED;
+                               return r;
+                       }
+                       
+                       r = perform_action_1picture_1pixel( //top-right
+                               2, //id
+                               width_total - 1, //x0
+                               0, //y0
+                               0, //f0
+                               &fill_color, //function
+                               flags_total | IN_WINDOW | NOT_READABLE, //flags
+                               &color //data
+                       );
+                       if (r!=0)
                        {
-                               newdata[4*(i+X0*j)+0]=0xFF;
-                               newdata[4*(i+X0*j)+1]=0xFF;
-                               newdata[4*(i+X0*j)+2]=0xFF;
-                               newdata[4*(i+X0*j)+3]=0xFF;
+                               *err = CONVERT_FAILED;
+                               return r;
                        }
-                       else if((i>=X01)&&(i<X01+X02)&&
-                               (j>=Y01)&&(j<Y01+Y02))
+                       
+                       r = perform_action_1picture_1pixel( //bottom-right
+                               2, //id
+                               width_total - 1, //x0
+                               height_total - 1, //y0
+                               0, //f0
+                               &fill_color, //function
+                               flags_total | IN_WINDOW | NOT_READABLE, //flags
+                               &color //data
+                       );
+                       if (r!=0)
                        {
-                               newdata[4*(i+X0*j)+0]=0xFF;//looks better white
-                               newdata[4*(i+X0*j)+1]=0xFF;
-                               newdata[4*(i+X0*j)+2]=0xFF;
-                               newdata[4*(i+X0*j)+3]=0xFF;
+                               *err = CONVERT_FAILED;
+                               return r;
                        }
-                       else
+                       
+                       r = perform_action_1picture_1pixel( //bottom-left
+                               2, //id
+                               0, //x0
+                               height_total - 1, //y0
+                               0, //f0
+                               &fill_color, //function
+                               flags_total | IN_WINDOW | NOT_READABLE, //flags
+                               &color //data
+                       );
+                       if (r!=0)
                        {
-                               //newdata[4*(i+X0*j)+0]=0xFF;
-                               //newdata[4*(i+X0*j)+1]=0xFF;
-                               //newdata[4*(i+X0*j)+2]=0xFF;
-                               //newdata[4*(i+X0*j)+3]=0x00;
+                               *err = CONVERT_FAILED;
+                               return r;
                        }
                }
        }
-       //if(!ilSetData(newdata))mustard(OUTPIX_MUSTARD);
        
-       //printf("%d\n",iCurImage);
-       if(!ilOverlayImage(inPix,X01+(X02-inX)/2,Y0-inY-(Y01+(Y02-inY)/2),0))mustard(FAIL);
-       if(!ilOverlayImage(npbPix,0,0,0))mustard(FAIL);
-       if(!ilSave(IL_PNG,path))mustard(OUTPIX_MUSTARD);
-}
-
-void npbottify1(const char *path)
-{
-       //newdata= new ILubyte[X0*Y0*4];
-       ilGenImages(1, &outPix);
-       outH=true;
-       loadnpb(NPBPIX1);
-       ilBindImage(outPix);
-       if(!ilCopyImage(npbPix))mustard(FAIL);
-       //if(!ilTexImage(X1,Y1,1,4,IL_RGBA,IL_UNSIGNED_BYTE,NULL))mustard(OUTPIX_MUSTARD);
-       //if(!ilConvertImage(IL_RGBA,IL_UNSIGNED_BYTE))mustard(OUTPIX_MUSTARD);
-       newdata=ilGetData();
-       for(unsigned long i=0;i<X1;++i)
+       /* 4: insert npb before */
+       
+       if (!npb_after)
        {
-               for(unsigned long j=0;j<Y1;++j)
+               id[0] = 1; //npb
+               id[1] = 2; //total
+               x0[0] = 0;
+               x0[1] = x0_npb;
+               y0[0] = 0;
+               y0[1] = y0_npb;
+               flags[0] = flags_npb | IN_WINDOW;
+               flags[1] = flags_total | IN_WINDOW;
+               
+               r = perform_action(
+                       2, //n
+                       id,
+                       x0, y0, f0,
+                       width_npb, height_npb, 1,
+                       &copy_pixels,
+                       flags,
+                       &max //data
+               );
+               if (r!=0)
                {
-                       if((i>=X11+(X12-inX)/2)&&
-                          (i< X11+(X12-inX)/2+inX)&&
-                          (j>=Y11+(Y12-inY)/2)&&
-                          (j< Y11+(Y12-inY)/2+inY))
-                       {
-                               newdata[4*(i+X1*j)+0]=0xFF;
-                               newdata[4*(i+X1*j)+1]=0xFF;
-                               newdata[4*(i+X1*j)+2]=0xFF;
-                               newdata[4*(i+X1*j)+3]=0xFF;
-                       }
-                       else if((i>=X11)&&(i<X11+X12)&&
-                               (j>=Y11)&&(j<Y11+Y12))
-                       {
-                               newdata[4*(i+X1*j)+0]=0x00;
-                               newdata[4*(i+X1*j)+1]=0x00;
-                               newdata[4*(i+X1*j)+2]=0x00;
-                               newdata[4*(i+X1*j)+3]=0xFF;
-                       }
-                       else
-                       {
-                               //
-                       }
+                       *err = CONVERT_FAILED;
+                       return r;
                }
        }
-       //if(!ilSetData(newdata))mustard(OUTPIX_MUSTARD);
        
-       //printf("%d\n",iCurImage);
-       if(!ilOverlayImage(inPix,X11+(X12-inX)/2,Y1-inY-(Y11+(Y12-inY)/2),0))mustard(FAIL);
-       //(!ilOverlayImage(npbPix,0,0,0))mustard(FAIL);
-       if(!ilSave(IL_PNG,path))mustard(OUTPIX_MUSTARD);
-}
-
-void npbottify2(const char *path)
-{
-       unsigned long i,j;
-       outX=(X21+inX+2>X2)?(X21+inX+2):X2;
-       outY=(Y21+inY+2>Y2)?(Y21+inY+2):Y2;
-       ilGenImages(1, &outPix);
-       outH=true;
-       loadnpb(NPBPIX2);
-       newdata=ilGetData();
-       ilBindImage(outPix);
-       if(!ilTexImage(outX,outY,1,4,IL_RGBA,IL_UNSIGNED_BYTE,NULL))mustard(OUTPIX_MUSTARD);
-       if(!ilClearImage())mustard(FAIL);
-       ilSetPixels(outX-X2,0,0,X2,Y2,1,IL_RGBA,IL_UNSIGNED_BYTE,newdata);
-       newdata=ilGetData();
-       for(i=outX-X21-inX-2;i<outX-X21+2;++i)
+       /* 5: fill_background */
+       
+       if (fill_white)
        {
-               //printf("i=%lu\n",i);
-               for(j=Y21-2;j<Y21+inY+2;++j)
+               color.red   = max;
+               color.green = max;
+               color.blue  = max;
+               color.alpha = max;
+               
+               r = perform_action_1picture(
+                       2, //id
+                       fixed_frame ? space_l + external_border : x0_content_global, //x0
+                       fixed_frame ? space_t + external_border: y0_content_global, //y0
+                       0, //f0
+                       fixed_frame ? (space_r - space_l + 1) : width_content, //width
+                       fixed_frame ? (space_b - space_t + 1) : height_content, //height
+                       1, //frames
+                       &fill_color, //function
+                       flags_total | IN_WINDOW | NOT_READABLE, //flags
+                       &color //data
+               );
+               if (r!=0)
                {
-                       //printf("i=%lu j=%lu\n",i,j);
-                       if((i==outX-X21-inX-2)||(i==outX-X21-inX-1)||
-                          (i==outX-X21    +1)||(i==outX-X21      )||
-                          (j==     Y21    -2)||(j==     Y21    -1)||
-                          (j==     Y21+inY+1)||(j==     Y21+inY  ))
-                       {
-                               newdata[4*(i+outX*j)+0]=0x00;
-                               newdata[4*(i+outX*j)+1]=0x00;
-                               newdata[4*(i+outX*j)+2]=0x00;
-                               newdata[4*(i+outX*j)+3]=0xFF;   
-                       }
-                       else
-                       {
-                               newdata[4*(i+outX*j)+0]=0xFF;
-                               newdata[4*(i+outX*j)+1]=0xFF;
-                               newdata[4*(i+outX*j)+2]=0xFF;
-                               newdata[4*(i+outX*j)+3]=0xFF;
-                       }
+                       *err = CONVERT_FAILED;
+                       return r;
                }
        }
        
-       if(!ilOverlayImage(inPix,outX-X21-inX,outY-Y21-inY,0))mustard(FAIL);
-       
-       i=outX-X21-inX-2;
-       j=Y21-2;
-       newdata[4*(i+outX*j)+0]=0x00;
-       newdata[4*(i+outX*j)+1]=0x00;
-       newdata[4*(i+outX*j)+2]=0x00;
-       newdata[4*(i+outX*j)+3]=0x00;   
-       j=Y21+inY+1;
-       newdata[4*(i+outX*j)+0]=0x00;
-       newdata[4*(i+outX*j)+1]=0x00;
-       newdata[4*(i+outX*j)+2]=0x00;
-       newdata[4*(i+outX*j)+3]=0x00;   
-       i=outX-X21+1;
-       newdata[4*(i+outX*j)+0]=0x00;
-       newdata[4*(i+outX*j)+1]=0x00;
-       newdata[4*(i+outX*j)+2]=0x00;
-       newdata[4*(i+outX*j)+3]=0x00;   
-       j=Y21-2;
-       newdata[4*(i+outX*j)+0]=0x00;
-       newdata[4*(i+outX*j)+1]=0x00;
-       newdata[4*(i+outX*j)+2]=0x00;
-       newdata[4*(i+outX*j)+3]=0x00;   
-       
-       i=outX-X21-inX;
-       j=Y21;
-       newdata[4*(i+outX*j)+0]=0x00;
-       newdata[4*(i+outX*j)+1]=0x00;
-       newdata[4*(i+outX*j)+2]=0x00;
-       newdata[4*(i+outX*j)+3]=0xFF;   
-       j=Y21+inY-1;
-       newdata[4*(i+outX*j)+0]=0x00;
-       newdata[4*(i+outX*j)+1]=0x00;
-       newdata[4*(i+outX*j)+2]=0x00;
-       newdata[4*(i+outX*j)+3]=0xFF;   
-       i=outX-X21-1;
-       newdata[4*(i+outX*j)+0]=0x00;
-       newdata[4*(i+outX*j)+1]=0x00;
-       newdata[4*(i+outX*j)+2]=0x00;
-       newdata[4*(i+outX*j)+3]=0xFF;   
-       j=Y21;
-       newdata[4*(i+outX*j)+0]=0x00;
-       newdata[4*(i+outX*j)+1]=0x00;
-       newdata[4*(i+outX*j)+2]=0x00;
-       newdata[4*(i+outX*j)+3]=0xFF;
-       
-       if(!ilSave(IL_PNG,path))mustard(OUTPIX_MUSTARD);
-
+       /* 6: insert content */
        
-}
-
-void mustard(int mustard)
-{
-       switch(mustard)
+       id[0] = 0; //content
+       id[1] = 2; //total
+       x0[0] = x0_content_own;
+       x0[1] = x0_content_global;
+       y0[0] = y0_content_own;
+       y0[1] = y0_content_global;
+       flags[0] = flags_content | IN_WINDOW;
+       flags[1] = flags_total | IN_WINDOW;
+       
+       r = perform_action(
+               2, //n
+               id,
+               x0, y0, f0,
+               width_content, height_content, 1,
+               &copy_pixels,
+               flags,
+               &max //data
+       );
+       if (r!=0)
        {
-       case 0:
-               if(q) printf("NewpixbOTTified!\n");break;
-       case ARGUMENT_MUSTARD:
-               if(q) printf("npb inPix outPix [q]\n");break;
-       case INPIX_MUSTARD:
-               if(q) printf("inPIX mustard.\n");break;
-       case OUTPIX_MUSTARD:
-               if(q) printf("outPIX mustard.\n");break;
-       case NPBPIX_MUSTARD:
-               if(q) printf("npbPIX mustard.\n");break;
-       case SEAISH_MUSTARD:
-               if(q) printf("Seaishness is mustard.\n");break;
-       case ANIMATED_MUSTARD:
-               if(q) printf("Animation is mustard.\n");break;
-       default:
-               if (q) printf("Ch*rpin* mustard mustaard!\n");
+               *err = CONVERT_FAILED;
+               return r;
        }
-       if(inH)
-               ilDeleteImages(1, &inPix);
-       if(outH)
+       
+       /* 7: draw border */
+       
+       if (new_border >0)
        {
-               ilDeleteImages(1, &outPix);
-               //delete[] newdata;
+               color.red   = 0;
+               color.green = 0;
+               color.blue  = 0;
+               color.alpha = max;
+               
+               r = perform_action_1picture( //top
+                       2, //id
+                       corners ? (x0_border + 1) : x0_border, //x0
+                       y0_border, //y0
+                       0, //f0
+                       corners ? (width_border - 2) : width_border, //width
+                       new_border, //height
+                       1, //frames
+                       &fill_color, //function
+                       flags_total | IN_WINDOW | NOT_READABLE, //flags
+                       &color //data
+               );
+               if (r!=0)
+               {
+                       *err = CONVERT_FAILED;
+                       return r;
+               }
+               
+               r = perform_action_1picture( //bottom
+                       2, //id
+                       corners ? (x0_border + 1) : x0_border, //x0
+                       y0_border + height_border - new_border, //y0
+                       0, //f0
+                       corners ? (width_border - 2) : width_border, //width
+                       new_border, //height
+                       1, //frames
+                       &fill_color, //function
+                       flags_total | IN_WINDOW | NOT_READABLE, //flags
+                       &color //data
+               );
+               if (r!=0)
+               {
+                       *err = CONVERT_FAILED;
+                       return r;
+               }
+               
+               r = perform_action_1picture( //left
+                       2, //id
+                       x0_border, //x0
+                       corners ? (y0_border + 1) : y0_content_global , //y0
+                       0, //f0
+                       new_border, //width
+                       corners ? (height_border - 2) : height_content, //height
+                       1, //frames
+                       &fill_color, //function
+                       flags_total | IN_WINDOW | NOT_READABLE, //flags
+                       &color //data
+               );
+               if (r!=0)
+               {
+                       *err = CONVERT_FAILED;
+                       return r;
+               }
+               
+               r = perform_action_1picture( //right
+                       2, //id
+                       x0_border + width_border - new_border, //x0
+                       corners ? (y0_border + 1) : y0_content_global , //y0
+                       0, //f0
+                       new_border, //width
+                       corners ? (height_border - 2) : height_content, //height
+                       1, //frames
+                       &fill_color, //function
+                       flags_total | IN_WINDOW | NOT_READABLE, //flags
+                       &color //data
+               );
+               if (r!=0)
+               {
+                       *err = CONVERT_FAILED;
+                       return r;
+               }
        }
-       if(npbH)
-               ilDeleteImages(1, &npbPix);
-       exit(mustard);
+       
+       /* 8: insert npb after */
+       
+       if (npb_after)
+       {
+               id[0] = 1; //npb
+               id[1] = 2; //total
+               x0[0] = 0;
+               x0[1] = x0_npb;
+               y0[0] = 0;
+               y0[1] = y0_npb;
+               flags[0] = flags_npb | IN_WINDOW;
+               flags[1] = flags_total | IN_WINDOW;
+               
+               r = perform_action(
+                       2, //n
+                       id,
+                       x0, y0, f0,
+                       width_npb, height_npb, 1,
+                       &copy_pixels,
+                       flags,
+                       &max //data
+               );
+               if (r!=0)
+               {
+                       *err = CONVERT_FAILED;
+                       return r;
+               }
+       }
+       
+       /* 9: ok, done, now save */
+       
+       r = save_picture(2, argv[optind+1], flags_total);
+       if (r!=0)
+       {
+               *err = SAVE_FAILED;
+               return r;
+       }
+       
+       return 0;
 }
-       */