image_converter._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2004 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * $Id: image_converter.pike,v 1.1 2008/03/31 13:39:57 exodusd Exp $
18  */
19 inherit "/kernel/module";
20 #include <classes.h>
21 #include <attributes.h>
22 #include <macros.h>
23 //! Converts images from one format to another. The most
24 //! important function is the get_image() function of this module.
25 //!
26 class image_converter : public module{
27 public:
28 
29 
30 
31 
32 import htmllib;
33 
34 
35 #define _FILEPATH _Server->get_module("filepath:tree")
36 #define MODULE_FONT_CACHE _Server->get_module("fonts:TTF")
37 
38 
39 
40 /**
41  * Get a font according to font-description
42  * substitutes the default font, if no matching font can be found.
43  * @param type - the fonts name
44  * @param style - 0 plain, 1 bold, 2 italic (bitwise or to use combinations)
45  * @param size - fontsize
46  */
47 private:
48 private Image.Font get_font(string type, int style, int size)
49 {
50  Image.Font oTTF;
51  if ( objectp(MODULE_FONT_CACHE) )
52  {
53  oTTF=MODULE_FONT_CACHE->get_font_object(type, style);
54 
55  if (objectp(oTTF))
56  {
57  oTTF = oTTF();
58  oTTF->set_height(size);
59  return oTTF;
60  }
61  }
62  return Image.Font();
63 }
64 
65 public:
66 
67 private:
68 private array __text_extends(array list, object font)
69 {
70  mapping(int:int) width_cache=([]);
71  array result = ({});
72 
73  foreach(list, string s)
74  {
75  int width=0, w;
76  foreach(s/"", string c)
77  {
78  if (w=width_cache[c[0]])
79  width+=w;
80  else
81  {
82  width_cache[c[0]]=w=font->write(c)->xsize();
83  width+=w;
84  }
85  }
86  result += ({ width });
87  }
88  return result;
89 }
90 
91 public:
92 
93 private:
94 private array wrap_with_font(string from, int width, object font)
95 {
96  // array charlens = font->text_extends(from/"");
97  // doesn't work inspite of the Pike Dokumentation
98  array charlens = __text_extends(from/"", font);
99  int i,sz;
100  int last_pos = 0;
101  int curr_len = 0;
102  array result = ({});
103 
104  for (i=0,sz=sizeof(charlens);i<sz;i++)
105  {
106  if (from[i]=='\n')
107  {
108  result += ({ from[last_pos..i-1] });
109  curr_len = 0;
110  i++;
111  last_pos = i;
112  }
113  else
114  {
115  if ((curr_len < width) ||
116  (font->write(from[last_pos..i-1])->xsize()) < width)
117  curr_len += charlens[i];
118  else
119  {
120  if (from[i]==' ')
121  while (from[i]==' ') i++;
122  else {
123  int oldi=i;
124  while (from[i]!=' ' && i>last_pos) i--;
125  i++;
126  if (i==last_pos) i=oldi;
127  }
128  result += ({ from[last_pos..i-1] });
129  last_pos = i;
130  curr_len = 0;
131  }
132  }
133  }
134  result += ({ from[last_pos..sz] });
135  LOG("number of lines wrapped is"+sizeof(result));
136  return result;
137 }
138 
139 public:
140 
141 private:
142 private object hard_default_icon(int iOclass)
143 {
144  string sImagePath;
145 
146  if (iOclass & CLASS_CONTAINER)
147  if (iOclass & CLASS_ROOM)
148  sImagePath = "/images/doctypes/type_room.gif";
149  else
150  sImagePath = "/images/doctypes/type_folder.gif";
151 
152  if (iOclass & CLASS_DOCLPC)
153  sImagePath = "/images/doctypes/type_object.gif";
154 
155  object oIcon=_FILEPATH->path_to_object(sImagePath);
156 }
157 
158 public:
159 
160 private:
161 private Image.Layer image_from_object(object oIcon)
162 {
163  string sMime = oIcon->query_attribute(DOC_MIME_TYPE);
164  if (!sMime)
165  sMime = "ANY";
166  else
167  sscanf(sMime, "image/%s", sMime);
168  sMime = upper_case(sMime);
169 
170  LOG("sMime in image_from_object is "+sMime);
171  string content = oIcon->get_content();
172  if (strlen(content))
173  {
174  object oInputImageCoder = Image[sMime];
175  if (objectp(oInputImageCoder))
176  if (sMime=="GIF")
177  return oInputImageCoder->decode_layer(content)->image();
178  else
179  return oInputImageCoder->decode(content);
180  }
181 }
182 
183 public:
184 
185 
186 /**
187  * Get an image representation of given (container) object (if any)
188  *
189  * @param obj - the object to represent
190  * @param x - x-size of image
191  * @param y - y-size of image
192  * @param encoding - an image/encoding (e.g. image/jpeg)
193  * @return a string containing the image of given encoding
194  */
195 string get_image(object obj, int x, int y, string encoding)
196 {
197  array aoInv;
198  Image.Image oLine;
199  Image.Image oIcon;
200  object oTempImage;
201 
202  string sImagePath = "/images/doctypes/type_generic.gif";
203 
204  if (!(obj->get_object_class() & CLASS_CONTAINER))
205  return 0;
206 
207  aoInv = obj->get_inventory();
208  if (!arrayp(aoInv))
209  return 0;
210 
211  mapping mLayer = obj->query_attribute("WHITEBOARD_ATTR_LAYER_INFO");
212  if (mLayer)
213  {
214  foreach(aoInv, object o)
215  LOG("["+o->get_object_id()+"]");
216  mLayer -= ({"size"});
217  mapping(int:int) LayTable = ([]);
218  foreach(indices(mLayer), int layer)
219  LayTable[mLayer[layer]]=layer;
220  array ordered = allocate(sizeof(mLayer));
221 
222  int p;
223  for (int i=0; i<sizeof(aoInv); i++)
224  {
225  p=LayTable[aoInv[i]->get_object_id()];
226  if (!zero_type(p))
227  {
228  LOG("p for "+aoInv[i]->get_object_id()+" is "+p+"("+
229  aoInv[i]->get_identifier()+")");
230  ordered[p]=aoInv[i];
231  aoInv[i]=0;
232  }
233  }
234  aoInv += reverse(ordered);
235  aoInv -= ({ 0});
236  foreach(aoInv, object o)
237  LOG("["+o->get_object_id()+"]");
238  }
239  if (!x || x < 0)
240  {
241  x = (int) obj->query_attribute(CONT_SIZE_X);
242  if (!x) x = 1646;
243  }
244  if (!y || y < 0)
245  {
246  y = (int) obj->query_attribute(CONT_SIZE_Y);
247  if (!y) y = 1442;
248  }
249 
250  object oImage = Image.Image(x, y);
251  // object oColor = Image.Color()
252  oImage->box(0,0,x,y,255,255,255);
253  oImage->box(0,0,0,0,0,0,0);
254  // to do ... sort by WHITEBOARD_ATTR_LAYER_INFO
255 
256  foreach(aoInv, object graphics)
257  {
258  LOG("I:"+sprintf("%O", graphics));
259  int x1 = (int) graphics->query_attribute(OBJ_POSITION_X);
260  int w = (int) graphics->query_attribute(DRAWING_WIDTH);
261  int x2 = (int) x1+ w;
262  int y1 = (int) graphics->query_attribute(OBJ_POSITION_Y);
263  int h = (int) graphics->query_attribute(DRAWING_HEIGHT);
264  int y2 = (int) y1+h;
265  int iColor = graphics->query_attribute(DRAWING_COLOR);
266 
267  int r,g,b;
268 
269  b = iColor & 511;
270  iColor = iColor >> 8;
271  g = iColor & 511;
272  iColor = iColor >> 8;
273  r = iColor & 511;
274 
275  int iOclass;
276 
277  if (!((iOclass = graphics->get_object_class()) &
278  (CLASS_DRAWING|CLASS_USER )))
279  {
280  oIcon=graphics->query_attribute(OBJ_ICON);
281  if (!oIcon)
282  oIcon= hard_default_icon(iOclass);
283 
284  if (oIcon)
285  {
286  catch {oTempImage = image_from_object(oIcon);};
287  if (oTempImage)
288  {
289  oLine = Image.Font()->write(graphics->get_identifier());
290  oImage->paste_alpha_color(
291  oLine, 0,0,0,
292  x1,
293  (y1+oTempImage->ysize())
294  );
295  oImage->paste(oTempImage, x1-(oTempImage->xsize()/2)+(oLine->xsize()/2), y1);
296  }
297  }
298  }
299 
300  switch (graphics->query_attribute(DRAWING_TYPE))
301  {
302  case DRAWING_LINE :
303  if (graphics->query_attribute("LINE_ATTR_DIRECTION") == 1)
304  oImage->line(x1, y1, x2, y2, r, g, b);
305  else
306  oImage->line(x1, y2, x2, y1, r, g, b);
307  break;
308  case DRAWING_RECTANGLE:
309  oImage->line(x1, y1, x2, y1, r, g, b);
310  oImage->line(x1, y1, x1, y2, r, g, b);
311  oImage->line(x2, y1, x2, y2, r, g, b);
312  oImage->line(x1, y2, x2, y2, r, g, b);
313  break;
314  //case DRAWING_TRIANGLE:
315  //case DRAWING_POLYGON:
316  //case DRAWO
317  case DRAWING_CIRCLE :
318  oImage->circle((x1+x2)/2,(y1+y2)/2,
319  (int)(w/2), (int) (h/2), r, g, b);//, 0, 255, 0);
320  break;
321 
322  case 9: // embedded image
323  oIcon = graphics->query_attribute("IMAGE_ATTR_IMAGEOBJECT");
324  if (oIcon)
325  {
326  catch {oTempImage = image_from_object(oIcon);};
327  if (oTempImage)
328  {
329  float xf = (float)w /(float)oTempImage->xsize();
330  float yf = (float)h /(float)oTempImage->ysize();
331  oImage->paste(oTempImage->scale(xf,yf), x1, y1);
332  }
333  }
334  break;
335  case 10: // filled rectangle
336  oImage->box(x1,y1,x2,y2, r,g,b);
337  break;
338  case 11: // filled circle
339  oTempImage = Image.Image(w,h);
340  oTempImage->circle(w/2, h/2, w/2, h/2, 255, 255, 255);
341  oImage->paste_alpha_color(
342  oTempImage->select_from(w/2,h/2), r,g,b,x1,y1);
343  break;
344  case DRAWING_TEXT : // obsolete, but for compatibility reasons.
345  case 16 : // multiline text
346  string fontfile = graphics->query_attribute("TEXT_ATTR_TYPE");
347  int fontstyle = graphics->query_attribute("TEXT_ATTR_STYLE");
348  string textlabel = graphics->query_attribute("TEXT_ATTR_TEXT");
349  int fontsize = graphics->query_attribute("TEXT_ATTR_SIZE");
350 
351  object oFont = get_font(fontfile, fontstyle, fontsize);
352 
353  /*if ( stringp(textlabel) )
354  {
355  oLine = oFont->write(textlabel);
356  oImage->paste_alpha_color(oLine, r,g,b, x1, y1);
357  }*/
358  if (stringp(textlabel))
359  {
360  array splitted =
361  wrap_with_font(textlabel, w, oFont);
362  for (int i=0;i<sizeof(splitted);i++)
363  {
364  LOG("Line"+i+":"+splitted[i]);
365  oLine = oFont->write(splitted[i]);
366  oImage->paste_alpha_color(oLine, r,g,b, x1, y1);
367  y1 += (int)(oLine->ysize()*1.2);
368  }
369  }
370  break;
371  default:
372  LOG("unknown graphixtype:"+
373  graphics->query_attribute(DRAWING_TYPE));
374  }
375  }
376  if (!encoding) // use a free one by default!
377  encoding = "image/jpeg";
378 
379  string sImageCoder;
380  sscanf(encoding, "image/%s", sImageCoder);
381  sImageCoder = upper_case(sImageCoder);
382  object oImageCoder = Image[sImageCoder];
383 
384  if (!oImageCoder)
385  return 0;
386 
387  return oImageCoder->encode(oImage);
388 }
389 
390 string get_image_map(object obj, void|mapping vars)
391 {
392  array aoInv;
393  object oLine;
394  string sImageMap;
395  string sImagePath = "/images/doctypes/type_generic.gif";
396 
397  if (!(obj->get_object_class() & CLASS_CONTAINER))
398  return 0;
399 
400  aoInv = obj->get_inventory();
401  if (!arrayp(aoInv))
402  return 0;
403 
404  sImageMap = "<map name=\""+obj->get_object_id()+"\">\n";
405  foreach(aoInv, object graphics)
406  {
407  int iOclass;
408 
409  if (!((iOclass = graphics->get_object_class())
410  & (CLASS_DRAWING|CLASS_USER)))
411  {
412  int x1 = (int) graphics->query_attribute(OBJ_POSITION_X);
413  int w = (int) graphics->query_attribute(DRAWING_WIDTH);
414  int y1 = (int) graphics->query_attribute(OBJ_POSITION_Y);
415  int h = (int) graphics->query_attribute(DRAWING_HEIGHT);
416 
417  if (!w || !h)
418  {
419  object oIcon = graphics->query_attribute(OBJ_ICON);
420  if ( !objectp(oIcon) )
421  continue;
422  string sMime = oIcon->query_attribute(DOC_MIME_TYPE);
423  if (!sMime)
424  sMime = "ANY";
425  else
426  sscanf(sMime, "image/%s", sMime);
427  sMime = upper_case(sMime);
428 
429  MESSAGE("Module"+sMime);
430  object oInputImageCoder = Image[sMime];
431  if (objectp(oInputImageCoder))
432  {
433  MESSAGE("ImageCoder:"+master()->describe_object(oInputImageCoder));
434  mapping mIconData;
435  if (sMime == "GIF")
436  mIconData =
437  oInputImageCoder->decode_map(oIcon->get_content());
438  else
439  mIconData =
440  oInputImageCoder->_decode(oIcon->get_content());
441  w = mIconData["xsize"];
442  h = mIconData["ysize"];
443  }
444  }
445 
446  sImageMap +=" <area shape=\"rect\" coords=\""+
447  x1+ ", " + y1 + ", " + (x1+w) + ", " + (y1+h) +"\" "+
448  href_link_navigate_postfix(graphics, vars->prefix, vars->postfix)+"/>\n";
449 
450  oLine = Image.Font()->write(graphics->get_identifier());
451  sImageMap +=" <area shape=\"rect\" coords=\""+
452  (x1+(w/2)-(oLine->xsize()/2))+", "+
453  (y1+h+5)+", "+
454  (x1+(w/2)+(oLine->xsize()/2))+", "+
455  (y1+h+5+oLine->ysize())+"\" "+
456  href_link_navigate_postfix(graphics, vars->prefix, vars->postfix)+"/>\n";
457  }
458  }
459  int x = -1;
460  int y = -1;
461  if (stringp(vars["x"])) x = (int)vars["x"];
462  if (intp(vars["x"])) x = vars["x"];
463  if (stringp(vars["y"])) y = (int)vars["y"];
464  if (intp(vars["x"])) y = vars["y"];
465  sImageMap += "</map> <img src=\"/scripts/svg.svg?object="+obj->get_object_id()+
466  "&amp;enc=image/jpeg&amp;x="+x+"&amp;y="+y+"\" usemap=\"#"+obj->get_object_id()+"\"/>\n";
467 
468  return sImageMap;
469 }
470 
471 string get_identifier() { return "Converter:IMAGE"; }
472 
473 
474 };