/*
npb.c
Take a picture and add a newpixbot to it!
-29.11.2022
+30.11.2022
Copyright (C) 2013 - 2015, 2022 Balthasar Szczepański
#include <stdint.h>
#include <getopt.h>
+#include <errno.h>
#include "core.h"
#include "npb.h"
#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
+
+#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 265
+#define NPB_403_T 261
+#define NPB_403_B 261
char NPB_MISSING_ARGS[] = "Missing parameters.\nnpb [-o -4 -r -b -c] inPix outPix\n";
uint_fast8_t corners = 0;
uint_fast8_t fullsize = 0;
uint_fast8_t fill_white = 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;
ILuint cut_border = 0;
ILuint new_border = 2;
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'},
int opt;
int r;
+ /* we get options first */
+
optind = argi;
while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1)
{
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;
break;
case 'c':
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;
+ border_outside = 1;
+ fill_white = 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;
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;
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;
}
-
-
+
+ /* load selected npb */
+
+ r = load_picture_mem(1, npb_pix, npb_size, &(info_npb), &(flags_npb));
+ if (r)
+ {
+ *err = LOAD_FAILED;
+ return r;
+ }
+
+ /* determine rectangle of content with new border */
+
+ if (border_outside)
+ {
+ width_border = width_content;
+ height_border = height_content;
+ }
+ else
+ {
+ 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_width;
+ 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
+ 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 */
+
+ if (border_outside)
+ {
+ x0_content_global = x0_border;
+ y0_content_global = y0_border;
+ }
+ else
+ {
+ 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 (border_outside)
+ {
+ width_total += 2 * new_border;
+ height_total += 2 * new_border;
+ x0_border += new_border;
+ y0_border += new_border;
+ x0_content_global += new_border;
+ y0_content_global += new_border;
+ x0_npb += new_border;
+ y0_npb += new_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 = (border_outside && fill_white) ? max : 0;
+
+ r = perform_action_1picture(
+ 2, //id
+ border_outside ? new_border : 0, //x0
+ border_outside ? new_border : 0, //y0
+ 0, //f0
+ border_outside ? (width_total - 2 * new_border) : width_total, //width
+ border_outside ? (height_total - 2 * new_border) : height_total, //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 (border_outside && (new_border >0))
+ {
+ 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
+ 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
+ 0, //x0
+ height_total - new_border, //y0
+ 0, //f0
+ width_total, //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
+ 0, //x0
+ new_border, //y0
+ 0, //f0
+ new_border, //width
+ height_total - 2*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( //right
+ 2, //id
+ width_total - new_border, //x0
+ new_border, //y0
+ 0, //f0
+ new_border, //width
+ height_total - 2*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;
+ }
+
+ if (corners)
+ {
+ r = perform_action_1picture_1pixel( //top-left
+ 2, //id
+ new_border, //x0
+ new_border, //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 - new_border - 1, //x0
+ new_border, //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( //bottom-right
+ 2, //id
+ width_total - new_border - 1, //x0
+ height_total - new_border - 1, //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( //bottom-left
+ 2, //id
+ new_border, //x0
+ height_total - new_border - 1, //y0
+ 0, //f0
+ &fill_color, //function
+ flags_total | IN_WINDOW | NOT_READABLE, //flags
+ &color //data
+ );
+ if (r!=0)
+ {
+ *err = CONVERT_FAILED;
+ return r;
+ }
+ }
+ }
+
+ /* 4: insert npb before */
+
+ 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,
+ ©_pixels,
+ flags,
+ &max //data
+ );
+ if (r!=0)
+ {
+ *err = CONVERT_FAILED;
+ return r;
+ }
+ }
+
+ /* 5: fill_background */
+
+ if ((!border_outside) && fill_white)
+ {
+ color.red = max;
+ color.green = max;
+ color.blue = max;
+ color.alpha = max;
+
+ r = perform_action_1picture(
+ 2, //id
+ fixed_frame ? space_l : x0_content_global, //x0
+ fixed_frame ? space_t : 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)
+ {
+ *err = CONVERT_FAILED;
+ return r;
+ }
+ }
+
+ /* 6: insert content */
+
+ 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,
+ ©_pixels,
+ flags,
+ &max //data
+ );
+ if (r!=0)
+ {
+ *err = CONVERT_FAILED;
+ return r;
+ }
+
+ /* 7: draw border */
+
+ if ((!border_outside) && (new_border >0))
+ {
+ 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;
+ }
+ }
+
+ /* 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,
+ ©_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;
}
-
+/*
#define INPIX_MUSTARD 1
#define OUTPIX_MUSTARD 2
#define NPBPIX_MUSTARD 3