Initial git commit -- Transition from CodeGuard repository
[sdk] / ide / src / documents / PictureEdit.ec
1 /****************************************************************************
2    ECERE IDE
3
4    Copyright (c) 2003 Jerome Jacovella-St-Louis
5    All Rights Reserved.
6    
7    pictureEdit.ec - Picture Editor Control
8 ****************************************************************************/
9 #ifdef ECERE_STATIC
10 import static "ecere"
11 #else
12 import "ecere"
13 #endif
14
15 #define ID_IMAGE_MODE_COLORTABLE 9
16 #define ID_IMAGE_MODE_INDEXED    10
17 #define ID_IMAGE_MODE_RGB        11
18
19 static FileFilter filters[] =
20 {
21    {
22       "Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png, *.gif)",
23       "jpg, jpeg, bmp, pcx, png, gif"
24    },
25    { "All files", null }
26 };
27
28 static FileType types[] =
29 {
30    { "Based on extension", null,  never },
31    { "JPG Image",          "jpg", always },
32    { "BMP Image",          "bmp", always },
33    { "PCX Image",          "pcx", always },
34    { "PNG Image",          "png", always },
35    { "GIF Image",          "gif", always }
36 };
37
38 FileDialog pictureEditFileDialog { filters = filters, sizeFilters = sizeof(filters), types = types, sizeTypes = sizeof(types) };
39
40 class PictureEdit : Window
41 {
42    background = black;
43    isDocument = true;
44    isActiveClient = true;
45    menu = Menu { };
46
47    OnHScroll = OnScroll;
48    OnVScroll = OnScroll;
49
50    float zoomFactor;
51    char fileName[MAX_LOCATION];
52    Bitmap bitmap;
53    
54    //saveDialog = pictureEditFileDialog;
55    
56    Menu fileMenu { menu, "File", f }
57       MenuItem { fileMenu, "Save", s, ctrlS, NotifySelect = MenuFileSave };
58       MenuItem { fileMenu, "Save As...", a, NotifySelect = MenuFileSaveAs };
59    Menu imageMenu { menu, "Image", i };
60       Menu modeMenu { imageMenu, "Mode", m };
61          MenuItem imageModeIndexedItem
62          {
63             modeMenu, "Indexed Color...", i, isRadio = true;
64             bool NotifySelect(MenuItem selection, Modifiers mods)
65             {
66                ColorAlpha * palette = bitmap.Quantize(0, 255);
67                /*
68                eBitmap_Convert(null, bitmap, PixelFormat8, palette);
69                bitmap.allocatePalette = true;
70                */               
71                
72                imageModeColorTableItem.disabled = false;
73                Update(null);
74                modifiedDocument = true;
75                return true;
76             }
77          };
78          MenuItem imageModeRGBItem
79          {
80             modeMenu, "RGB Color", r, isRadio = true;
81             bool NotifySelect(MenuItem selection, Modifiers mods)
82             {
83                bitmap.Convert(null, pixelFormat888, null);
84                imageModeColorTableItem.disabled = true;
85                Update(null);
86                modifiedDocument = true;
87                return true;
88             }
89          };
90          MenuDivider { modeMenu };
91          MenuItem imageModeColorTableItem
92          {
93             modeMenu, "Color Table", r;
94             bool NotifySelect(MenuItem selection, Modifiers mods)
95             {
96                PictureEditColorTable colorTable { master = this };
97                colorTable.Modal();
98                Update(null);
99                return true;
100             }
101          };
102          #ifdef _DEBUG
103          MenuDivider { imageMenu };
104          MenuItem adjustHSVItem
105          {
106             imageMenu, "Adjust Hue, Saturation, Value", h;
107             bool NotifySelect(MenuItem selection, Modifiers mods)
108             {
109                AdjustHSV adjustHSV { master = this };
110                adjustHSV.Modal();
111                Update(null);
112                return true;
113             }
114          };
115          #endif
116    
117    property char * bitmapFile
118    {
119       set
120       {
121          if(value)
122          {
123             strcpy(fileName, value);
124          }
125          if(fileName[0])
126          {
127             bitmap = Bitmap {};
128             if(bitmap.Load(fileName, null, null))
129             {
130                if(bitmap.pixelFormat == pixelFormatRGBA)
131                   bitmap.Convert(null, pixelFormat888, null);
132
133                //if(!eWindow_GetStartWidth(window) || !eWindow_GetStartHeight(window))
134                {
135                   Size size = initSize;  // what's the use of retrieving initSize
136                   size.w = bitmap.width;
137                   size.h = bitmap.height;
138                   clientSize = size;
139
140                   /*
141                   Move(eWindow_GetStartX(window), eWindow_GetStartY(window), 
142                      (!eWindow_GetStartWidth(window)) ? (A_CLIENT|bitmap.width) : eWindow_GetStartWidth(window), 
143                      (!eWindow_GetStartHeight(window)) ? (A_CLIENT|bitmap.height) : eWindow_GetStartHeight(window));
144                   */
145
146                   /*
147                   Move(eWindow_GetStartX(window), eWindow_GetStartY(window), 
148                      (!) ? (A_CLIENT|bitmap.width) : eWindow_GetStartWidth(window), 
149                      (!eWindow_GetStartHeight(window)) ? (A_CLIENT|bitmap.height) : eWindow_GetStartHeight(window));
150                   */
151                }
152                scrollArea = Size {bitmap.width, bitmap.height };
153             }
154             else
155                delete bitmap;
156          }
157
158          if(bitmap)
159          {
160             switch(bitmap.pixelFormat)
161             {
162                case pixelFormat8:
163                   imageModeIndexedItem.checked = true;
164                   break;
165                case pixelFormat888:
166                   imageModeRGBItem.checked = true;
167                   imageModeColorTableItem.disabled = true;
168                   break;
169             }
170          }
171       }
172    }
173
174    void OnRedraw(Surface surface)
175    {
176       if(bitmap)
177       {
178          int w = (int)(bitmap.width * zoomFactor);
179          int h = (int)(bitmap.height * zoomFactor);
180          if(w == bitmap.width && h == bitmap.height)
181          {
182             surface.Blit(bitmap, 
183                Max(0, (clientSize.w - w) / 2), Max(0, (clientSize.h - h) / 2), 
184                scroll.x, scroll.y, w, h);
185          }
186          else
187          {
188             surface.Filter(bitmap, 
189                Max(0, (clientSize.w - w) / 2), Max(0, (clientSize.h - h) / 2), 
190                (int)(scroll.x / zoomFactor), (int)(scroll.y / zoomFactor), w, h, 
191                bitmap.width, bitmap.height);
192          }
193       }
194    }
195
196    void OnScroll(ScrollBarAction action, int position, Key key)
197    {
198       Update(null);
199    }
200
201    bool OnKeyHit(Key key, unichar ch)
202    {
203       switch(key)
204       {
205          case equal:
206          case keyPadPlus:
207             if(zoomFactor < 25)
208             {
209                float x = 0.5f, y = 0.5f;
210                if(bitmap.width * zoomFactor > clientSize.w) 
211                   x = scroll.x / (bitmap.width * zoomFactor - clientSize.w);
212                if(bitmap.height * zoomFactor > clientSize.h) 
213                   y = scroll.y / (bitmap.height * zoomFactor - clientSize.h);
214
215                zoomFactor *= 1.5;
216                scrollArea = Size { bitmap.width * zoomFactor,  bitmap.height * zoomFactor };
217
218                scroll = Point { 
219                      (int)(Max(0, bitmap.width * zoomFactor - clientSize.w) * x), 
220                      (int)(Max(0, bitmap.height * zoomFactor - clientSize.h) * y) };
221
222                Update(null);
223             }
224             break;
225          case minus:
226          case keyPadMinus:
227             if(zoomFactor > 0.05)
228             {
229                float x = 0.5f, y = 0.5f;
230                if(bitmap.width * zoomFactor > clientSize.w) 
231                   x = scroll.x / (bitmap.width * zoomFactor - clientSize.w);
232                if(bitmap.height * zoomFactor > clientSize.w) 
233                   y = scroll.y / (bitmap.height * zoomFactor - clientSize.h);
234
235                zoomFactor /= 1.5;
236                scrollArea = Size { bitmap.width * zoomFactor, bitmap.height * zoomFactor };
237
238                scroll = Point { 
239                      (int)(Max(0, bitmap.width * zoomFactor - clientSize.w) * x),
240                      (int)(Max(0, bitmap.height * zoomFactor - clientSize.h) * y) };
241
242                Update(null);
243             }
244             break;
245       }
246       return true;
247    }
248
249    bool OnSaveFile(char * fileName)
250    {
251       bool result = false;
252       if(bitmap)
253       {
254          if(bitmap.Save(fileName, 
255             ((FileType *)pictureEditFileDialog.types)[pictureEditFileDialog.fileType].typeExtension, (void *) bool::true))
256          {
257             modifiedDocument = false;
258             result = true;
259          }
260       }
261       return result;
262    }
263    
264    PictureEdit()
265    {
266       zoomFactor = 1.0f;
267       return true;
268    }
269
270 }
271
272 class PictureEditColorTable : Window
273 {
274    hasClose = true;
275    text = "Color Table";
276    background = activeBorder;
277    minClientSize = Size { 400, 400 };
278
279    Button button
280    {
281       parent = this, hotKey = escape, size = { 80 }, text = "Close";
282       anchor = Anchor { right = 10, bottom = 10 };
283       NotifyClicked = ButtonCloseDialog;
284    };
285
286    void OnRedraw(Surface surface)
287    {
288       PictureEdit picture = (PictureEdit)master;
289       Bitmap bitmap = picture.bitmap;
290       int c;
291       for(c = 0; c < 256; c++)
292       {
293          int x = (c % 16) * 16;
294          int y = (c / 16) * 16;
295          surface.SetBackground(bitmap.palette[c]);
296          surface.Area(10 + x, 30 + y, 10 + x + 15, 30 + y + 15);
297       }
298    }
299 }
300
301 class ColorBox : Window
302 {
303    size = { 32, 32 };
304    borderStyle = deepContour;
305 }
306
307 #ifdef _DEBUG
308 class AdjustHSV : Window
309 {
310    size = { 400, 300 };
311
312    background = activeBorder;
313    ColorHSV target;
314    ColorHSV replace;
315    replace = { 248, 100, 71 }; //Color { 26, 0, 183 };
316    target = { 207, 61, 71 };
317    hasClose = true;
318
319    Button button1
320    {
321       this, text = "Go", position = { 296, 104 }, isDefault = true;
322
323       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
324       {
325          PictureEdit picture = (PictureEdit)master;
326          Bitmap bitmap = picture.bitmap;
327          double h = 1.0f, s = 0.80f, v = 1.24f;
328          double tolH = 1;
329          double tolS = 1;
330          double tolV = 1;
331          
332          h = target.h - replace.h;
333          s = target.s / replace.s;
334          v = target.v / replace.v;
335
336          for(y = 0; y<bitmap.height; y++)
337          {
338             for(x = 0; x<bitmap.width; x++)
339             {
340                ColorAlpha color = ((ColorAlpha *)bitmap.picture)[y * bitmap.stride + x];
341                ColorHSV hsv = color;
342                double diffH = Abs(hsv.h/360 - replace.h/360);
343                double diffS = Abs(hsv.s - replace.s)/100.0;
344                double diffV = Abs(hsv.v - replace.v)/100.0;
345                if(diffH <= tolH && diffS <= tolS && diffV <= tolV)
346                {
347                   hsv.h += h;
348                   hsv.s *= s;
349                   hsv.v *= v;
350                   color.color = hsv;
351                   ((ColorAlpha *)bitmap.picture)[y * bitmap.stride + x] = color;
352                }
353             }
354          }
355          picture.Update(null);
356          picture.modifiedDocument = true;
357          Destroy(0);
358          return true;
359       }
360    };
361
362    EditBox hBox { this, text = "H", size = { 78, 19 }, position = { 176, 80 } };
363    EditBox sBox { this, text = "S", size = { 78, 19 }, position = { 176, 120 } };
364    EditBox vBox { this, text = "V", size = { 78, 19 }, position = { 176, 160 } };
365    Label label1 { this, size = { 7, 13 }, position = { 152, 80 }, labeledWindow = hBox };
366    Label label2 { this, size = { 6, 13 }, position = { 152, 120 }, labeledWindow = sBox };
367    Label label3 { this, size = { 6, 13 }, position = { 152, 168 }, labeledWindow = vBox };
368    ColorBox original { this, position = { 10, 10 }, background = replace };
369    ColorBox result { this, position = { 10, 100 }, background = target };
370 }
371 #endif