0 | 2 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,76 @@ |
1 |
+#!/usr/bin/pike |
|
2 |
+/* |
|
3 |
+ * collage.pike |
|
4 |
+ * |
|
5 |
+ * Makes a poster-sized collage of all the photos on the specified directory |
|
6 |
+ * |
|
7 |
+ * History: |
|
8 |
+ * 28/06/2019 Creation |
|
9 |
+ * |
|
10 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
11 |
+ * This program is distributed under the terms of the GNU GPL v2.1+ |
|
12 |
+ */ |
|
13 |
+ |
|
14 |
+int |
|
15 |
+main(int argc, array(string) argv) |
|
16 |
+{ |
|
17 |
+ int a4w,a4h; |
|
18 |
+ string resfilename; |
|
19 |
+ int imgw,imgh; |
|
20 |
+ int dpi=300; |
|
21 |
+ int pw,ph; |
|
22 |
+ int framethickness; |
|
23 |
+ int total; |
|
24 |
+ Image.Image img,photo,frame; |
|
25 |
+ if(argc<5 || (argc>1 && argv[1]=="--help")) { |
|
26 |
+ Stdio.werror("Syntax: "+argv[0]+" <width_in_a4pages> <height_in_a4_pages> <resimage.png> <photodir> [<photodir2> [...]]\n"); |
|
27 |
+ Stdio.werror("Example: "+argv[0]+" 4 2 . result.png\n"); |
|
28 |
+ return(1); |
|
29 |
+ } |
|
30 |
+ a4w=(int)argv[1]; |
|
31 |
+ a4h=(int)argv[2]; |
|
32 |
+ resfilename=argv[3]; |
|
33 |
+ // A4 is 8.27in � 11.69in (equivalent to 210mm � 297mm) |
|
34 |
+ imgw=(a4w*dpi*827)/100; |
|
35 |
+ imgh=(a4h*dpi*1169)/100; |
|
36 |
+ // we want to fit approx. 4 photos in a a4, we calc the photo size |
|
37 |
+ pw=dpi*827*(a4w+a4h)/(100*16); |
|
38 |
+ ph=dpi*1169*(a4w+a4h)/(100*16); |
|
39 |
+ framethickness=pw/20; |
|
40 |
+ // resulting image |
|
41 |
+ img=Image.Image(imgw,imgh); |
|
42 |
+ // Put a nice bg |
|
43 |
+// TODO |
|
44 |
+ // add each photo |
|
45 |
+ total=0; |
|
46 |
+ foreach(argv[4..sizeof(argv)-1],string photodir) { |
|
47 |
+ foreach(get_dir(photodir),string e) { |
|
48 |
+ if(sizeof(e)<4 || !(e[sizeof(e)-4..sizeof(e)]==".png" || e[sizeof(e)-4..sizeof(e)]==".jpg")) { |
|
49 |
+ write("* (Ignoring "+e+")\n"); |
|
50 |
+ continue; |
|
51 |
+ } |
|
52 |
+ write("* Loading "+e+"...\n"); |
|
53 |
+ photo=Image.load(photodir+"/"+e); |
|
54 |
+ write("* Resizing...\n"); |
|
55 |
+ if(photo->xsize()>photo->ysize()) { /* landscape */ |
|
56 |
+ photo=photo->scale(2*pw,2*photo->ysize()*pw/photo->xsize()); |
|
57 |
+ } else { /* portrait */ |
|
58 |
+ photo=photo->scale(2*photo->xsize()*ph/photo->ysize(),2*ph); |
|
59 |
+ } |
|
60 |
+ write("* Drawing frame...\n"); |
|
61 |
+ frame=Image.Image(photo->xsize()+2*(2+framethickness),photo->ysize()+2*(2+framethickness),0,0,0); |
|
62 |
+ frame->box(2,2,frame->xsize()-1-2,frame->ysize()-1-2,255,255,255); |
|
63 |
+ frame->box(2*(1+framethickness),2*(1+framethickness),frame->xsize()-1-2*(1+framethickness),frame->ysize()-1-2*(1+framethickness),127,127,127); |
|
64 |
+ frame->paste(photo,2+framethickness,2+framethickness); |
|
65 |
+ // WARNING TODO: rotate, paste using layers |
|
66 |
+ frame=frame->scale(frame->xsize()/2,frame->ysize()/2); |
|
67 |
+ img->paste(frame,random(img->xsize()+photo->xsize())-photo->xsize()/2,random(img->ysize()+photo->ysize())-photo->ysize()/2); |
|
68 |
+ total++; |
|
69 |
+ } |
|
70 |
+ } |
|
71 |
+ // write result |
|
72 |
+ write("* Writing "+resfilename+"...\n"); |
|
73 |
+ Stdio.write_file(resfilename,Image.PNG.encode(img)); |
|
74 |
+ write("Composed "+total+" photos into "+resfilename+". Process finished.\n"); |
|
75 |
+ |
|
76 |
+} |
0 | 77 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,44 @@ |
1 |
+#!/usr/bin/pike |
|
2 |
+/* |
|
3 |
+ * cropper.pike |
|
4 |
+ * |
|
5 |
+ * Crom a NxM+i+j pngs into another png |
|
6 |
+ * |
|
7 |
+ * History: |
|
8 |
+ * 28/09/2020 Creation from tiler.pike |
|
9 |
+ * |
|
10 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
11 |
+ * This program is distributed under the terms of the GNU GPL v2.1+ |
|
12 |
+ */ |
|
13 |
+ |
|
14 |
+int |
|
15 |
+main(int argc, array(string) argv) |
|
16 |
+{ |
|
17 |
+ int xsize,ysize,xoff,yoff; |
|
18 |
+ string infilename; |
|
19 |
+ string destfilename; |
|
20 |
+ Image.Image result; |
|
21 |
+ if(argc<4 || (argc>1 && argv[1]=="--help")) { |
|
22 |
+ Stdio.werror("Syntax: "+argv[0]+" <crop_expression> <infile.png> <outfile.png>\n"); |
|
23 |
+ Stdio.werror("Example: "+argv[0]+" 200x300+50+20 file.png dest.png\n"); |
|
24 |
+ Stdio.werror("Example result: dest.png\n"); |
|
25 |
+ return(1); |
|
26 |
+ } |
|
27 |
+ write("* Cropping to "+argv[1]+"\n"); |
|
28 |
+ xsize=ysize=xoff=yoff; |
|
29 |
+ xsize=(int) (argv[1]/"x")[0]; |
|
30 |
+ if(sizeof(argv[1]/"x")>1) |
|
31 |
+ ysize=(int) (((argv[1]/"x")[1])/"+")[0]; |
|
32 |
+ if(sizeof(argv[1]/"+")>1) |
|
33 |
+ xoff=(int) (argv[1]/"+")[1]; |
|
34 |
+ if(sizeof(argv[1]/"+")>2) |
|
35 |
+ yoff=(int) (argv[1]/"+")[2]; |
|
36 |
+ infilename=argv[2]; |
|
37 |
+ destfilename=argv[3]; |
|
38 |
+ result=Image.load(infilename)->copy(xoff,yoff,xoff+xsize-1,yoff+ysize-1,255,255,255); |
|
39 |
+ write("* Writing "+destfilename+"...\n"); |
|
40 |
+ Stdio.write_file(destfilename,Image.PNG.encode(result)); |
|
41 |
+ write("* Finished successfully\n"); |
|
42 |
+ return(0); |
|
43 |
+} |
|
44 |
+ |
0 | 45 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,93 @@ |
1 |
+#!/usr/bin/pike |
|
2 |
+/* |
|
3 |
+ * jpgscanclean.pike |
|
4 |
+ * |
|
5 |
+ * Utility to clean the background of scanned pages (req. RGB page) |
|
6 |
+ * |
|
7 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
8 |
+ * The program is licensed under the terms of the MIT/X license. |
|
9 |
+ */ |
|
10 |
+ |
|
11 |
+int bgthreshold=64; // from 0 to 255 |
|
12 |
+int amplitude=15; // from 1 to 255 |
|
13 |
+ |
|
14 |
+int |
|
15 |
+main(int argc, array(string) argv) |
|
16 |
+{ |
|
17 |
+ Image.Image in,out,inhsv,indistance; |
|
18 |
+ string infile,outfile; |
|
19 |
+ if(argc!=3 || argv[argc-1]=="--help") { |
|
20 |
+ write("Syntax: "+argv[0]+" infile.jpg outfile.png\n"); |
|
21 |
+ return(1); |
|
22 |
+ } |
|
23 |
+ write(argv[1]+" -> "+argv[2]+"\n"); |
|
24 |
+ write("* Generating intermediate representations..."); |
|
25 |
+ infile=argv[1]; |
|
26 |
+ outfile=argv[2]; |
|
27 |
+ in=Image.load(infile); |
|
28 |
+ inhsv=in->copy()->rgb_to_hsv(); |
|
29 |
+ indistance=in->copy()->distancesq(255,255,255); |
|
30 |
+ out=Image.Image(in.xsize(),in.ysize()); |
|
31 |
+ // Guess the most used bg color |
|
32 |
+ write("done.\n* Guessing most used bg hue..."); |
|
33 |
+ array(int) hues=allocate(256); |
|
34 |
+ int x,y; |
|
35 |
+ int h,n,selh,seln,j; |
|
36 |
+ int c; |
|
37 |
+ for(y=0;y<in.ysize();y++) { |
|
38 |
+ for(x=0;x<in.xsize();x++) { |
|
39 |
+ c=indistance.getpixel(x,y)[0]; |
|
40 |
+ if(c<bgthreshold) { |
|
41 |
+ // possible bg |
|
42 |
+ c=inhsv.getpixel(x,y)[0]; |
|
43 |
+ hues[c]++; |
|
44 |
+ } |
|
45 |
+ } |
|
46 |
+ if(!(y%1000)) |
|
47 |
+ write("."); |
|
48 |
+ } |
|
49 |
+ for(selh=0,seln=0,h=0;h<256;h++) { |
|
50 |
+ for(n=0,j=-amplitude;j<amplitude;j++) { |
|
51 |
+ n+=hues[(h+256+j)%256]; |
|
52 |
+ } |
|
53 |
+ if(n>seln) { |
|
54 |
+ seln=n; |
|
55 |
+ selh=h; |
|
56 |
+ } |
|
57 |
+ } |
|
58 |
+ write(""+selh); |
|
59 |
+ // Clean image |
|
60 |
+ write(".\n* Cleaning image..."); |
|
61 |
+ int d; |
|
62 |
+ for(y=0;y<in.ysize();y++) { |
|
63 |
+ for(x=0;x<in.xsize();x++) { |
|
64 |
+ c=indistance.getpixel(x,y)[0]; |
|
65 |
+ h=inhsv.getpixel(x,y)[0]; |
|
66 |
+ // calc. hue distance to bg hue wrapping on the color wheel |
|
67 |
+ if(h<selh) { |
|
68 |
+ if((selh-h)<(h+256-selh)) |
|
69 |
+ d=selh-h; |
|
70 |
+ else |
|
71 |
+ d=h+256-selh; |
|
72 |
+ } else { |
|
73 |
+ if((h-selh)<(selh+256-h)) |
|
74 |
+ d=h-selh; |
|
75 |
+ else |
|
76 |
+ d=selh+256-h; |
|
77 |
+ } |
|
78 |
+ // heuristics |
|
79 |
+ if(c<bgthreshold && d<bgthreshold) { |
|
80 |
+ out.setpixel(x,y,255,255,255); |
|
81 |
+ } else { |
|
82 |
+ array(int) rgb=in.getpixel(x,y); |
|
83 |
+ out.setpixel(x,y,rgb[0],rgb[1],rgb[2]); |
|
84 |
+ } |
|
85 |
+ } |
|
86 |
+ if(!(y%1000)) |
|
87 |
+ write("."); |
|
88 |
+ } |
|
89 |
+ // Write result |
|
90 |
+ write("done.\n* Writing result to disk..."); |
|
91 |
+ Stdio.write_file(outfile,Image.PNG.encode(out)); |
|
92 |
+ write("done.\n* Process finished.\n"); |
|
93 |
+} |
0 | 94 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,82 @@ |
1 |
+#!/usr/bin/pike |
|
2 |
+/* |
|
3 |
+ * paster.pike |
|
4 |
+ * |
|
5 |
+ * Resize a png into another png |
|
6 |
+ * |
|
7 |
+ * History: |
|
8 |
+ * 28/09/2020 Creation from resizer.pike |
|
9 |
+ * |
|
10 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
11 |
+ * This program is distributed under the terms of the GNU GPL v2.1+ |
|
12 |
+ */ |
|
13 |
+ |
|
14 |
+int |
|
15 |
+main(int argc, array(string) argv) |
|
16 |
+{ |
|
17 |
+ int i; |
|
18 |
+ string geom; |
|
19 |
+ mapping imagemapping; |
|
20 |
+ int xsize,ysize; |
|
21 |
+ int xoff,yoff; |
|
22 |
+ string destfilename; |
|
23 |
+ Image.Image image,alpha; |
|
24 |
+ array(Image.Layer) layers=({}); |
|
25 |
+ Image.Layer l; |
|
26 |
+ if(argc<4 || (argc%2)!=0 || (argc>1 && argv[1]=="--help")) { |
|
27 |
+ Stdio.werror("Syntax: "+argv[0]+" <geom1> { <file1.png> | <htmlcolor1> } [<geom2> { <file2.png> | <htmlcolor2> } [...]] <outfile.png>\n"); |
|
28 |
+ Stdio.werror("Example: "+argv[0]+" 200x300+0+0 bg.png 150x0+25+25 image.png 100x1+0+0 \"#ff0000\" dest.png\n"); |
|
29 |
+ Stdio.werror("Example result: dest.png\n"); |
|
30 |
+ return(1); |
|
31 |
+ } |
|
32 |
+ destfilename=argv[argc-1]; |
|
33 |
+ write("* Loading images...\n"); |
|
34 |
+ for(i=1;(i+1)<argc;i+=2) { |
|
35 |
+ geom=argv[i]; |
|
36 |
+ if(sizeof(argv[i+1])>1 && argv[i+1][0]=='#') { |
|
37 |
+ string htmlcolor=argv[i+1]; |
|
38 |
+ int r,g,b,a; |
|
39 |
+ a=0; |
|
40 |
+ htmlcolor-="#"; |
|
41 |
+ sscanf(htmlcolor[0..1],"%x",r); |
|
42 |
+ sscanf(htmlcolor[2..3],"%x",g); |
|
43 |
+ sscanf(htmlcolor[4..5],"%x",b); |
|
44 |
+ if(sizeof(htmlcolor)>6) |
|
45 |
+ sscanf(htmlcolor[6..7],"%x",a); |
|
46 |
+write("r:"+r+" g:"+g+" b:"+b+" a:"+a+"\n"); |
|
47 |
+ image=Image.Image(1,1,r,g,b); |
|
48 |
+ imagemapping=([ "image":image, "alpha":Image.Image(1,1,255-a,255-a,255-a) ]); |
|
49 |
+ } else { |
|
50 |
+ imagemapping=Image._load(argv[i+1]); |
|
51 |
+ } |
|
52 |
+ xsize=ysize=xoff=yoff=0; |
|
53 |
+ xsize=(int) (geom/"x")[0]; |
|
54 |
+ if(sizeof(geom/"x")>1) |
|
55 |
+ ysize=(int) (((geom/"x")[1])/"+")[0]; |
|
56 |
+ if(sizeof(geom/"+")>1) |
|
57 |
+ xoff=(int) (geom/"+")[1]; |
|
58 |
+ if(sizeof(geom/"+")>2) |
|
59 |
+ yoff=(int) (geom/"+")[2]; |
|
60 |
+ image=imagemapping["image"]; |
|
61 |
+ alpha=imagemapping["alpha"]; |
|
62 |
+ xsize=(xsize!=0)?xsize:(ysize==0)?image->xsize():ysize*image->xsize()/image->ysize(); |
|
63 |
+ ysize=(ysize!=0)?ysize:(xsize==0)?image->ysize():xsize*image->ysize()/image->xsize(); |
|
64 |
+ if(xsize!=image->xsize() || ysize!=image->ysize()) { |
|
65 |
+ image=image->scale(xsize,ysize); |
|
66 |
+ if(!intp(alpha)) |
|
67 |
+ alpha=alpha->scale(xsize,ysize); |
|
68 |
+ } |
|
69 |
+ if(intp(alpha)) |
|
70 |
+ alpha=Image.Image(xsize,ysize)->clear(0,0,0); |
|
71 |
+ l=Image.Layer(image,alpha,"normal"); |
|
72 |
+ l->set_offset(xoff,yoff); |
|
73 |
+ layers+=({l}); |
|
74 |
+ } |
|
75 |
+ l=Image.lay(layers); |
|
76 |
+ l->set_offset(0,0); |
|
77 |
+ write("* Writing "+destfilename+"...\n"); |
|
78 |
+ Stdio.write_file(destfilename,Image.PNG.encode(l->image(),(["alpha":l->alpha()]))); |
|
79 |
+ write("* Finished successfully\n"); |
|
80 |
+ return(0); |
|
81 |
+} |
|
82 |
+ |
0 | 83 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,54 @@ |
1 |
+#!/usr/bin/pike |
|
2 |
+/* |
|
3 |
+ * resizer.pike |
|
4 |
+ * |
|
5 |
+ * Resize a png into another png |
|
6 |
+ * |
|
7 |
+ * History: |
|
8 |
+ * 28/09/2020 Creation from cropper.pike |
|
9 |
+ * |
|
10 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
11 |
+ * This program is distributed under the terms of the GNU GPL v2.1+ |
|
12 |
+ */ |
|
13 |
+ |
|
14 |
+int |
|
15 |
+main(int argc, array(string) argv) |
|
16 |
+{ |
|
17 |
+ int xsize,ysize; |
|
18 |
+ string infilename; |
|
19 |
+ string destfilename; |
|
20 |
+ mapping orig; |
|
21 |
+ Image.Image image,alpha,result; |
|
22 |
+ if(argc<4 || (argc>1 && argv[1]=="--help")) { |
|
23 |
+ Stdio.werror("Syntax: "+argv[0]+" <newwidthxnewheight> <infile.png> <outfile.png>\n"); |
|
24 |
+ Stdio.werror("Example: "+argv[0]+" 200x300 file.png dest.png\n"); |
|
25 |
+ Stdio.werror("Example: "+argv[0]+" 200x0 file.png dest.png\n"); |
|
26 |
+ Stdio.werror("Example: "+argv[0]+" 0x300 file.png dest.png\n"); |
|
27 |
+ Stdio.werror("Example result: dest.png\n"); |
|
28 |
+ return(1); |
|
29 |
+ } |
|
30 |
+ xsize=ysize=0; |
|
31 |
+ xsize=(int) (argv[1]/"x")[0]; |
|
32 |
+ if(sizeof(argv[1]/"x")>1) |
|
33 |
+ ysize=(int) (((argv[1]/"x")[1])/"+")[0]; |
|
34 |
+ infilename=argv[2]; |
|
35 |
+ destfilename=argv[3]; |
|
36 |
+ write("* Loading "+infilename+"\n"); |
|
37 |
+ orig=Image._load(infilename); |
|
38 |
+ image=orig["image"]; |
|
39 |
+ alpha=orig["alpha"]; |
|
40 |
+ xsize=(xsize!=0)?xsize:(ysize==0)?image->xsize():ysize*image->xsize()/image->ysize(); |
|
41 |
+ ysize=(ysize!=0)?ysize:(xsize==0)?image->ysize():xsize*image->ysize()/image->xsize(); |
|
42 |
+ write("* Resizing from "+image->xsize()+"x"+image->ysize()+" to "+xsize+"x"+ysize+"\n"); |
|
43 |
+ image=image->scale(xsize,ysize); |
|
44 |
+ if(!intp(alpha)) |
|
45 |
+ alpha=alpha->scale(xsize,ysize); |
|
46 |
+ write("* Writing "+destfilename+"...\n"); |
|
47 |
+ if(intp(alpha)) |
|
48 |
+ Stdio.write_file(destfilename,Image.PNG.encode(image)); |
|
49 |
+ else |
|
50 |
+ Stdio.write_file(destfilename,Image.PNG.encode(image,(["alpha":alpha]))); |
|
51 |
+ write("* Finished successfully\n"); |
|
52 |
+ return(0); |
|
53 |
+} |
|
54 |
+ |
0 | 55 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,50 @@ |
1 |
+#!/usr/bin/pike |
|
2 |
+/* |
|
3 |
+ * slicer.pike |
|
4 |
+ * |
|
5 |
+ * Slices a png in NxM different pngs |
|
6 |
+ * |
|
7 |
+ * History: |
|
8 |
+ * 28/06/2019 Creation |
|
9 |
+ * |
|
10 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
11 |
+ * This program is distributed under the terms of the GNU GPL v2.1+ |
|
12 |
+ */ |
|
13 |
+ |
|
14 |
+int |
|
15 |
+main(int argc, array(string) argv) |
|
16 |
+{ |
|
17 |
+ int a4w,a4h; |
|
18 |
+ int px,py; |
|
19 |
+ string origfilename; |
|
20 |
+ string resprefix; |
|
21 |
+ int x,y,total; |
|
22 |
+ Image.Image img,cropped; |
|
23 |
+ string outfilename; |
|
24 |
+ if(argc<4 || (argc>1 && argv[1]=="--help")) { |
|
25 |
+ Stdio.werror("Syntax: "+argv[0]+" <width_in_a4pages> <height_in_a4_pages> <origimage.png>\n"); |
|
26 |
+ Stdio.werror("Example: "+argv[0]+" 4 2 orig.png\n"); |
|
27 |
+ Stdio.werror("Example result: orig_0001.png ... orig_0008.png\n"); |
|
28 |
+ return(1); |
|
29 |
+ } |
|
30 |
+ a4w=(int)argv[1]; |
|
31 |
+ a4h=(int)argv[2]; |
|
32 |
+ origfilename=argv[3]; |
|
33 |
+ resprefix=(origfilename/".png")[0]; |
|
34 |
+ write("* Loading "+origfilename+"...\n"); |
|
35 |
+ img=Image.load(origfilename); |
|
36 |
+ px=img->xsize()/a4w; |
|
37 |
+ py=img->ysize()/a4h; |
|
38 |
+ for(total=0,y=0;y<a4h;y++) { |
|
39 |
+ for(x=0;x<a4w;x++) { |
|
40 |
+ total++; |
|
41 |
+ cropped=img->copy(x*px,y*py,(x+1)*px-1,(y+1)*py-1,255,255,255); |
|
42 |
+ outfilename=sprintf("%s_%05d.png",resprefix,total); |
|
43 |
+ write("* Writing "+outfilename+"...\n"); |
|
44 |
+ Stdio.write_file(outfilename,Image.PNG.encode(cropped)); |
|
45 |
+ } |
|
46 |
+ } |
|
47 |
+ write(""+total+" slices written. Process finished.\n"); |
|
48 |
+ return(0); |
|
49 |
+} |
|
50 |
+ |
0 | 51 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,62 @@ |
1 |
+#!/usr/bin/pike |
|
2 |
+/* |
|
3 |
+ * tiler.pike |
|
4 |
+ * |
|
5 |
+ * Tiles NxM different pngs into a single png |
|
6 |
+ * |
|
7 |
+ * History: |
|
8 |
+ * 1/07/2019 Creation |
|
9 |
+ * 5/11/2019 Fix erroneous 1-pixel border around every tile |
|
10 |
+ * |
|
11 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
12 |
+ * This program is distributed under the terms of the GNU GPL v2.1+ |
|
13 |
+ */ |
|
14 |
+ |
|
15 |
+int |
|
16 |
+main(int argc, array(string) argv) |
|
17 |
+{ |
|
18 |
+ int a4w,a4h; |
|
19 |
+ int maxx,maxy; |
|
20 |
+ int px,py; |
|
21 |
+ string destfilename; |
|
22 |
+ int total; |
|
23 |
+ Image.Image img,result; |
|
24 |
+ if(argc<4 || (argc>1 && argv[1]=="--help")) { |
|
25 |
+ Stdio.werror("Syntax: "+argv[0]+" <width_in_tiles> <height_in_tiles> <file1.png> [<file2.png> [...]] <destfile.png>\n"); |
|
26 |
+ Stdio.werror("Example: "+argv[0]+" 3 2 file1.png file2.png file3.png file4.png file5.png file6.png dest.png\n"); |
|
27 |
+ Stdio.werror("Example result: dest.png\n"); |
|
28 |
+ return(1); |
|
29 |
+ } |
|
30 |
+ a4w=(int)argv[1]; |
|
31 |
+ a4h=(int)argv[2]; |
|
32 |
+ destfilename=argv[sizeof(argv)-1]; |
|
33 |
+ array(string) infiles=argv[3..sizeof(argv)-2]; |
|
34 |
+ maxx=maxy=1; |
|
35 |
+ write("* Calculating tile size\n"); |
|
36 |
+ foreach(infiles, string f) { |
|
37 |
+ img=Image.load(f); |
|
38 |
+ if(img->xsize()>maxx) |
|
39 |
+ maxx=img->xsize(); |
|
40 |
+ if(img->ysize()>maxy) |
|
41 |
+ maxy=img->ysize(); |
|
42 |
+ } |
|
43 |
+ result=Image.Image(maxx*a4w,maxy*a4h,255,255,255); |
|
44 |
+ px=py=0; |
|
45 |
+ total=0; |
|
46 |
+ foreach(infiles, string f) { |
|
47 |
+ write("* Processing "+f+"...\n"); |
|
48 |
+ img=Image.load(f); |
|
49 |
+ result->paste(img,px*(maxx),py*(maxy)); |
|
50 |
+ px++; |
|
51 |
+ if(px>=a4w) { |
|
52 |
+ px=0; |
|
53 |
+ py++; |
|
54 |
+ } |
|
55 |
+ total++; |
|
56 |
+ } |
|
57 |
+ write("* Writing "+destfilename+"...\n"); |
|
58 |
+ Stdio.write_file(destfilename,Image.PNG.encode(result)); |
|
59 |
+ write("tiled "+total+" images into "+destfilename+". Process finished.\n"); |
|
60 |
+ return(0); |
|
61 |
+} |
|
62 |
+ |
0 | 63 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,56 @@ |
1 |
+#!/usr/bin/pike |
|
2 |
+/* |
|
3 |
+ * ttfwriter.pike |
|
4 |
+ * |
|
5 |
+ * Create a png with some text using the specified ttf font. |
|
6 |
+ * |
|
7 |
+ * History: |
|
8 |
+ * 27/10/2020 Creation from cropper.pike |
|
9 |
+ * |
|
10 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
11 |
+ * This program is distributed under the terms of the GNU GPL v2.1+ |
|
12 |
+ */ |
|
13 |
+ |
|
14 |
+int |
|
15 |
+main(int argc, array(string) argv) |
|
16 |
+{ |
|
17 |
+ string fontname; |
|
18 |
+ int fontsize; |
|
19 |
+ string htmlcolor; |
|
20 |
+ string text; |
|
21 |
+ string destfilename; |
|
22 |
+ Image.Image textimage; |
|
23 |
+ Image.Image colorimage; |
|
24 |
+ mapping(string:int) color; |
|
25 |
+ if(argc<5 || (argc>1 && argv[1]=="--help")) { |
|
26 |
+ Stdio.werror("Syntax: "+argv[0]+" <font.ttf> <fontsize> <htmlcolor> <text> <outfile.png>\n"); |
|
27 |
+ Stdio.werror("Example: "+argv[0]+" font.ttf 16 \"#000000\" \"Text\" dest.png\n"); |
|
28 |
+ Stdio.werror("Example with alpha: "+argv[0]+" font.ttf 16 \"#000000a0\" \"Text\" dest.png\n"); |
|
29 |
+ return(1); |
|
30 |
+ } |
|
31 |
+ fontname=argv[1]; |
|
32 |
+ fontsize=(int)argv[2]; |
|
33 |
+ htmlcolor=argv[3]; |
|
34 |
+ text=argv[4]; |
|
35 |
+ destfilename=argv[5]; |
|
36 |
+ write("* Loading font "+fontname+"...\n"); |
|
37 |
+ Image.Fonts.set_font_dirs( ({"."}) ); |
|
38 |
+ Image.Fonts.Font font=Image.Fonts.Font(fontname,fontsize); |
|
39 |
+ write("* Parsing color...\n"); |
|
40 |
+ int r,g,b,a=0; |
|
41 |
+ htmlcolor-="#"; |
|
42 |
+ sscanf(htmlcolor[0..1],"%x",r); |
|
43 |
+ sscanf(htmlcolor[2..3],"%x",g); |
|
44 |
+ sscanf(htmlcolor[4..5],"%x",b); |
|
45 |
+ if(sizeof(htmlcolor)>6) |
|
46 |
+ sscanf(htmlcolor[6..7],"%x",a); |
|
47 |
+ color=(["r":r,"g":g,"b":b,"a":a]); |
|
48 |
+ write("* Rendering text...\n"); |
|
49 |
+ textimage=font->write(text)*((255.0-color["a"])/255.0); |
|
50 |
+ colorimage=Image.Image(textimage->xsize(),textimage->ysize())->clear(color["r"],color["g"],color["b"]); |
|
51 |
+ write("* Writing "+destfilename+"...\n"); |
|
52 |
+ Stdio.write_file(destfilename,Image.PNG.encode(colorimage,(["alpha":textimage]))); |
|
53 |
+ write("* Finished successfully\n"); |
|
54 |
+ return(0); |
|
55 |
+} |
|
56 |
+ |