RNA
[blender-staging.git] / source / blender / editors / space_image / image_ops.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, 2002-2009
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <string.h>
29 #include <stdlib.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_image_types.h"
34 #include "DNA_node_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_packedFile_types.h"
37 #include "DNA_space_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_screen_types.h"
40 #include "DNA_userdef_types.h"
41 #include "DNA_windowmanager_types.h"
42
43 #include "BKE_colortools.h"
44 #include "BKE_context.h"
45 #include "BKE_image.h"
46 #include "BKE_global.h"
47 #include "BKE_library.h"
48 #include "BKE_node.h"
49 #include "BKE_packedFile.h"
50 #include "BKE_screen.h"
51
52 #include "BLI_arithb.h"
53 #include "BLI_blenlib.h"
54
55 #include "IMB_imbuf.h"
56 #include "IMB_imbuf_types.h"
57
58 #include "RE_pipeline.h"
59
60 #include "RNA_access.h"
61 #include "RNA_define.h"
62 #include "RNA_types.h"
63
64 #include "ED_screen.h"
65 #include "ED_uvedit.h"
66
67 #include "WM_api.h"
68 #include "WM_types.h"
69
70 #include "image_intern.h"
71
72 void imagespace_composite_flipbook(SpaceImage *sima, Scene *scene)
73 {
74         ImBuf *ibuf;
75         int cfrao= scene->r.cfra;
76         int sfra, efra;
77         
78         if(sima->iuser.frames<2)
79                 return;
80         if(scene->nodetree==NULL)
81                 return;
82         
83         sfra= sima->iuser.sfra;
84         efra= sima->iuser.sfra + sima->iuser.frames-1;
85         scene->nodetree->test_break= NULL; // XXX blender_test_break;
86         
87         for(scene->r.cfra=sfra; scene->r.cfra<=efra; scene->r.cfra++) {
88                 
89                 // XXX set_timecursor(CFRA);
90                 
91                 BKE_image_all_free_anim_ibufs(CFRA);
92                 ntreeCompositTagAnimated(scene->nodetree);
93                 ntreeCompositExecTree(scene->nodetree, &scene->r, scene->r.cfra!=cfrao);        /* 1 is no previews */
94                 
95                 // XXX force_draw(0);
96                 
97                 ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
98                 /* save memory in flipbooks */
99                 if(ibuf)
100                         imb_freerectfloatImBuf(ibuf);
101                 
102                 // XXX if(blender_test_break())
103                 // XXX  break;
104         }
105         scene->nodetree->test_break= NULL;
106         // XXX waitcursor(0);
107         
108         // XXX play_anim(0);
109         
110         // XXX allqueue(REDRAWNODE, 1);
111         // XXX allqueue(REDRAWIMAGE, 1);
112         
113         scene->r.cfra= cfrao;
114 }
115
116 /******************** view navigation utilities *********************/
117
118 static void sima_zoom_set(SpaceImage *sima, ARegion *ar, float zoom)
119 {
120         float oldzoom= sima->zoom;
121         int width, height;
122
123         sima->zoom= zoom;
124
125         if (sima->zoom > 0.1f && sima->zoom < 4.0f)
126                 return;
127
128         /* check zoom limits */
129         get_space_image_size(sima, &width, &height);
130
131         width *= sima->zoom;
132         height *= sima->zoom;
133
134         if((width < 4) && (height < 4))
135                 sima->zoom= oldzoom;
136         else if((ar->winrct.xmax - ar->winrct.xmin) <= sima->zoom)
137                 sima->zoom= oldzoom;
138         else if((ar->winrct.ymax - ar->winrct.ymin) <= sima->zoom)
139                 sima->zoom= oldzoom;
140 }
141
142 static void sima_zoom_set_factor(SpaceImage *sima, ARegion *ar, float zoomfac)
143 {
144         sima_zoom_set(sima, ar, sima->zoom*zoomfac);
145 }
146
147 static int space_image_main_area_poll(bContext *C)
148 {
149         SpaceLink *slink= CTX_wm_space_data(C);
150         ARegion *ar= CTX_wm_region(C);
151
152         if(slink && (slink->spacetype == SPACE_IMAGE))
153                 return (ar && ar->type->regionid == RGN_TYPE_WINDOW);
154         
155         return 0;
156 }
157
158 /********************** view pan operator *********************/
159
160 typedef struct ViewPanData {
161         float x, y;
162         float xof, yof;
163 } ViewPanData;
164
165 static void view_pan_init(bContext *C, wmOperator *op, wmEvent *event)
166 {
167         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
168         ViewPanData *vpd;
169
170         op->customdata= vpd= MEM_callocN(sizeof(ViewPanData), "ImageViewPanData");
171         WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
172
173         vpd->x= event->x;
174         vpd->y= event->y;
175         vpd->xof= sima->xof;
176         vpd->yof= sima->yof;
177
178         WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
179 }
180
181 static void view_pan_exit(bContext *C, wmOperator *op, int cancel)
182 {
183         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
184         ViewPanData *vpd= op->customdata;
185
186         if(cancel) {
187                 sima->xof= vpd->xof;
188                 sima->yof= vpd->yof;
189                 ED_area_tag_redraw(CTX_wm_area(C));
190         }
191
192         WM_cursor_restore(CTX_wm_window(C));
193         MEM_freeN(op->customdata);
194 }
195
196 static int view_pan_exec(bContext *C, wmOperator *op)
197 {
198         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
199         float offset[2];
200
201         RNA_float_get_array(op->ptr, "offset", offset);
202         sima->xof += offset[0];
203         sima->yof += offset[1];
204
205         ED_area_tag_redraw(CTX_wm_area(C));
206
207         /* XXX notifier? */
208 #if 0
209         if(image_preview_active(curarea, NULL, NULL)) {
210                 /* recalculates new preview rect */
211                 scrarea_do_windraw(curarea);
212                 image_preview_event(2);
213         }
214 #endif
215         
216         return OPERATOR_FINISHED;
217 }
218
219 static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
220 {
221         view_pan_init(C, op, event);
222         return OPERATOR_RUNNING_MODAL;
223 }
224
225 static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event)
226 {
227         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
228         ViewPanData *vpd= op->customdata;
229         float offset[2];
230
231         switch(event->type) {
232                 case MOUSEMOVE:
233                         sima->xof= vpd->xof;
234                         sima->yof= vpd->yof;
235                         offset[0]= (vpd->x - event->x)/sima->zoom;
236                         offset[1]= (vpd->y - event->y)/sima->zoom;
237                         RNA_float_set_array(op->ptr, "offset", offset);
238                         view_pan_exec(C, op);
239                         break;
240                 case MIDDLEMOUSE:
241                         if(event->val==0) {
242                                 view_pan_exit(C, op, 0);
243                                 return OPERATOR_FINISHED;
244                         }
245                         break;
246         }
247
248         return OPERATOR_RUNNING_MODAL;
249 }
250
251 static int view_pan_cancel(bContext *C, wmOperator *op)
252 {
253         view_pan_exit(C, op, 1);
254         return OPERATOR_CANCELLED;
255 }
256
257 void IMAGE_OT_view_pan(wmOperatorType *ot)
258 {
259         /* identifiers */
260         ot->name= "View Pan";
261         ot->idname= "IMAGE_OT_view_pan";
262         
263         /* api callbacks */
264         ot->exec= view_pan_exec;
265         ot->invoke= view_pan_invoke;
266         ot->modal= view_pan_modal;
267         ot->cancel= view_pan_cancel;
268         ot->poll= space_image_main_area_poll;
269
270         /* properties */
271         RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
272                 "Offset", "Offset in floating point units, 1.0 is the width and height of the image.", -FLT_MAX, FLT_MAX);
273 }
274
275 /********************** view zoom operator *********************/
276
277 typedef struct ViewZoomData {
278         float x, y;
279         float zoom;
280 } ViewZoomData;
281
282 static void view_zoom_init(bContext *C, wmOperator *op, wmEvent *event)
283 {
284         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
285         ViewZoomData *vpd;
286
287         op->customdata= vpd= MEM_callocN(sizeof(ViewZoomData), "ImageViewZoomData");
288         WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
289
290         vpd->x= event->x;
291         vpd->y= event->y;
292         vpd->zoom= sima->zoom;
293
294         WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
295 }
296
297 static void view_zoom_exit(bContext *C, wmOperator *op, int cancel)
298 {
299         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
300         ViewZoomData *vpd= op->customdata;
301
302         if(cancel) {
303                 sima->zoom= vpd->zoom;
304                 ED_area_tag_redraw(CTX_wm_area(C));
305         }
306
307         WM_cursor_restore(CTX_wm_window(C));
308         MEM_freeN(op->customdata);
309 }
310
311 static int view_zoom_exec(bContext *C, wmOperator *op)
312 {
313         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
314         ARegion *ar= CTX_wm_region(C);
315
316         sima_zoom_set_factor(sima, ar, RNA_float_get(op->ptr, "factor"));
317
318         ED_area_tag_redraw(CTX_wm_area(C));
319
320         /* XXX notifier? */
321 #if 0
322         if(image_preview_active(curarea, NULL, NULL)) {
323                 /* recalculates new preview rect */
324                 scrarea_do_windraw(curarea);
325                 image_preview_event(2);
326         }
327 #endif
328         
329         return OPERATOR_FINISHED;
330 }
331
332 static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
333 {
334         view_zoom_init(C, op, event);
335         return OPERATOR_RUNNING_MODAL;
336 }
337
338 static int view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event)
339 {
340         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
341         ARegion *ar= CTX_wm_region(C);
342         ViewZoomData *vpd= op->customdata;
343         float factor;
344
345         switch(event->type) {
346                 case MOUSEMOVE:
347                         factor= 1.0 + (vpd->x-event->x+vpd->y-event->y)/300.0f;
348                         RNA_float_set(op->ptr, "factor", factor);
349                         sima_zoom_set(sima, ar, vpd->zoom*factor);
350                         ED_area_tag_redraw(CTX_wm_area(C));
351                         break;
352                 case MIDDLEMOUSE:
353                         if(event->val==0) {
354                                 view_zoom_exit(C, op, 0);
355                                 return OPERATOR_FINISHED;
356                         }
357                         break;
358         }
359
360         return OPERATOR_RUNNING_MODAL;
361 }
362
363 static int view_zoom_cancel(bContext *C, wmOperator *op)
364 {
365         view_zoom_exit(C, op, 1);
366         return OPERATOR_CANCELLED;
367 }
368
369 void IMAGE_OT_view_zoom(wmOperatorType *ot)
370 {
371         /* identifiers */
372         ot->name= "View Zoom";
373         ot->idname= "IMAGE_OT_view_zoom";
374         
375         /* api callbacks */
376         ot->exec= view_zoom_exec;
377         ot->invoke= view_zoom_invoke;
378         ot->modal= view_zoom_modal;
379         ot->cancel= view_zoom_cancel;
380         ot->poll= space_image_main_area_poll;
381
382         /* properties */
383         RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, FLT_MAX,
384                 "Factor", "Zoom factor, values higher than 1.0 zoom in, lower values zoom out.", -FLT_MAX, FLT_MAX);
385 }
386
387 /********************** view all operator *********************/
388
389 /* Updates the fields of the View2D member of the SpaceImage struct.
390  * Default behavior is to reset the position of the image and set the zoom to 1
391  * If the image will not fit within the window rectangle, the zoom is adjusted */
392
393 static int view_all_exec(bContext *C, wmOperator *op)
394 {
395         SpaceImage *sima;
396         ARegion *ar;
397         Scene *scene;
398         Object *obedit;
399         Image *ima;
400         ImBuf *ibuf;
401         float aspx, aspy, zoomx, zoomy, w, h;
402         int width, height;
403
404         /* retrieve state */
405         sima= (SpaceImage*)CTX_wm_space_data(C);
406         ar= CTX_wm_region(C);
407         scene= (Scene*)CTX_data_scene(C);
408         obedit= CTX_data_edit_object(C);
409
410         ima= get_space_image(sima);
411         ibuf= get_space_image_buffer(sima);
412         get_space_image_size(sima, &width, &height);
413         get_space_image_aspect(sima, &aspx, &aspy);
414
415         w= width*aspx;
416         h= height*aspy;
417         
418         /* check if the image will fit in the image with zoom==1 */
419         width = ar->winrct.xmax - ar->winrct.xmin + 1;
420         height = ar->winrct.ymax - ar->winrct.ymin + 1;
421
422         if((w >= width || h >= height) && (width > 0 && height > 0)) {
423                 /* find the zoom value that will fit the image in the image space */
424                 zoomx= width/w;
425                 zoomy= height/h;
426                 sima_zoom_set(sima, ar, 1.0f/power_of_2(1/MIN2(zoomx, zoomy)));
427         }
428         else
429                 sima_zoom_set(sima, ar, 1.0f);
430
431         sima->xof= sima->yof= 0.0f;
432
433         ED_area_tag_redraw(CTX_wm_area(C));
434         
435         return OPERATOR_FINISHED;
436 }
437
438 void IMAGE_OT_view_all(wmOperatorType *ot)
439 {
440         /* identifiers */
441         ot->name= "View All";
442         ot->idname= "IMAGE_OT_view_all";
443         
444         /* api callbacks */
445         ot->exec= view_all_exec;
446         ot->poll= space_image_main_area_poll;
447 }
448
449 /********************** view selected operator *********************/
450
451 static int view_selected_exec(bContext *C, wmOperator *op)
452 {
453         SpaceImage *sima;
454         ARegion *ar;
455         Scene *scene;
456         Object *obedit;
457         Image *ima;
458         ImBuf *ibuf;
459         float size, min[2], max[2], d[2];
460         int width, height;
461
462         /* retrieve state */
463         sima= (SpaceImage*)CTX_wm_space_data(C);
464         ar= CTX_wm_region(C);
465         scene= (Scene*)CTX_data_scene(C);
466         obedit= CTX_data_edit_object(C);
467
468         ima= get_space_image(sima);
469         ibuf= get_space_image_buffer(sima);
470         get_space_image_size(sima, &width, &height);
471
472         /* get bounds */
473         if(!ED_uvedit_minmax(scene, ima, obedit, min, max))
474                 return OPERATOR_CANCELLED;
475
476         /* adjust offset and zoom */
477         sima->xof= (int)(((min[0] + max[0])*0.5f - 0.5f)*width);
478         sima->yof= (int)(((min[1] + max[1])*0.5f - 0.5f)*height);
479
480         d[0]= max[0] - min[0];
481         d[1]= max[1] - min[1];
482         size= 0.5*MAX2(d[0], d[1])*MAX2(width, height)/256.0f;
483         
484         if(size<=0.01) size= 0.01;
485         sima_zoom_set(sima, ar, 0.7/size);
486
487         ED_area_tag_redraw(CTX_wm_area(C));
488         
489         return OPERATOR_FINISHED;
490 }
491
492 void IMAGE_OT_view_selected(wmOperatorType *ot)
493 {
494         /* identifiers */
495         ot->name= "View Center";
496         ot->idname= "IMAGE_OT_view_selected";
497         
498         /* api callbacks */
499         ot->exec= view_selected_exec;
500         ot->poll= ED_operator_uvedit;
501 }
502
503 /********************** view zoom in/out operator *********************/
504
505 static int view_zoom_in_exec(bContext *C, wmOperator *op)
506 {
507         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
508         ARegion *ar= CTX_wm_region(C);
509
510         sima_zoom_set_factor(sima, ar, 1.25f);
511
512         ED_area_tag_redraw(CTX_wm_area(C));
513         
514         return OPERATOR_FINISHED;
515 }
516
517 void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
518 {
519         /* identifiers */
520         ot->name= "View Zoom In";
521         ot->idname= "IMAGE_OT_view_zoom_in";
522         
523         /* api callbacks */
524         ot->exec= view_zoom_in_exec;
525         ot->poll= space_image_main_area_poll;
526 }
527
528 static int view_zoom_out_exec(bContext *C, wmOperator *op)
529 {
530         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
531         ARegion *ar= CTX_wm_region(C);
532
533         sima_zoom_set_factor(sima, ar, 0.8f);
534
535         ED_area_tag_redraw(CTX_wm_area(C));
536         
537         return OPERATOR_FINISHED;
538 }
539
540 void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
541 {
542         /* identifiers */
543         ot->name= "View Zoom Out";
544         ot->idname= "IMAGE_OT_view_zoom_out";
545         
546         /* api callbacks */
547         ot->exec= view_zoom_out_exec;
548         ot->poll= space_image_main_area_poll;
549 }
550
551 /********************** view zoom ratio operator *********************/
552
553 static int view_zoom_ratio_exec(bContext *C, wmOperator *op)
554 {
555         SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
556         ARegion *ar= CTX_wm_region(C);
557
558         sima_zoom_set(sima, ar, RNA_float_get(op->ptr, "ratio"));
559         
560         /* ensure pixel exact locations for draw */
561         sima->xof= (int)sima->xof;
562         sima->yof= (int)sima->yof;
563
564         /* XXX notifier? */
565 #if 0
566         if(image_preview_active(curarea, NULL, NULL)) {
567                 /* recalculates new preview rect */
568                 scrarea_do_windraw(curarea);
569                 image_preview_event(2);
570         }
571 #endif
572
573         ED_area_tag_redraw(CTX_wm_area(C));
574         
575         return OPERATOR_FINISHED;
576 }
577
578 void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
579 {
580         /* identifiers */
581         ot->name= "View Zoom Ratio";
582         ot->idname= "IMAGE_OT_view_zoom_ratio";
583         
584         /* api callbacks */
585         ot->exec= view_zoom_ratio_exec;
586         ot->poll= space_image_main_area_poll;
587         
588         /* properties */
589         RNA_def_float(ot->srna, "ratio", 0.0f, 0.0f, FLT_MAX,
590                 "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out.", -FLT_MAX, FLT_MAX);
591 }
592
593 /* Image functions */
594
595 #if 0
596 static void load_image_filesel(SpaceImage *sima, Scene *scene, Object *obedit, char *str)       /* called from fileselect */
597 {
598         Image *ima= NULL;
599
600         ima= BKE_add_image_file(str, scene->r.cfra);
601         if(ima) {
602                 BKE_image_signal(ima, &sima->iuser, IMA_SIGNAL_RELOAD);
603                 set_space_image(sima, scene, obedit, ima);
604         }
605         // XXX BIF_undo_push("Load image UV");
606         // XXX allqueue(REDRAWIMAGE, 0);
607 }
608
609 static void replace_image_filesel(SpaceImage *sima, char *str)          /* called from fileselect */
610 {
611         if (!sima->image)
612                 return;
613         
614         BLI_strncpy(sima->image->name, str, sizeof(sima->image->name)-1); /* we cant do much if the str is longer then 240 :/ */
615         BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD);
616         // XXX BIF_undo_push("Replace image UV");
617         // XXX allqueue(REDRAWIMAGE, 0);
618         // XXX allqueue(REDRAWVIEW3D, 0);
619 }
620 #endif
621
622 static void save_image_doit(SpaceImage *sima, Scene *scene, char *name)
623 {
624         Image *ima= get_space_image(sima);
625         ImBuf *ibuf= get_space_image_buffer(sima);
626         int len;
627         char str[FILE_MAXDIR+FILE_MAXFILE];
628
629         if (ibuf) {
630                 BLI_strncpy(str, name, sizeof(str));
631
632                 BLI_convertstringcode(str, G.sce);
633                 BLI_convertstringframe(str, scene->r.cfra);
634                 
635                 
636                 if(scene->r.scemode & R_EXTENSION)  {
637                         BKE_add_image_extension(scene, str, sima->imtypenr);
638                         BKE_add_image_extension(scene, name, sima->imtypenr);
639                 }
640                 
641                 if (1) { // XXX saveover(str)) {
642                         
643                         /* enforce user setting for RGB or RGBA, but skip BW */
644                         if(scene->r.planes==32)
645                                 ibuf->depth= 32;
646                         else if(scene->r.planes==24)
647                                 ibuf->depth= 24;
648                         
649                         // XXX waitcursor(1);
650                         if(sima->imtypenr==R_MULTILAYER) {
651                                 RenderResult *rr= BKE_image_get_renderresult(scene, ima);
652                                 if(rr) {
653                                         RE_WriteRenderResult(rr, str, scene->r.quality);
654                                         
655                                         BLI_strncpy(ima->name, name, sizeof(ima->name));
656                                         BLI_strncpy(ibuf->name, str, sizeof(ibuf->name));
657                                         
658                                         /* should be function? nevertheless, saving only happens here */
659                                         for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next)
660                                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
661                                         
662                                 }
663                                 else; // XXX error("Did not write, no Multilayer Image");
664                         }
665                         else if (BKE_write_ibuf(scene, ibuf, str, sima->imtypenr, scene->r.subimtype, scene->r.quality)) {
666                                 BLI_strncpy(ima->name, name, sizeof(ima->name));
667                                 BLI_strncpy(ibuf->name, str, sizeof(ibuf->name));
668                                 
669                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
670                                 
671                                 /* change type? */
672                                 if( ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
673                                         ima->source= IMA_SRC_FILE;
674                                         ima->type= IMA_TYPE_IMAGE;
675                                 }
676                                 if(ima->type==IMA_TYPE_R_RESULT)
677                                         ima->type= IMA_TYPE_IMAGE;
678                                 
679                                 /* name image as how we saved it */
680                                 len= strlen(str);
681                                 while (len > 0 && str[len - 1] != '/' && str[len - 1] != '\\') len--;
682                                 rename_id(&ima->id, str+len);
683                         } 
684                         else {
685                                 ; // XXX error("Couldn't write image: %s", str);
686                         }
687
688                         // XXX allqueue(REDRAWHEADERS, 0);
689                         // XXX allqueue(REDRAWBUTSSHADING, 0);
690
691                         // XXX waitcursor(0);
692                 }
693         }
694 }
695
696 void open_image_sima(SpaceImage *sima, short imageselect)
697 {
698         char name[FILE_MAXDIR+FILE_MAXFILE];
699
700         if(sima->image)
701                 BLI_strncpy(name, sima->image->name, sizeof(name));
702         else
703                 BLI_strncpy(name, U.textudir, sizeof(name));
704
705         if(imageselect)
706                 ; // XXX activate_imageselect(FILE_SPECIAL, "Open Image", name, load_image_filesel);
707         else
708                 ; // XXX activate_fileselect(FILE_SPECIAL, "Open Image", name, load_image_filesel);
709 }
710
711 void replace_image_sima(SpaceImage *sima, short imageselect)
712 {
713         char name[FILE_MAXDIR+FILE_MAXFILE];
714
715         if(sima->image)
716                 BLI_strncpy(name, sima->image->name, sizeof(name));
717         else
718                 BLI_strncpy(name, U.textudir, sizeof(name));
719         
720         if(imageselect)
721                 ; // XXX activate_imageselect(FILE_SPECIAL, "Replace Image", name, replace_image_filesel);
722         else
723                 ; // XXX activate_fileselect(FILE_SPECIAL, "Replace Image", name, replace_image_filesel);
724 }
725
726
727 static char *filesel_imagetype_string(Image *ima)
728 {
729         char *strp, *str= MEM_callocN(14*32, "menu for filesel");
730         
731         strp= str;
732         str += sprintf(str, "Save Image as: %%t|");
733         str += sprintf(str, "Targa %%x%d|", R_TARGA);
734         str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
735         str += sprintf(str, "PNG %%x%d|", R_PNG);
736         str += sprintf(str, "BMP %%x%d|", R_BMP);
737         str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
738         str += sprintf(str, "Iris %%x%d|", R_IRIS);
739         if(G.have_libtiff)
740                 str += sprintf(str, "Tiff %%x%d|", R_TIFF);
741         str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
742         str += sprintf(str, "Cineon %%x%d|", R_CINEON);
743         str += sprintf(str, "DPX %%x%d|", R_DPX);
744 #ifdef WITH_OPENEXR
745         str += sprintf(str, "OpenEXR %%x%d|", R_OPENEXR);
746         /* saving sequences of multilayer won't work, they copy buffers  */
747         if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER);
748         else str += sprintf(str, "MultiLayer %%x%d|", R_MULTILAYER);
749 #endif  
750         return strp;
751 }
752
753 /* always opens fileselect */
754 void save_as_image_sima(SpaceImage *sima, Scene *scene)
755 {
756         Image *ima = sima->image;
757         ImBuf *ibuf= get_space_image_buffer(sima);
758         char name[FILE_MAXDIR+FILE_MAXFILE];
759
760         if (ima) {
761                 strcpy(name, ima->name);
762
763                 if (ibuf) {
764                         char *strp;
765                         
766                         strp= filesel_imagetype_string(ima);
767                         
768                         /* cant save multilayer sequence, ima->rr isn't valid for a specific frame */
769                         if(ima->rr && !(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER))
770                                 sima->imtypenr= R_MULTILAYER;
771                         else if(ima->type==IMA_TYPE_R_RESULT)
772                                 sima->imtypenr= scene->r.imtype;
773                         else sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
774                         
775                         // XXX activate_fileselect_menu(FILE_SPECIAL, "Save Image", name, strp, &sima->imtypenr, save_image_doit);
776                 }
777         }
778 }
779
780 /* if exists, saves over without fileselect */
781 void save_image_sima(SpaceImage *sima, Scene *scene)
782 {
783         Image *ima = get_space_image(sima);
784         ImBuf *ibuf= get_space_image_buffer(sima);
785         char name[FILE_MAXDIR+FILE_MAXFILE];
786
787         if (ima) {
788                 strcpy(name, ima->name);
789
790                 if (ibuf) {
791                         if (BLI_exists(ibuf->name)) {
792                                 if(BKE_image_get_renderresult(scene, ima)) 
793                                         sima->imtypenr= R_MULTILAYER;
794                                 else 
795                                         sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
796                                 
797                                 save_image_doit(sima, scene, ibuf->name);
798                         }
799                         else
800                                 save_as_image_sima(sima, scene);
801                 }
802         }
803 }
804
805 void save_image_sequence_sima(SpaceImage *sima)
806 {
807         ImBuf *ibuf;
808         int tot= 0;
809         char di[FILE_MAX], fi[FILE_MAX];
810         
811         if(sima->image==NULL)
812                 return;
813         if(sima->image->source!=IMA_SRC_SEQUENCE)
814                 return;
815         if(sima->image->type==IMA_TYPE_MULTILAYER) {
816                 // XXX error("Cannot save Multilayer Sequences");
817                 return;
818         }
819         
820         /* get total */
821         for(ibuf= sima->image->ibufs.first; ibuf; ibuf= ibuf->next) 
822                 if(ibuf->userflags & IB_BITMAPDIRTY)
823                         tot++;
824         
825         if(tot==0) {
826                 // XXX notice("No Images have been changed");
827                 return;
828         }
829         /* get a filename for menu */
830         for(ibuf= sima->image->ibufs.first; ibuf; ibuf= ibuf->next) 
831                 if(ibuf->userflags & IB_BITMAPDIRTY)
832                         break;
833         
834         BLI_strncpy(di, ibuf->name, FILE_MAX);
835         BLI_splitdirstring(di, fi);
836         
837         sprintf(fi, "%d Image(s) will be saved in %s", tot, di);
838         if(1) { // XXX okee(fi)) {
839                 
840                 for(ibuf= sima->image->ibufs.first; ibuf; ibuf= ibuf->next) {
841                         if(ibuf->userflags & IB_BITMAPDIRTY) {
842                                 char name[FILE_MAX];
843                                 BLI_strncpy(name, ibuf->name, sizeof(name));
844                                 
845                                 BLI_convertstringcode(name, G.sce);
846
847                                 if(0 == IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat)) {
848                                         // XXX error("Could not write image", name);
849                                         break;
850                                 }
851                                 printf("Saved: %s\n", ibuf->name);
852                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
853                         }
854                 }
855         }
856 }
857
858 void reload_image_sima(SpaceImage *sima)
859 {
860         if (sima ) {
861                 BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD);
862                 /* set_space_image(sima, scene, obedit, NULL); - do we really need this? */
863         }
864
865         // XXX allqueue(REDRAWIMAGE, 0);
866         // XXX allqueue(REDRAWVIEW3D, 0);
867         // XXX BIF_preview_changed(ID_TE);
868 }
869
870 void new_image_sima(SpaceImage *sima, Scene *scene, Object *obedit)
871 {
872         static int width= 1024, height= 1024;
873         static short uvtestgrid= 0;
874         static int floatbuf=0;
875         static float color[] = {0, 0, 0, 1};
876         char name[22];
877         Image *ima;
878         
879         strcpy(name, "Untitled");
880
881 #if 0
882         add_numbut(0, TEX, "Name:", 0, 21, name, NULL);
883         add_numbut(1, NUM|INT, "Width:", 1, 16384, &width, NULL);
884         add_numbut(2, NUM|INT, "Height:", 1, 16384, &height, NULL);
885         add_numbut(3, COL, "", 0, 0, &color, NULL);
886         add_numbut(4, NUM|FLO, "Alpha:", 0.0, 1.0, &color[3], NULL);
887         add_numbut(5, TOG|SHO, "UV Test Grid", 0, 0, &uvtestgrid, NULL);
888         add_numbut(6, TOG|INT, "32 bit Float", 0, 0, &floatbuf, NULL);
889         if (!do_clever_numbuts("New Image", 7, REDRAW))
890                 return;
891 #endif
892
893         ima = BKE_add_image_size(width, height, name, floatbuf, uvtestgrid, color);
894         set_space_image(sima, scene, obedit, ima);
895         BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
896         // XXX BIF_undo_push("Add image");
897
898         // XXX allqueue(REDRAWIMAGE, 0);
899         // XXX allqueue(REDRAWVIEW3D, 0);
900 }
901
902 void pack_image_sima(SpaceImage *sima)
903 {
904         Image *ima = sima->image;
905
906         if (ima) {
907                 if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) {
908                         if (ima->packedfile) {
909                                 if (G.fileflags & G_AUTOPACK)
910                                         if (1) // XXX okee("Disable AutoPack?"))
911                                                 G.fileflags &= ~G_AUTOPACK;
912                                 
913                                 if ((G.fileflags & G_AUTOPACK) == 0) {
914                                         unpackImage(ima, PF_ASK);
915                                         // XXX BIF_undo_push("Unpack image");
916                                 }
917                         }
918                         else {
919                                 ImBuf *ibuf= get_space_image_buffer(sima);
920                                 if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
921                                         if(1) // XXX okee("Can't pack painted image. Use Repack as PNG?"))
922                                                 BKE_image_memorypack(ima);
923                                 }
924                                 else {
925                                         ima->packedfile = newPackedFile(ima->name);
926                                         // XXX BIF_undo_push("Pack image");
927                                 }
928                         }
929
930                         // XXX allqueue(REDRAWBUTSSHADING, 0);
931                         // XXX allqueue(REDRAWHEADERS, 0);
932                 }
933         }
934 }
935
936 /* XXX notifier? */
937 #if 0
938 /* goes over all ImageUsers, and sets frame numbers if auto-refresh is set */
939 void BIF_image_update_frame(void)
940 {
941         Tex *tex;
942         
943         /* texture users */
944         for(tex= G.main->tex.first; tex; tex= tex->id.next) {
945                 if(tex->type==TEX_IMAGE && tex->ima)
946                         if(ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
947                                 if(tex->iuser.flag & IMA_ANIM_ALWAYS)
948                                         BKE_image_user_calc_imanr(&tex->iuser, scene->r.cfra, 0);
949                 
950         }
951         /* image window, compo node users */
952         if(G.curscreen) {
953                 ScrArea *sa;
954                 for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
955                         if(sa->spacetype==SPACE_VIEW3D) {
956                                 View3D *v3d= sa->spacedata.first;
957                                 if(v3d->bgpic)
958                                         if(v3d->bgpic->iuser.flag & IMA_ANIM_ALWAYS)
959                                                 BKE_image_user_calc_imanr(&v3d->bgpic->iuser, scene->r.cfra, 0);
960                         }
961                         else if(sa->spacetype==SPACE_IMAGE) {
962                                 SpaceImage *sima= sa->spacedata.first;
963                                 if(sima->iuser.flag & IMA_ANIM_ALWAYS)
964                                         BKE_image_user_calc_imanr(&sima->iuser, scene->r.cfra, 0);
965                         }
966                         else if(sa->spacetype==SPACE_NODE) {
967                                 SpaceNode *snode= sa->spacedata.first;
968                                 if((snode->treetype==NTREE_COMPOSIT) && (snode->nodetree)) {
969                                         bNode *node;
970                                         for(node= snode->nodetree->nodes.first; node; node= node->next) {
971                                                 if(node->id && node->type==CMP_NODE_IMAGE) {
972                                                         Image *ima= (Image *)node->id;
973                                                         ImageUser *iuser= node->storage;
974                                                         if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
975                                                                 if(iuser->flag & IMA_ANIM_ALWAYS)
976                                                                         BKE_image_user_calc_imanr(iuser, scene->r.cfra, 0);
977                                                 }
978                                         }
979                                 }
980                         }
981                 }
982         }
983 }
984 #endif
985
986 void image_pixel_aspect(Image *image, float *x, float *y)
987 {
988         *x = *y = 1.0;
989         
990         if(             (image == NULL) ||
991                         (image->type == IMA_TYPE_R_RESULT) ||
992                         (image->type == IMA_TYPE_COMPOSITE) ||
993                         (image->tpageflag & IMA_TILES) ||
994                         (image->aspx==0.0 || image->aspy==0.0)
995         ) {
996                 return;
997         }
998         
999         /* x is always 1 */
1000         *y = image->aspy / image->aspx;
1001 }
1002
1003 void image_final_aspect(Image *image, float *x, float *y)
1004 {
1005         *x = *y = 1.0;
1006         
1007         if(             (image == NULL) ||
1008                         (image->type == IMA_TYPE_R_RESULT) ||
1009                         (image->type == IMA_TYPE_COMPOSITE) ||
1010                         (image->tpageflag & IMA_TILES) ||
1011                         (image->aspx==0.0 || image->aspy==0.0)
1012         ) {
1013                 return;
1014         } else {
1015                 ImBuf *ibuf= BKE_image_get_ibuf(image, NULL);
1016                 if (ibuf && ibuf->x && ibuf->y)  {
1017                         *y = (image->aspy * ibuf->y) / (image->aspx * ibuf->x);
1018                 } else {
1019                         /* x is always 1 */
1020                         *y = image->aspy / image->aspx;
1021                 }
1022         }
1023 }
1024
1025 void sima_sample_color(SpaceImage *sima)
1026 {
1027         ImBuf *ibuf= get_space_image_buffer(sima);
1028         float fx, fy;
1029         short mval[2], mvalo[2], firsttime=1;
1030         
1031         if(ibuf==NULL)
1032                 return;
1033         
1034         // XXX calc_image_view(sima, 'f');
1035         // XXX getmouseco_areawin(mvalo);
1036         
1037         while(0) { // XXX get_mbut() & L_MOUSE) {
1038                 
1039                 // XXX getmouseco_areawin(mval);
1040                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || firsttime) {
1041                         firsttime= 0;
1042                         // XXX areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
1043                         
1044                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
1045                                 float *fp= NULL, *zpf= NULL;
1046                                 float vec[3];
1047                                 int *zp= NULL;
1048                                 char *cp= NULL;
1049                                 
1050                                 int x= (int) (fx*ibuf->x);
1051                                 int y= (int) (fy*ibuf->y);
1052                                 
1053                                 if(x>=ibuf->x) x= ibuf->x-1;
1054                                 if(y>=ibuf->y) y= ibuf->y-1;
1055                                 
1056                                 if(ibuf->rect)
1057                                         cp= (char *)(ibuf->rect + y*ibuf->x + x);
1058                                 if(ibuf->zbuf)
1059                                         zp= ibuf->zbuf + y*ibuf->x + x;
1060                                 if(ibuf->zbuf_float)
1061                                         zpf= ibuf->zbuf_float + y*ibuf->x + x;
1062                                 if(ibuf->rect_float)
1063                                         fp= (ibuf->rect_float + (ibuf->channels)*(y*ibuf->x + x));
1064                                         
1065                                 if(fp==NULL) {
1066                                         fp= vec;
1067                                         vec[0]= (float)cp[0]/255.0f;
1068                                         vec[1]= (float)cp[1]/255.0f;
1069                                         vec[2]= (float)cp[2]/255.0f;
1070                                 }
1071                                 
1072                                 if(sima->cumap) {
1073                                         
1074                                         if(ibuf->channels==4) {
1075                                                 if(0) { // XXX G.qual & LR_CTRLKEY) {
1076                                                         curvemapping_set_black_white(sima->cumap, NULL, fp);
1077                                                         curvemapping_do_ibuf(sima->cumap, ibuf);
1078                                                 }
1079                                                 else if(0) { // XXX G.qual & LR_SHIFTKEY) {
1080                                                         curvemapping_set_black_white(sima->cumap, fp, NULL);
1081                                                         curvemapping_do_ibuf(sima->cumap, ibuf);
1082                                                 }
1083                                         }
1084                                 }
1085                                 
1086 #if 0
1087                                 {
1088                                         ScrArea *sa, *cur= curarea;
1089                                         
1090                                         node_curvemap_sample(fp);       /* sends global to node editor */
1091                                         for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1092                                                 if(sa->spacetype==SPACE_NODE) {
1093                                                         areawinset(sa->win);
1094                                                         scrarea_do_windraw(sa);
1095                                                 }
1096                                         }
1097                                         node_curvemap_sample(NULL);             /* clears global in node editor */
1098                                         curarea= cur;
1099                                 }
1100                                 
1101                                 areawinset(curarea->win);
1102                                 scrarea_do_windraw(curarea);
1103                                 myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
1104                                 glLoadIdentity();
1105                                 
1106                                 sima_show_info(ibuf->channels, x, y, cp, (ibuf->rect_float)?fp:NULL, zp, zpf);
1107                                 
1108                                 screen_swapbuffers();
1109 #endif
1110                                 
1111                         }
1112                 }
1113                 // XXX BIF_wait_for_statechange();
1114         }
1115         
1116         // XXX scrarea_queue_winredraw(curarea);
1117 }
1118
1119 void mouseco_to_curtile(SpaceImage *sima, struct Object *obedit)
1120 {
1121         float fx, fy;
1122         short mval[2];
1123         int show_uvedit;
1124         
1125         show_uvedit= get_space_image_show_uvedit(sima, obedit);
1126         if(!show_uvedit) return;
1127
1128         if(sima->image && sima->image->tpageflag & IMA_TILES) {
1129                 
1130                 sima->flag |= SI_EDITTILE;
1131                 
1132                 while(0) { // XXX get_mbut()&L_MOUSE) {
1133                         
1134                         // XXX calc_image_view(sima, 'f');
1135                         
1136                         // XXX getmouseco_areawin(mval);
1137                         // XXX areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
1138
1139                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
1140                         
1141                                 fx= (fx)*sima->image->xrep;
1142                                 fy= (fy)*sima->image->yrep;
1143                                 
1144                                 mval[0]= fx;
1145                                 mval[1]= fy;
1146                                 
1147                                 sima->curtile= mval[1]*sima->image->xrep + mval[0];
1148                         }
1149
1150                         // XXX scrarea_do_windraw(curarea);
1151                         // XXX screen_swapbuffers();
1152                 }
1153                 
1154                 sima->flag &= ~SI_EDITTILE;
1155
1156                 // XXX image_set_tile(sima, 2);
1157
1158                 // XXX allqueue(REDRAWVIEW3D, 0);
1159                 // XXX scrarea_queue_winredraw(curarea);
1160         }
1161 }
1162
1163 /* Could be used for other 2D views also */
1164 void mouseco_to_cursor_sima(void)
1165 {
1166         // XXX short mval[2];
1167         // XXX getmouseco_areawin(mval);
1168         // XXX areamouseco_to_ipoco(G.v2d, mval, &G.v2d->cursor[0], &G.v2d->cursor[1]);
1169         // XXX scrarea_queue_winredraw(curarea);
1170 }
1171