Browse code

bugfix: add missing initialization for flagjpeg in util_imgsave

Dario Rodriguez authored on 06/02/2022 15:46:14
Showing 1 changed files
... ...
@@ -232,6 +232,7 @@ util_imgsave(char *filename, char *bufimg, int width, int height,int quality)
232 232
         if(filename==NULL || bufimg==NULL || width<=0 || height<=0)
233 233
                 return(-1); /* sanity check error */
234 234
         l=strlen(filename);
235
+        flagjpeg=0;
235 236
         if((l>=4
236 237
           && filename[l-4]=='.'
237 238
           && (filename[l-3]=='J' || filename[l-3]=='j')
Browse code

Minor tweak to help text

Dario Rodriguez authored on 06/02/2022 14:45:26
Showing 1 changed files
... ...
@@ -53,11 +53,11 @@ main(int argc, char *argv[])
53 53
         char *currentoutfilename;
54 54
         if(argc<2 || strcmp(argv[argc-1],"--help")==0) {
55 55
                 printf("Syntax: %s [-i] [-q jpegquality] [-n identitylevel] {identity | lutfile[,lutfile[,...]]} { identity | infile1 } [infile2 [...]] -o outfile\n",argv[0]);
56
+                printf("NOTE: -i makes the program interpolate the LUTs.\n");
56 57
                 printf("Example: %s haldclut.png sprite.png -o result.png\n",argv[0]);
57 58
                 printf("Example: %s -i haldclut.png sprite.png -o result.png\n",argv[0]);
58 59
                 printf("Example: %s -n 16 identity identity -o identity.png\n",argv[0]);
59 60
                 printf("Example: %s -q 85 haldclut.png infile.png -o outfile.jpg\n",argv[0]);
60
-                printf("NOTE: -i makes the program interpolate the LUTs.\n");
61 61
                 return(1);
62 62
         }
63 63
         /* parse arguments */
Browse code

Fix warnings related to jpg load

Dario Rodriguez authored on 06/02/2022 14:43:59
Showing 1 changed files
... ...
@@ -492,12 +492,12 @@ util_jpgsave(char *filename, char *bufimg, int width, int height,int quality)
492 492
         jpeg_start_compress(&cinfo,TRUE);
493 493
         while(cinfo.next_scanline<cinfo.image_height) {
494 494
                 ptr=(unsigned char *)(bufimg+cinfo.next_scanline*(width*4));
495
-                for(orig=ptr,dest=rowdata,i=0;i<width;i++,orig+=4,dest+=3) {
495
+                for(orig=ptr,dest=(unsigned char *)rowdata,i=0;i<width;i++,orig+=4,dest+=3) {
496 496
                         dest[0]=orig[0];
497 497
                         dest[1]=orig[1];
498 498
                         dest[2]=orig[2];
499 499
                 }
500
-                rowptrs[0]=rowdata;
500
+                rowptrs[0]=(JSAMPROW) rowdata;
501 501
                 jpeg_write_scanlines(&cinfo,rowptrs,1);
502 502
         }
503 503
         jpeg_finish_compress(&cinfo);
Browse code

Add jpeg support

Dario Rodriguez authored on 16/01/2022 19:30:36
Showing 1 changed files
... ...
@@ -13,18 +13,26 @@
13 13
 #include <stdlib.h>
14 14
 #include <unistd.h>
15 15
 #include <string.h>
16
+#include <setjmp.h>
17
+#include <sys/types.h>
18
+#include <sys/stat.h>
19
+#include <fcntl.h>
16 20
 #include <math.h>
17 21
 #include <png.h>
22
+#include <jpeglib.h>
18 23
 
19 24
 #define DEFAULT_IDENTITYSIZE 12 /* Same as RawTherapee's HaldCLUTs, 1728x1728 AKA (12*12)*12x12*(12*12), equivalent to a cube with 144px wide sides*/
20 25
 #define DEFAULT_QUALITY 85
21
-/* #define JPEG_SUPPORTED */
22 26
 
23 27
 int luttool_applylut(char *lutfilenamelist,char *infilename, char *outfilename,int quality,int identitysize,int flaginterpolatelut);
24 28
 
29
+int util_imgload(char *filename, char **bufimg, int *sizebufimg, int *width, int *height);
30
+int util_imgsave(char *filename, char *bufimg, int width, int height,int quality);
25 31
 int util_pnginfo(char *filename, int *width, int *height);
26 32
 int util_pngload(char *filename, char **bufimg, int *sizebufimg, int *width, int *height);
27 33
 int util_pngsave(char *filename, char *bufimg, int width, int height);
34
+int util_jpgload(char *filename, char **bufimg, int *sizebufimg, int *width, int *height);
35
+int util_jpgsave(char *filename, char *bufimg, int width, int height,int quality);
28 36
 int util_identitygen(char **bufimg, int *sizebufimg, int identitysize, int *width, int *height);
29 37
 int luttool_rgba2lut4096(char *rgba, int width, int height, char **lut4096, int *sizelut4096);
30 38
 int luttool_rgba2lut4096_interpolated(char *rgba, int width, int height, char **lut4096, int *sizelut4096);
... ...
@@ -44,20 +52,12 @@ main(int argc, char *argv[])
44 52
         char bufoutfilename[1024];
45 53
         char *currentoutfilename;
46 54
         if(argc<2 || strcmp(argv[argc-1],"--help")==0) {
47
-#ifdef JPEG_SUPPORTED
48 55
                 printf("Syntax: %s [-i] [-q jpegquality] [-n identitylevel] {identity | lutfile[,lutfile[,...]]} { identity | infile1 } [infile2 [...]] -o outfile\n",argv[0]);
49 56
                 printf("Example: %s haldclut.png sprite.png -o result.png\n",argv[0]);
50 57
                 printf("Example: %s -i haldclut.png sprite.png -o result.png\n",argv[0]);
51 58
                 printf("Example: %s -n 16 identity identity -o identity.png\n",argv[0]);
52 59
                 printf("Example: %s -q 85 haldclut.png infile.png -o outfile.jpg\n",argv[0]);
53 60
                 printf("NOTE: -i makes the program interpolate the LUTs.\n");
54
-#else
55
-                printf("Syntax: %s [-n identitylevel] {identity | lutfile[,lutfile[,...]]} { identity | infile1 } [infile2 [...]] -o outfile\n",argv[0]);
56
-                printf("Example: %s haldclut.png sprite.png -o result.png\n",argv[0]);
57
-                printf("Example: -i %s haldclut.png sprite.png -o result.png\n",argv[0]);
58
-                printf("Example: %s -n 16 identity identity -o identity.png\n",argv[0]);
59
-                printf("NOTE: -i makes the program interpolate the LUTs.\n");
60
-#endif
61 61
                 return(1);
62 62
         }
63 63
         /* parse arguments */
... ...
@@ -153,7 +153,7 @@ luttool_applylut(char *lutlist,char *infilename, char *outfilename,int quality,i
153 153
                  if(util_identitygen(&imgbuf,&sizeimgbuf,identitysize,&imgwidth,&imgheight)==-1)
154 154
                          in_error=1;
155 155
         } else {
156
-                if(util_pngload(infilename,&imgbuf,&sizeimgbuf,&imgwidth,&imgheight)!=0)
156
+                if(util_imgload(infilename,&imgbuf,&sizeimgbuf,&imgwidth,&imgheight)!=0)
157 157
                         in_error=1;
158 158
         }
159 159
         /* apply all luts */
... ...
@@ -170,7 +170,7 @@ luttool_applylut(char *lutlist,char *infilename, char *outfilename,int quality,i
170 170
                                 break; /* couldn't generate identity lut */
171 171
                         }
172 172
                 } else {
173
-                        if(util_pngload(filename,&lutbuf,&sizelutbuf,&lutwidth,&lutheight)==-1) {
173
+                        if(util_imgload(filename,&lutbuf,&sizelutbuf,&lutwidth,&lutheight)==-1) {
174 174
                                 in_error=1;
175 175
                                 break; /* couldn't load lut */
176 176
                         }
... ...
@@ -191,7 +191,7 @@ luttool_applylut(char *lutlist,char *infilename, char *outfilename,int quality,i
191 191
         }
192 192
         /* save the result */
193 193
         if(in_error==0) {
194
-                if(util_pngsave(outfilename,imgbuf,imgwidth,imgheight)!=0)
194
+                if(util_imgsave(outfilename,imgbuf,imgwidth,imgheight,quality)!=0)
195 195
                         in_error=1; /* couldn't write */
196 196
         }
197 197
         /* cleanup and exit */
... ...
@@ -204,7 +204,52 @@ luttool_applylut(char *lutlist,char *infilename, char *outfilename,int quality,i
204 204
         return((in_error!=0)?-1:0);
205 205
 }
206 206
 
207
+int
208
+util_imgload(char *filename, char **bufimg, int *sizebufimg, int *width, int *height)
209
+{
210
+        int fd;
211
+        char buf[8];
212
+        if((fd=open(filename,O_RDONLY))==-1
213
+          || read(fd,buf,sizeof(buf))<sizeof(buf)) {
214
+                if(fd!=-1)
215
+                        close(fd),fd=-1;
216
+                return(-1); /* couldn't open file for reading */
217
+        }
218
+        close(fd),fd=-1;
219
+        if(memcmp(buf,"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a",8)==0) { /* PNG magic */
220
+                return(util_pngload(filename,bufimg,sizebufimg,width,height));
221
+        } else if(memcmp(buf,"\xff\xd8",2)==0) { /* EXIF magic */
222
+                return(util_jpgload(filename,bufimg,sizebufimg,width,height));
223
+        }
224
+        return(-1); /* file type not recognized */
225
+}
207 226
 
227
+int
228
+util_imgsave(char *filename, char *bufimg, int width, int height,int quality)
229
+{
230
+        int l;
231
+        int flagjpeg;
232
+        if(filename==NULL || bufimg==NULL || width<=0 || height<=0)
233
+                return(-1); /* sanity check error */
234
+        l=strlen(filename);
235
+        if((l>=4
236
+          && filename[l-4]=='.'
237
+          && (filename[l-3]=='J' || filename[l-3]=='j')
238
+          && (filename[l-2]=='P' || filename[l-2]=='p')
239
+          && (filename[l-1]=='G' || filename[l-1]=='g'))
240
+          || (l>=5
241
+          && filename[l-5]=='.'
242
+          && (filename[l-4]=='J' || filename[l-4]=='j')
243
+          && (filename[l-3]=='P' || filename[l-3]=='p')
244
+          && (filename[l-2]=='e' || filename[l-2]=='e')
245
+          && (filename[l-1]=='G' || filename[l-1]=='g'))) {
246
+                flagjpeg=1;
247
+        }
248
+        /* use png as default format; only use jpg if file extension says so */
249
+        if(flagjpeg)
250
+                return(util_jpgsave(filename,bufimg,width,height,quality));
251
+        return(util_pngsave(filename,bufimg,width,height));
252
+}
208 253
 
209 254
 int
210 255
 util_pnginfo(char *filename, int *width, int *height)
... ...
@@ -322,6 +367,147 @@ util_pngsave(char *filename, char *bufimg, int width, int height)
322 367
         return(0);
323 368
 }
324 369
 
370
+typedef struct jpegerrmgr_t {
371
+        struct jpeg_error_mgr pub;
372
+        jmp_buf setjmpbuf;
373
+} jpegerrmgr_t;
374
+
375
+static void
376
+util_jpgerrhandler(j_common_ptr cinfo)
377
+{
378
+        jpegerrmgr_t *errmgr;
379
+        errmgr=(jpegerrmgr_t *)cinfo->err;
380
+        longjmp(errmgr->setjmpbuf,1);
381
+}
382
+
383
+int
384
+util_jpgload(char *filename, char **bufimg, int *sizebufimg, int *width, int *height)
385
+{
386
+        FILE *f;
387
+        struct jpeg_decompress_struct cinfo;
388
+        jpegerrmgr_t errmgr;
389
+        int reqsize;
390
+        JSAMPROW rowptrs[1];
391
+        unsigned char *ptr,*orig,*dest;
392
+        if(filename==NULL || (bufimg==NULL && sizebufimg!=NULL) || (bufimg!=NULL && sizebufimg==NULL) || width==NULL || height==NULL)
393
+                return(-1); /* sanity check failed */
394
+        if((f=fopen(filename,"rb"))==NULL)
395
+                return(-1); /* couldn't open file */
396
+        memset(&cinfo,0,sizeof(cinfo));
397
+        cinfo.err=jpeg_std_error(&errmgr.pub);
398
+        errmgr.pub.error_exit=util_jpgerrhandler;
399
+        if(setjmp(errmgr.setjmpbuf)) {
400
+                jpeg_destroy_decompress(&cinfo);
401
+                if(f!=NULL)
402
+                        fclose(f),f=NULL;
403
+                return(-1); /* libjpeg couldn't decompress stream */
404
+        }
405
+        jpeg_create_decompress(&cinfo);
406
+        jpeg_stdio_src(&cinfo,f);
407
+        jpeg_read_header(&cinfo,TRUE);
408
+        jpeg_start_decompress(&cinfo);
409
+        *width=cinfo.output_width;
410
+        *height=cinfo.output_height;
411
+        /* special case: if bufimg==NULL, we only want the width/height */
412
+        if(bufimg==NULL) {
413
+                jpeg_destroy_decompress(&cinfo);
414
+                return(0); /* all done */
415
+        }
416
+        /* make sure is in a supported format */
417
+        if(cinfo.output_components!=3 && cinfo.output_components!=4) {
418
+                jpeg_destroy_decompress(&cinfo);
419
+                return(-1); /* we only support 8-bit RGB jpeg */
420
+        }
421
+        /* make sure we have enough space for the new image in 8-bit RGBA */
422
+        reqsize=(*width)*(*height)*4;
423
+        if(*sizebufimg<reqsize) {
424
+                char *newbufimg;
425
+                if((newbufimg=realloc(*bufimg,reqsize))==NULL) {
426
+                      jpeg_destroy_decompress(&cinfo);
427
+                      fclose(f),f=NULL;
428
+                      return(-1); /* insuf. mem. for resulting image */
429
+                }
430
+                *bufimg=newbufimg;
431
+                *sizebufimg=reqsize;
432
+        }
433
+        while(cinfo.output_scanline<cinfo.output_height) {
434
+                ptr=(unsigned char *)((*bufimg)+cinfo.output_scanline*((*width)*4));
435
+                rowptrs[0]=ptr;
436
+                jpeg_read_scanlines(&cinfo,rowptrs,1);
437
+                if(cinfo.output_components==3) {
438
+                        orig=ptr+((*width)-1)*3;
439
+                        dest=ptr+((*width)-1)*4;
440
+                        for(;orig>=ptr;orig-=3,dest-=4) {
441
+                                dest[0]=orig[0];
442
+                                dest[1]=orig[1];
443
+                                dest[2]=orig[2];
444
+                                dest[3]=0xff;
445
+                        }
446
+                }
447
+        }
448
+        jpeg_finish_decompress(&cinfo);
449
+        jpeg_destroy_decompress(&cinfo);
450
+        fclose(f),f=NULL;
451
+        return(0);
452
+}
453
+
454
+int
455
+util_jpgsave(char *filename, char *bufimg, int width, int height,int quality)
456
+{
457
+        FILE *f;
458
+        struct jpeg_compress_struct cinfo;
459
+        jpegerrmgr_t errmgr;
460
+        char *rowdata;
461
+        JSAMPROW rowptrs[1];
462
+        int i;
463
+        unsigned char *ptr,*orig,*dest;
464
+        if(filename==NULL || bufimg==NULL || width<=0 || height<=0 || quality<1 || quality>100)
465
+                return(-1); /* sanity check failed */
466
+        if((rowdata=malloc(width*3))==NULL)
467
+                return(-1);
468
+        if((f=fopen(filename,"wb"))==NULL) {
469
+                if(rowdata!=NULL)
470
+                        free(rowdata),rowdata=NULL;
471
+                return(-1); /* couldn't open file for writing */
472
+        }
473
+        memset(&cinfo,0,sizeof(cinfo));
474
+        cinfo.err=jpeg_std_error(&errmgr.pub);
475
+        errmgr.pub.error_exit=util_jpgerrhandler;
476
+        if(setjmp(errmgr.setjmpbuf)) {
477
+                if(f!=NULL)
478
+                        fclose(f),f=NULL;
479
+                if(rowdata!=NULL)
480
+                        free(rowdata),rowdata=NULL;
481
+                jpeg_destroy_compress(&cinfo);
482
+                return(-1); /* libjpeg couldn't compress stream */
483
+        }
484
+        jpeg_create_compress(&cinfo);
485
+        jpeg_stdio_dest(&cinfo,f);
486
+        cinfo.image_width=width;
487
+        cinfo.image_height=height;
488
+        cinfo.input_components=3;
489
+        cinfo.in_color_space=JCS_RGB;
490
+        jpeg_set_defaults(&cinfo);
491
+        jpeg_set_quality(&cinfo,quality,TRUE);
492
+        jpeg_start_compress(&cinfo,TRUE);
493
+        while(cinfo.next_scanline<cinfo.image_height) {
494
+                ptr=(unsigned char *)(bufimg+cinfo.next_scanline*(width*4));
495
+                for(orig=ptr,dest=rowdata,i=0;i<width;i++,orig+=4,dest+=3) {
496
+                        dest[0]=orig[0];
497
+                        dest[1]=orig[1];
498
+                        dest[2]=orig[2];
499
+                }
500
+                rowptrs[0]=rowdata;
501
+                jpeg_write_scanlines(&cinfo,rowptrs,1);
502
+        }
503
+        jpeg_finish_compress(&cinfo);
504
+        jpeg_destroy_compress(&cinfo);
505
+        fclose(f),f=NULL;
506
+        free(rowdata),rowdata=NULL;
507
+        return(0);
508
+}
509
+
510
+
325 511
 int
326 512
 util_identitygen(char **bufimg, int *sizebufimg, int identitysize, int *width, int *height)
327 513
 {
Browse code

Implement LUT interpolation

Dario Rodriguez authored on 16/01/2022 16:07:19
Showing 1 changed files
... ...
@@ -13,13 +13,14 @@
13 13
 #include <stdlib.h>
14 14
 #include <unistd.h>
15 15
 #include <string.h>
16
+#include <math.h>
16 17
 #include <png.h>
17 18
 
18 19
 #define DEFAULT_IDENTITYSIZE 12 /* Same as RawTherapee's HaldCLUTs, 1728x1728 AKA (12*12)*12x12*(12*12), equivalent to a cube with 144px wide sides*/
19 20
 #define DEFAULT_QUALITY 85
20 21
 /* #define JPEG_SUPPORTED */
21 22
 
22
-int luttool_applylut(char *lutfilenamelist,char *infilename, char *outfilename,int quality,int identitysize);
23
+int luttool_applylut(char *lutfilenamelist,char *infilename, char *outfilename,int quality,int identitysize,int flaginterpolatelut);
23 24
 
24 25
 int util_pnginfo(char *filename, int *width, int *height);
25 26
 int util_pngload(char *filename, char **bufimg, int *sizebufimg, int *width, int *height);
... ...
@@ -39,25 +40,36 @@ main(int argc, char *argv[])
39 40
         char *lutlist;
40 41
         int i;
41 42
         int flagseveralinfile;
43
+        int flaginterpolatelut;
42 44
         char bufoutfilename[1024];
43 45
         char *currentoutfilename;
44 46
         if(argc<2 || strcmp(argv[argc-1],"--help")==0) {
45 47
 #ifdef JPEG_SUPPORTED
46
-                printf("Syntax: %s [-q jpegquality] [-n identitylevel] {identity | lutfile[,lutfile[,...]]} { identity | infile1 } [infile2 [...]] -o outfile\n",argv[0]);
48
+                printf("Syntax: %s [-i] [-q jpegquality] [-n identitylevel] {identity | lutfile[,lutfile[,...]]} { identity | infile1 } [infile2 [...]] -o outfile\n",argv[0]);
47 49
                 printf("Example: %s haldclut.png sprite.png -o result.png\n",argv[0]);
50
+                printf("Example: %s -i haldclut.png sprite.png -o result.png\n",argv[0]);
48 51
                 printf("Example: %s -n 16 identity identity -o identity.png\n",argv[0]);
49 52
                 printf("Example: %s -q 85 haldclut.png infile.png -o outfile.jpg\n",argv[0]);
53
+                printf("NOTE: -i makes the program interpolate the LUTs.\n");
50 54
 #else
51 55
                 printf("Syntax: %s [-n identitylevel] {identity | lutfile[,lutfile[,...]]} { identity | infile1 } [infile2 [...]] -o outfile\n",argv[0]);
52 56
                 printf("Example: %s haldclut.png sprite.png -o result.png\n",argv[0]);
57
+                printf("Example: -i %s haldclut.png sprite.png -o result.png\n",argv[0]);
53 58
                 printf("Example: %s -n 16 identity identity -o identity.png\n",argv[0]);
59
+                printf("NOTE: -i makes the program interpolate the LUTs.\n");
54 60
 #endif
55 61
                 return(1);
56 62
         }
57 63
         /* parse arguments */
58 64
         identitysize=DEFAULT_IDENTITYSIZE;
59 65
         quality=DEFAULT_QUALITY;
60
-        for(firstarg=1;firstarg<(argc-1) && (strcmp(argv[firstarg],"-n")==0 || (strcmp(argv[firstarg],"-q")==0));) {
66
+        flaginterpolatelut=0;
67
+        for(firstarg=1
68
+          ;firstarg<(argc-1)
69
+          && (strcmp(argv[firstarg],"-n")==0
70
+          || strcmp(argv[firstarg],"-q")==0
71
+          || strcmp(argv[firstarg],"-i")==0)
72
+          ;) {
61 73
                 if(strcmp(argv[firstarg],"-n")==0) {
62 74
                         identitysize=atoi(argv[firstarg+1]);
63 75
                         if(identitysize<2 || identitysize>16) {
... ...
@@ -70,6 +82,9 @@ main(int argc, char *argv[])
70 82
                                 fprintf(stderr,"%s: ERROR: the parameter to -q must be between 1 and 100 (default: %i)\n",argv[0],DEFAULT_QUALITY);
71 83
                                 return(1);
72 84
                         }
85
+                } else if(strcmp(argv[firstarg],"-i")==0) {
86
+                        flaginterpolatelut=1;
87
+                        firstarg--; /* doesn't have param. */
73 88
                 }
74 89
                 firstarg+=2;
75 90
         }
... ...
@@ -107,7 +122,7 @@ main(int argc, char *argv[])
107 122
                         bufoutfilename[sizeof(bufoutfilename)-1]='\0';
108 123
                         currentoutfilename=bufoutfilename;
109 124
                 }
110
-                if(luttool_applylut(lutlist,argv[i],currentoutfilename,quality,identitysize)!=0) {
125
+                if(luttool_applylut(lutlist,argv[i],currentoutfilename,quality,identitysize,flaginterpolatelut)!=0) {
111 126
                         fprintf(stderr,"%s: ERROR: couldn't apply LUTs \"%s\" to \"%s\" or couldn't write \"%s\"\n",argv[0],lutlist,argv[i],currentoutfilename);
112 127
                         return(1);
113 128
                 }
... ...
@@ -116,7 +131,7 @@ main(int argc, char *argv[])
116 131
 }
117 132
 
118 133
 int
119
-luttool_applylut(char *lutlist,char *infilename, char *outfilename,int quality,int identitysize)
134
+luttool_applylut(char *lutlist,char *infilename, char *outfilename,int quality,int identitysize,int flaginterpolatelut)
120 135
 {
121 136
         char *curlut,*next;
122 137
         char filename[1024];
... ...
@@ -126,6 +141,7 @@ luttool_applylut(char *lutlist,char *infilename, char *outfilename,int quality,i
126 141
         int sizelutbuf,lutwidth,lutheight;
127 142
         int sizeimgbuf,imgwidth,imgheight;
128 143
         int sizergblutbuf;
144
+        int res;
129 145
         lutbuf=imgbuf=rgblutbuf=NULL;
130 146
         sizelutbuf=sizeimgbuf=sizergblutbuf=0;
131 147
         lutwidth=lutheight=imgwidth=imgheight=0;
... ...
@@ -159,7 +175,12 @@ luttool_applylut(char *lutlist,char *infilename, char *outfilename,int quality,i
159 175
                                 break; /* couldn't load lut */
160 176
                         }
161 177
                 }
162
-                if(luttool_rgba2lut4096(lutbuf, lutwidth, lutheight, &rgblutbuf, &sizergblutbuf)!=0) {
178
+                res=0;
179
+                if(flaginterpolatelut==0)
180
+                        res=luttool_rgba2lut4096(lutbuf, lutwidth, lutheight, &rgblutbuf, &sizergblutbuf);
181
+                else
182
+                        res=luttool_rgba2lut4096_interpolated(lutbuf, lutwidth, lutheight, &rgblutbuf, &sizergblutbuf);
183
+                if(res!=0) {
163 184
                         in_error=1;
164 185
                         break; /* couldn't process lut */
165 186
                 }
... ...
@@ -387,6 +408,92 @@ luttool_rgba2lut4096(char *rgba, int width, int height, char **lut4096, int *siz
387 408
         return(0);
388 409
 }
389 410
 
411
+int
412
+luttool_rgba2lut4096_interpolated(char *rgba, int width, int height, char **lut4096, int *sizelut4096)
413
+{
414
+        int n;
415
+        int reqsize;
416
+        float fr,fg,fb;
417
+        int ir,ig,ib;
418
+        int incr,incg,incb;
419
+        int posr,posg,posb;
420
+        int myrgb[3];
421
+        int x,y;
422
+        int r,g,b;
423
+        int i;
424
+        int isize,isizesq,isizesqminusone;
425
+        int osize,osizesq,osizesqminusone;
426
+        unsigned char *orig,*dest;
427
+        if(rgba==NULL || width!=height || lut4096==NULL || sizelut4096==NULL)
428
+                return(-1); /* sanity check error */
429
+        /* check if size is a supported size */
430
+        for(n=2;n<=16 && width!=(n*n*n);n++)
431
+                ;
432
+        if(n>16)
433
+                return(-1); /* invalid size */
434
+        /* expand lut4096 as necessary */
435
+        reqsize=4096*4096*3;
436
+        if(*sizelut4096<reqsize) {
437
+                char *newlut4096;
438
+                if((newlut4096=realloc(*lut4096,reqsize))==NULL)
439
+                      return(-1); /* insuf. mem. for resulting lut */
440
+                *lut4096=newlut4096;
441
+                *sizelut4096=reqsize;
442
+        }
443
+        /* do the conversion */
444
+        isize=n;
445
+        isizesq=n*n;
446
+        isizesqminusone=isizesq-1;
447
+        osize=16;
448
+        osizesq=osize*osize;
449
+        osizesqminusone=osizesq-1;
450
+        for(r=0;r<osizesq;r++) {
451
+                for(g=0;g<osizesq;g++) {
452
+                        for(b=0;b<osizesq;b++) {
453
+                                fr=((isizesqminusone*((float)r))/osizesqminusone);
454
+                                fg=((isizesqminusone*((float)g))/osizesqminusone);
455
+                                fb=((isizesqminusone*((float)b))/osizesqminusone);
456
+                                ir=floorf(fr);
457
+                                ig=floorf(fg);
458
+                                ib=floorf(fb);
459
+                                fr=fr-ir;
460
+                                fg=fg-ig;
461
+                                fb=fb-ib;
462
+                                myrgb[0]=myrgb[1]=myrgb[2]=0;
463
+                                for(i=0;i<2*2*2;i++) {
464
+                                        incr=(i>>2)&1;
465
+                                        incg=(i>>1)&1;
466
+                                        incb=i&1;
467
+                                        posr=ir+incr;
468
+                                        posr=(posr<0)?0:(posr>=isizesq)?isizesqminusone:posr;
469
+                                        posg=ig+incg;
470
+                                        posg=(posg<0)?0:(posg>=isizesq)?isizesqminusone:posg;
471
+                                        posb=ib+incb;
472
+                                        posb=(posb<0)?0:(posb>=isizesq)?isizesqminusone:posb;
473
+                                        x=posr+(posg%isize)*isizesq;
474
+                                        y=posb*isize+(posg/isize);
475
+                                        orig=(unsigned char *) (rgba+((y*width+x)<<2));
476
+                                        myrgb[0]+=orig[0]*((incr!=0)?fr:(1-fr));
477
+                                        myrgb[1]+=orig[1]*((incg!=0)?fg:(1-fg));
478
+                                        myrgb[2]+=orig[2]*((incb!=0)?fb:(1-fb));
479
+                                }
480
+                                myrgb[0]/=(i/2);
481
+                                myrgb[0]=(myrgb[0]<0)?0:(myrgb[0]>255)?255:myrgb[0];
482
+                                myrgb[1]/=(i/2);
483
+                                myrgb[1]=(myrgb[1]<0)?0:(myrgb[1]>255)?255:myrgb[1];
484
+                                myrgb[2]/=(i/2);
485
+                                myrgb[2]=(myrgb[2]<0)?0:(myrgb[2]>255)?255:myrgb[2];
486
+                                dest=(unsigned char *) ((*lut4096)+((r<<16)+(g<<8)+b)*3);
487
+                                dest[0]=myrgb[0];
488
+                                dest[1]=myrgb[1];
489
+                                dest[2]=myrgb[2];
490
+                        }
491
+                }
492
+        }
493
+        return(0);
494
+}
495
+
496
+
390 497
 int
391 498
 luttool_applylut4096(char *lut4096,char *imgbuf,int imgwidth,int imgheight)
392 499
 {
Browse code

Fix error description.

Dario Rodriguez authored on 16/01/2022 14:38:07
Showing 1 changed files
... ...
@@ -108,7 +108,7 @@ main(int argc, char *argv[])
108 108
                         currentoutfilename=bufoutfilename;
109 109
                 }
110 110
                 if(luttool_applylut(lutlist,argv[i],currentoutfilename,quality,identitysize)!=0) {
111
-                        fprintf(stderr,"%s: ERROR: couldn't apply LUTs \"%s\" to \"%s\" or couldn't write \"%s\"cified\n",argv[0],lutlist,argv[i],currentoutfilename);
111
+                        fprintf(stderr,"%s: ERROR: couldn't apply LUTs \"%s\" to \"%s\" or couldn't write \"%s\"\n",argv[0],lutlist,argv[i],currentoutfilename);
112 112
                         return(1);
113 113
                 }
114 114
         }
Browse code

Initial implementation. Only supports HaldCLUTs and PNGs.

Dario Rodriguez authored on 16/01/2022 11:05:23
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,408 @@
1
+/*
2
+ * luttool.c
3
+ *
4
+ * Utility to apply LUTs to images
5
+ *
6
+ * Author: Dario Rodriguez antartica@whereismybit.com
7
+ * This program is licensed under the terms of the MIT license,
8
+ * with an exception: the license text may be substituted for a
9
+ * link to it. MIT license text: https://spdx.org/licenses/MIT.html
10
+ */
11
+
12
+#include <stdio.h>
13
+#include <stdlib.h>
14
+#include <unistd.h>
15
+#include <string.h>
16
+#include <png.h>
17
+
18
+#define DEFAULT_IDENTITYSIZE 12 /* Same as RawTherapee's HaldCLUTs, 1728x1728 AKA (12*12)*12x12*(12*12), equivalent to a cube with 144px wide sides*/
19
+#define DEFAULT_QUALITY 85
20
+/* #define JPEG_SUPPORTED */
21
+
22
+int luttool_applylut(char *lutfilenamelist,char *infilename, char *outfilename,int quality,int identitysize);
23
+
24
+int util_pnginfo(char *filename, int *width, int *height);
25
+int util_pngload(char *filename, char **bufimg, int *sizebufimg, int *width, int *height);
26
+int util_pngsave(char *filename, char *bufimg, int width, int height);
27
+int util_identitygen(char **bufimg, int *sizebufimg, int identitysize, int *width, int *height);
28
+int luttool_rgba2lut4096(char *rgba, int width, int height, char **lut4096, int *sizelut4096);
29
+int luttool_rgba2lut4096_interpolated(char *rgba, int width, int height, char **lut4096, int *sizelut4096);
30
+int luttool_applylut4096(char *lut4096,char *imgbuf,int imgwidth,int imgheight);
31
+
32
+int
33
+main(int argc, char *argv[])
34
+{
35
+        int firstarg,outfilenamearg;
36
+        int identitysize;
37
+        int quality;
38
+        char *outfilename;
39
+        char *lutlist;
40
+        int i;
41
+        int flagseveralinfile;
42
+        char bufoutfilename[1024];
43
+        char *currentoutfilename;
44
+        if(argc<2 || strcmp(argv[argc-1],"--help")==0) {
45
+#ifdef JPEG_SUPPORTED
46
+                printf("Syntax: %s [-q jpegquality] [-n identitylevel] {identity | lutfile[,lutfile[,...]]} { identity | infile1 } [infile2 [...]] -o outfile\n",argv[0]);
47
+                printf("Example: %s haldclut.png sprite.png -o result.png\n",argv[0]);
48
+                printf("Example: %s -n 16 identity identity -o identity.png\n",argv[0]);
49
+                printf("Example: %s -q 85 haldclut.png infile.png -o outfile.jpg\n",argv[0]);
50
+#else
51
+                printf("Syntax: %s [-n identitylevel] {identity | lutfile[,lutfile[,...]]} { identity | infile1 } [infile2 [...]] -o outfile\n",argv[0]);
52
+                printf("Example: %s haldclut.png sprite.png -o result.png\n",argv[0]);
53
+                printf("Example: %s -n 16 identity identity -o identity.png\n",argv[0]);
54
+#endif
55
+                return(1);
56
+        }
57
+        /* parse arguments */
58
+        identitysize=DEFAULT_IDENTITYSIZE;
59
+        quality=DEFAULT_QUALITY;
60
+        for(firstarg=1;firstarg<(argc-1) && (strcmp(argv[firstarg],"-n")==0 || (strcmp(argv[firstarg],"-q")==0));) {
61
+                if(strcmp(argv[firstarg],"-n")==0) {
62
+                        identitysize=atoi(argv[firstarg+1]);
63
+                        if(identitysize<2 || identitysize>16) {
64
+                                fprintf(stderr,"%s: ERROR: the parameter to -n must be between 2 and 16 (default: %i)\n",argv[0],DEFAULT_IDENTITYSIZE);
65
+                                return(1);
66
+                        }
67
+                } else if(strcmp(argv[firstarg],"-q")==0) {
68
+                        quality=atoi(argv[firstarg+1]);
69
+                        if(quality<1 || quality>100) {
70
+                                fprintf(stderr,"%s: ERROR: the parameter to -q must be between 1 and 100 (default: %i)\n",argv[0],DEFAULT_QUALITY);
71
+                                return(1);
72
+                        }
73
+                }
74
+                firstarg+=2;
75
+        }
76
+        for(outfilenamearg=-1,outfilename=NULL,i=1;i<(argc-1);i++) {
77
+                if(strcmp(argv[i],"-o")==0) {
78
+                        outfilename=argv[i+1];
79
+                        outfilenamearg=i;
80
+                        break;
81
+                }
82
+        }
83
+        if(outfilename==NULL) {
84
+                fprintf(stderr,"%s: ERROR: no output file specified\n",argv[0]);
85
+                return(1);
86
+        }
87
+        firstarg+=((firstarg==outfilenamearg)?2:0);
88
+        lutlist=argv[firstarg];
89
+        firstarg++;
90
+        flagseveralinfile=((argc-firstarg-((outfilenamearg>=firstarg)?2:0))>1)?1:0;
91
+        /* process files sequentially, skipping the "-o outputfilename" */
92
+        for(i=firstarg;i<argc;i++) {
93
+                if(i==outfilenamearg) {
94
+                        i++;
95
+                        continue;
96
+                }
97
+                currentoutfilename=outfilename;
98
+                if(flagseveralinfile) {
99
+                        char *ext;
100
+                        int l;
101
+                        strncpy(bufoutfilename,argv[i],sizeof(bufoutfilename));
102
+                        bufoutfilename[sizeof(bufoutfilename)-1]='\0';
103
+                        if((ext=strrchr(bufoutfilename,'.'))!=NULL)
104
+                                *ext='\0';
105
+                        l=strlen(bufoutfilename);
106
+                        snprintf(bufoutfilename+l,sizeof(bufoutfilename)-l,"_%s",outfilename);
107
+                        bufoutfilename[sizeof(bufoutfilename)-1]='\0';
108
+                        currentoutfilename=bufoutfilename;
109
+                }
110
+                if(luttool_applylut(lutlist,argv[i],currentoutfilename,quality,identitysize)!=0) {
111
+                        fprintf(stderr,"%s: ERROR: couldn't apply LUTs \"%s\" to \"%s\" or couldn't write \"%s\"cified\n",argv[0],lutlist,argv[i],currentoutfilename);
112
+                        return(1);
113
+                }
114
+        }
115
+        return(0);
116
+}
117
+
118
+int
119
+luttool_applylut(char *lutlist,char *infilename, char *outfilename,int quality,int identitysize)
120
+{
121
+        char *curlut,*next;
122
+        char filename[1024];
123
+        int l;
124
+        int in_error;
125
+        char *lutbuf,*imgbuf,*rgblutbuf;
126
+        int sizelutbuf,lutwidth,lutheight;
127
+        int sizeimgbuf,imgwidth,imgheight;
128
+        int sizergblutbuf;
129
+        lutbuf=imgbuf=rgblutbuf=NULL;
130
+        sizelutbuf=sizeimgbuf=sizergblutbuf=0;
131
+        lutwidth=lutheight=imgwidth=imgheight=0;
132
+        if(lutlist==NULL || infilename==NULL || outfilename==NULL)
133
+                return(-1); /* sanity check error */
134
+        in_error=0;
135
+        /* load the image to process */
136
+        if(strcmp(infilename,"identity")==0) {
137
+                 if(util_identitygen(&imgbuf,&sizeimgbuf,identitysize,&imgwidth,&imgheight)==-1)
138
+                         in_error=1;
139
+        } else {
140
+                if(util_pngload(infilename,&imgbuf,&sizeimgbuf,&imgwidth,&imgheight)!=0)
141
+                        in_error=1;
142
+        }
143
+        /* apply all luts */
144
+        for(curlut=lutlist,next=strchr(curlut,','),next=((next==NULL)?(curlut+strlen(curlut)):next)
145
+          ;in_error==0 && *curlut!='\0'
146
+          ;curlut=next+((*next==',')?1:0),next=strchr(curlut,','),next=((next==NULL)?(curlut+strlen(curlut)):next)) {
147
+                l=next-curlut;
148
+                l=(l>(sizeof(filename)-1))?(sizeof(filename)-1):l;
149
+                memcpy(filename,curlut,l);
150
+                filename[l]='\0';
151
+                if(strcmp(filename,"identity")==0) {
152
+                        if(util_identitygen(&lutbuf,&sizelutbuf,identitysize,&lutwidth,&lutheight)==-1) {
153
+                                in_error=1;
154
+                                break; /* couldn't generate identity lut */
155
+                        }
156
+                } else {
157
+                        if(util_pngload(filename,&lutbuf,&sizelutbuf,&lutwidth,&lutheight)==-1) {
158
+                                in_error=1;
159
+                                break; /* couldn't load lut */
160
+                        }
161
+                }
162
+                if(luttool_rgba2lut4096(lutbuf, lutwidth, lutheight, &rgblutbuf, &sizergblutbuf)!=0) {
163
+                        in_error=1;
164
+                        break; /* couldn't process lut */
165
+                }
166
+                if(luttool_applylut4096(rgblutbuf,imgbuf,imgwidth,imgheight)!=0) {
167
+                        in_error=1;
168
+                        break; /* couldn't apply lut */
169
+                }
170
+        }
171
+        /* save the result */
172
+        if(in_error==0) {
173
+                if(util_pngsave(outfilename,imgbuf,imgwidth,imgheight)!=0)
174
+                        in_error=1; /* couldn't write */
175
+        }
176
+        /* cleanup and exit */
177
+        if(lutbuf!=NULL)
178
+                free(lutbuf),lutbuf=NULL;
179
+        if(imgbuf!=NULL)
180
+                free(imgbuf),imgbuf=NULL;
181
+        if(rgblutbuf!=NULL)
182
+                free(rgblutbuf),rgblutbuf=NULL;
183
+        return((in_error!=0)?-1:0);
184
+}
185
+
186
+
187
+
188
+int
189
+util_pnginfo(char *filename, int *width, int *height)
190
+{
191
+        return(util_pngload(filename,NULL,NULL,width,height));
192
+}
193
+
194
+int
195
+util_pngload(char *filename, char **bufimg, int *sizebufimg, int *width, int *height)
196
+{
197
+        FILE *f;
198
+        png_structp png;
199
+        png_infop info;
200
+        png_byte color_type,bit_depth;
201
+        png_bytep *rowpointers;
202
+        int reqsize;
203
+        int i,pitch;
204
+        if(filename==NULL || (bufimg==NULL && sizebufimg!=NULL) || (bufimg!=NULL && sizebufimg==NULL) || width==NULL || height==NULL)
205
+                return(-1); /* sanity check failed */
206
+        if((f=fopen(filename,"rb"))==NULL)
207
+                return(-1); /* couldn't open file */
208
+        if((png=png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL))==NULL
209
+          || (info=png_create_info_struct(png))==NULL
210
+          || setjmp(png_jmpbuf(png))) {
211
+                if(png!=NULL)
212
+                        png_destroy_read_struct(&png,&info,NULL),png=NULL,info=NULL;
213
+                fclose(f),f=NULL;
214
+                return(-1); /* couldn't init png library */
215
+        }
216
+        png_init_io(png,f);
217
+        png_read_info(png,info);
218
+        *width=png_get_image_width(png,info);
219
+        *height=png_get_image_height(png,info);
220
+        /* special case: if bufimg==NULL, we only want the width/height */
221
+        if(bufimg==NULL) {
222
+                png_destroy_read_struct(&png,&info,NULL),png=NULL,info=NULL;
223
+                fclose(f),f=NULL;
224
+                return(0); /* all done */
225
+        }
226
+        /* make sure we have enough space for the new image in 8-bit RGBA */
227
+        reqsize=(*width)*(*height)*4;
228
+        if(*sizebufimg<reqsize) {
229
+                char *newbufimg;
230
+                if((newbufimg=realloc(*bufimg,reqsize))==NULL) {
231
+                      png_destroy_read_struct(&png,&info,NULL),png=NULL,info=NULL;
232
+                      fclose(f),f=NULL;
233
+                      return(-1); /* insuf. mem. for resulting image */
234
+                }
235
+                *bufimg=newbufimg;
236
+                *sizebufimg=reqsize;
237
+        }
238
+        /* make sure we get 8-bit RGBA data, regardless of the file's bit_depth and color_type */
239
+        if((bit_depth=png_get_bit_depth(png,info))==16)
240
+                png_set_strip_16(png);
241
+        color_type=png_get_color_type(png,info);
242
+        if(color_type==PNG_COLOR_TYPE_PALETTE)
243
+                png_set_palette_to_rgb(png);
244
+        if(color_type==PNG_COLOR_TYPE_GRAY && bit_depth<8)
245
+                png_set_expand_gray_1_2_4_to_8(png);
246
+        if(png_get_valid(png,info,PNG_INFO_tRNS))
247
+                png_set_tRNS_to_alpha(png);
248
+        if(color_type==PNG_COLOR_TYPE_RGB
249
+          || color_type==PNG_COLOR_TYPE_GRAY
250
+          || color_type==PNG_COLOR_TYPE_PALETTE) {
251
+                png_set_filler(png,0xff,PNG_FILLER_AFTER);
252
+        }
253
+        if(color_type==PNG_COLOR_TYPE_GRAY
254
+          || color_type==PNG_COLOR_TYPE_GRAY_ALPHA) {
255
+                png_set_gray_to_rgb(png);
256
+        }
257
+        /* read the image */
258
+        png_read_update_info(png,info);         
259
+        if((rowpointers=(png_bytep *)malloc(sizeof(png_bytep)*(*height)))==NULL) {
260
+                png_destroy_read_struct(&png,&info,NULL),png=NULL,info=NULL;
261
+                fclose(f),f=NULL;
262
+                return(-1); /* insuf. mem. for temporary data */
263
+        }
264
+        for(i=0,pitch=(*width)*4;i<(*height);i++)
265
+                rowpointers[i]=(png_byte *)((*bufimg)+i*pitch);
266
+        png_read_image(png,rowpointers);
267
+        /* cleanup */
268
+        free(rowpointers),rowpointers=NULL;
269
+        fclose(f),f=NULL;
270
+        png_destroy_read_struct(&png,&info,NULL),png=NULL,info=NULL;
271
+        return(0);
272
+}
273
+
274
+int
275
+util_pngsave(char *filename, char *bufimg, int width, int height)
276
+{
277
+        FILE *f;
278
+        png_structp png;
279
+        png_infop info;
280
+        int i,pitch;
281
+        char *ptr;
282
+        if((f=fopen(filename,"wb"))==NULL)
283
+                return(-1); /* couldn't open file for writing */
284
+        if((png=png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL))==NULL
285
+          || (info=png_create_info_struct(png))==NULL
286
+          || setjmp(png_jmpbuf(png))) {
287
+                if(png!=NULL)
288
+                        png_destroy_write_struct(&png,&info),png=NULL,info=NULL;
289
+                fclose(f),f=NULL;
290
+                return(-1); /* couldn't init png library */
291
+        }
292
+        png_init_io(png,f);
293
+        png_set_IHDR(png,info,width,height,8,PNG_COLOR_TYPE_RGBA,
294
+          PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_BASE,PNG_FILTER_TYPE_BASE);
295
+        png_write_info(png,info);
296
+        for(i=0,ptr=bufimg,pitch=width*4;i<height;i++,ptr+=pitch)
297
+                png_write_row(png,(png_const_bytep)ptr);
298
+        png_write_end(png,NULL);
299
+        fclose(f),f=NULL;
300
+        png_destroy_write_struct(&png,&info),png=NULL,info=NULL;
301
+        return(0);
302
+}
303
+
304
+int
305
+util_identitygen(char **bufimg, int *sizebufimg, int identitysize, int *width, int *height)
306
+{
307
+        int x,y,r,g,b;
308
+        int isizesq,isizesqminusone;
309
+        int osizesqminusone;
310
+        int reqsize;
311
+        int l;
312
+        unsigned char *ptr;
313
+        if(bufimg==NULL || sizebufimg==NULL || identitysize<=1 || identitysize>16 || width==NULL || height==NULL)
314
+                return(-1);
315
+        l=*width=*height=identitysize*identitysize*identitysize;
316
+        reqsize=(*width)*(*height)*4;
317
+        if(*sizebufimg<reqsize) {
318
+                char *newbufimg;
319
+                if((newbufimg=realloc(*bufimg,reqsize))==NULL)
320
+                      return(-1); /* insuf. mem. for resulting image */
321
+                *bufimg=newbufimg;
322
+                *sizebufimg=reqsize;
323
+        }
324
+        isizesq=identitysize*identitysize;
325
+        isizesqminusone=isizesq-1;
326
+        osizesqminusone=256-1;
327
+        for(y=0,ptr=(unsigned char *)(*bufimg);y<l;y++) {
328
+                for(x=0;x<l;x++,ptr+=4) {
329
+                        r=x%isizesq;
330
+                        g=(y%identitysize)*identitysize+(x/isizesq);
331
+                        b=y/identitysize;
332
+                        ptr[0]=r*osizesqminusone/isizesqminusone;
333
+                        ptr[1]=g*osizesqminusone/isizesqminusone;
334
+                        ptr[2]=b*osizesqminusone/isizesqminusone;
335
+                        ptr[3]=0xff;
336
+                }
337
+        }
338
+        return(0);
339
+}
340
+
341
+int
342
+luttool_rgba2lut4096(char *rgba, int width, int height, char **lut4096, int *sizelut4096)
343
+{
344
+        int n;
345
+        int reqsize;
346
+        int x,y;
347
+        int r,g,b;
348
+        int isize,isizesq,isizesqminusone;
349
+        int osize,osizesq,osizesqminusone;
350
+        unsigned char *orig,*dest;
351
+        if(rgba==NULL || width!=height || lut4096==NULL || sizelut4096==NULL)
352
+                return(-1); /* sanity check error */
353
+        /* check if size is a supported size */
354
+        for(n=2;n<=16 && width!=(n*n*n);n++)
355
+                ;
356
+        if(n>16)
357
+                return(-1); /* invalid size */
358
+        /* expand lut4096 as necessary */
359
+        reqsize=4096*4096*3;
360
+        if(*sizelut4096<reqsize) {
361
+                char *newlut4096;
362
+                if((newlut4096=realloc(*lut4096,reqsize))==NULL)
363
+                      return(-1); /* insuf. mem. for resulting lut */
364
+                *lut4096=newlut4096;
365
+                *sizelut4096=reqsize;
366
+        }
367
+        /* do the conversion */
368
+        isize=n;
369
+        isizesq=n*n;
370
+        isizesqminusone=isizesq-1;
371
+        osize=16;
372
+        osizesq=osize*osize;
373
+        osizesqminusone=osizesq-1;
374
+        for(r=0;r<osizesq;r++) {
375
+                for(g=0;g<osizesq;g++) {
376
+                        for(b=0;b<osizesq;b++) {
377
+                                x=((isizesqminusone*r)/osizesqminusone)+(((isizesqminusone*g)/osizesqminusone)%isize)*isizesq;
378
+                                y=((isizesqminusone*b)/osizesqminusone)*isize+(((isizesqminusone*g)/osizesqminusone)/isize);
379
+                                orig=(unsigned char *) (rgba+((y*width+x)<<2));
380
+                                dest=(unsigned char *) ((*lut4096)+((r<<16)+(g<<8)+b)*3);
381
+                                dest[0]=orig[0];
382
+                                dest[1]=orig[1];
383
+                                dest[2]=orig[2];
384
+                        }
385
+                }
386
+        }
387
+        return(0);
388
+}
389
+
390
+int
391
+luttool_applylut4096(char *lut4096,char *imgbuf,int imgwidth,int imgheight)
392
+{
393
+        int x,y;
394
+        unsigned char *orig;
395
+        unsigned char *lut;
396
+        if(lut4096==NULL || imgbuf==NULL || imgwidth<=0 || imgheight<=0)
397
+                return(-1);
398
+        for(y=0,orig=(unsigned char *)imgbuf;y<imgheight ;y++) {
399
+                for(x=0;x<imgwidth;x++,orig+=4) {
400
+                        lut=((unsigned char *)lut4096)+((((int)(orig[0]))<<16)+(((int)(orig[1]))<<8)+((int)(orig[2])))*3;
401
+                        orig[0]=lut[0];
402
+                        orig[1]=lut[1];
403
+                        orig[2]=lut[2];
404
+                }
405
+        }
406
+        return(0);
407
+}
408
+