*/}}
Browse Source

Simple thumbnailing command

YimingWu 2 months ago
parent
commit
a156f91e45
3 changed files with 102 additions and 2 deletions
  1. 95 1
      ouroperations.c
  2. 2 1
      ourpaint.c
  3. 5 0
      ourpaint.h

+ 95 - 1
ouroperations.c

@@ -1520,6 +1520,71 @@ void our_ReadWidgetColor(laCanvasExtra*e,int x,int y){
     color[0]*=color[3];color[1]*=color[3];color[2]*=color[3];tnsVectorSet3v(Our->CurrentColor,color);
 }
 
+int our_RenderThumbnail(uint8_t** buf, int* sizeof_buf){
+    int x=INT_MAX,y=INT_MAX,w=-INT_MAX,h=-INT_MAX;
+    for(OurLayer* l=Our->Layers.pFirst;l;l=l->Item.pNext){
+        our_LayerClearEmptyTiles(l);
+        our_LayerEnsureImageBuffer(l,1);
+        if(Our->ImageX<x) x=Our->ImageX; if(Our->ImageY<y) y=Our->ImageY;
+        if(Our->ImageW>w) w=Our->ImageW; if(Our->ImageH>h) h=Our->ImageH;
+    }
+    if(w<=0||h<=0) return 0;
+    real r = (real)(TNS_MAX2(w,h))/400.0f;
+    int use_w=w/r, use_h=h/r;
+
+    tnsOffscreen* off = tnsCreate2DOffscreen(GL_RGBA,use_w,use_h,0,0,0);
+    tnsDrawToOffscreen(off,1,0);
+    tnsViewportWithScissor(0, 0, use_w, use_h);
+    tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
+    tnsOrtho(x,x+w,y+h,y,-100,100);
+    tnsClearColor(LA_COLOR3(Our->BackgroundColor),1); tnsClearAll();
+    our_CanvasDrawTextures();
+
+    if(Our->ImageBuffer){ free(Our->ImageBuffer); }
+    int bufsize=w*h*sizeof(uint16_t)*4;
+    Our->ImageBuffer=malloc(bufsize);
+    tnsBindTexture(off->pColor[0]); glPixelStorei(GL_PACK_ALIGNMENT, 2);
+    glGetTextureSubImage(off->pColor[0]->GLTexHandle, 0, 0, 0, 0, use_w, use_h, 1, GL_RGBA, GL_UNSIGNED_SHORT, bufsize, Our->ImageBuffer);
+
+    tnsDrawToScreen();
+    tnsDelete2DOffscreen(off);
+
+    our_ImageConvertForExport(OUR_EXPORT_BIT_DEPTH_8,OUR_EXPORT_COLOR_MODE_CLAY);
+
+    png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+
+    OurLayerWrite LayerWrite={0};
+    arrEnsureLength(&LayerWrite.data,0,&LayerWrite.MaxData,sizeof(unsigned char));
+    png_set_write_fn(png_ptr,&LayerWrite,_our_png_write,0);
+
+    png_set_IHDR(png_ptr, info_ptr,use_w,use_h,8,PNG_COLOR_TYPE_RGBA,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_BASE,PNG_FILTER_TYPE_BASE);
+    png_write_info(png_ptr, info_ptr);
+    png_set_swap(png_ptr);
+
+    uint8_t* data=Our->ImageBuffer;
+    for(int i=0;i<use_h;i++){
+        png_write_row(png_ptr,&data[use_w*i*4]);
+    }
+    png_write_end(png_ptr, info_ptr);
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+
+    *buf=LayerWrite.data; *sizeof_buf=LayerWrite.NextData;
+
+    free(Our->ImageBuffer);
+    Our->ImageBuffer=0;
+
+    return 1;
+}
+int our_GetFileThumbnail(char* file, uint8_t** buf, int* sizeof_buf){
+    laUDF* udf = laOpenUDF(file,0,0,0);
+
+    if(udf){
+        laExtractProp(udf,"our.thumbnail");
+        laExtractUDF(udf,0,LA_UDF_MODE_APPEND); laCloseUDF(udf);
+    }
+}
+
 void our_StartCropping(OurCanvasDraw* cd){
     if(cd->CanvasDownX<Our->X){
         if(cd->CanvasDownY<Our->Y-Our->H){ cd->AtCrop=OUR_AT_CROP_BL; }
@@ -1997,6 +2062,14 @@ int ourinv_ClearEmptyTiles(laOperator* a, laEvent* e){
     return LA_FINISHED;
 }
 
+void* ourgetraw_FileThumbnail(void* unused, int* r_size, int* r_is_copy){
+    void* buf=0;
+    if(our_RenderThumbnail(&buf, r_size)){ *r_is_copy=1; return buf; }
+    *r_is_copy=0; return 0;
+}
+void oursetraw_FileThumbnail(void* unused, void* data, int DataSize){
+    return;
+}
 void ourget_CanvasIdentifier(void* unused, char* buf, char** ptr){
     *ptr="Main canvas";
 }
@@ -2195,6 +2268,25 @@ void ourui_ToolExtras(laUiList *uil, laPropPack *pp, laPropPack *actinst, laColu
     //laShowLabel(uil, c, MAIN.MenuProgramName, 0, 0)->Expand=1;
 }
 
+int ourProcessInitArgs(int argc, char* argv[]){
+    if(argc == 4 && strstr(argv[1],"--t")==argv[1]){
+        FILE* fp=fopen(argv[2],"rb"); if(!fp){ printf("Can't open file %s\n",argv[2]); return -1; }
+        void* data=0; size_t size=0;
+        if(laExtractQuickRaw(fp,"our.thumbnail",&data,&size)){
+            FILE* thumb = fopen(argv[3],"wb");
+            if(thumb){
+                fwrite(data, size, 1, thumb);
+                fclose(thumb);
+            }
+            free(data);
+        }else{
+            printf("File doesn't have a thumbnail.\n",argv[2]);
+        }
+        fclose(fp);
+        return -1;
+    }
+}
+
 void ourPreFrame(){
     if(MAIN.GraphNeedsRebuild){ ourRebuildBrushEval(); }
 }
@@ -2280,6 +2372,7 @@ void ourRegisterEverything(){
     laAddSubGroup(pc,"our","Our","OurPaint main","our_paint",0,0,0,-1,ourget_our,0,0,0,0,0,0,LA_UDF_SINGLE);
 
     pc=laAddPropertyContainer("our_paint","Our Paint","OurPaint main",0,0,sizeof(OurPaint),0,0,1);
+    laAddRawProperty(pc,"thumbnail","Thumbnail","Thumbnail of this file",0,0,ourgetraw_FileThumbnail,oursetraw_FileThumbnail,LA_READ_ONLY);
     laAddSubGroup(pc,"canvas","Canvas","OurPaint canvas","our_canvas",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
     laAddSubGroup(pc,"tools","Tools","OurPaint tools","our_tools",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
     laAddSubGroup(pc,"preferences","Preferences","OurPaint preferences","our_preferences",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
@@ -2502,7 +2595,8 @@ void ourRegisterEverything(){
 
     ourRegisterNodes();
 
-    laSaveProp("our.canvas");
+    laManagedSaveProp* msp= laSaveProp("our.canvas");
+    laSaveAlongside(msp,"our.thumbnail");
     laSaveProp("our.tools");
 
     laGetSaverDummy(Our,Our->CanvasSaverDummyProp);

+ 2 - 1
ourpaint.c

@@ -23,6 +23,7 @@ extern tnsMain* T;
 extern OurPaint *Our;
 
 int main(int argc, char *argv[]){
+    if(ourProcessInitArgs(argc,argv) < 0){ return 0; }
     laInitArguments ia={0}; laSetDefaultInitArguments(&ia);
     ia.GLMajor=4; ia.GLMinor=5;
     ia.UseColorManagement=1;
@@ -43,7 +44,7 @@ int main(int argc, char *argv[]){
     for(int i=1;i<argc;i++){
         char* file=argv[i]; 
         laManagedUDF* m; laUDF* udf = laOpenUDF(file, 1, 0, &m);
-        if(udf){ laExtractUDF(udf,m,LA_UDF_MODE_APPEND,0); laCloseUDF(udf); }
+        if(udf){ laExtractUDF(udf,m,LA_UDF_MODE_APPEND); laCloseUDF(udf); }
     }
 
     //laAddRootDBInst("our.tools");

+ 5 - 0
ourpaint.h

@@ -391,12 +391,17 @@ STRUCTURE(OurPaint){
     uint16_t *ImageBuffer;
     int ImageW,ImageH,ImageX,ImageY,LoadX,LoadY,TempLoadX,TempLoadY;
 
+    uint8_t* ThumbnailBuffer;
+
     void* icc_LinearsRGB; int iccsize_LinearsRGB;
     void* icc_LinearClay; int iccsize_LinearClay;
     void* icc_sRGB; int iccsize_sRGB;
     void* icc_Clay; int iccsize_Clay;
 };
 
+
+int ourProcessInitArgs(int argc, char* argv[]);
+
 int ourInit();
 void ourRegisterNodes();
 int ourRebuildBrushEval();