OSDN Git Service

imagesize function.
authorvisor <visor@users.sourceforge.jp>
Mon, 11 Mar 2013 14:22:54 +0000 (23:22 +0900)
committervisor <visor@users.sourceforge.jp>
Mon, 11 Mar 2013 14:22:54 +0000 (23:22 +0900)
Makefile.src
lib/memcursor.h [new file with mode: 0644]
modules/ml-imagesize.cc [new file with mode: 0644]
modules/ml-imagesize.h [new file with mode: 0644]

index 8fcbddf..b941776 100644 (file)
@@ -1,3 +1,4 @@
+MSRCS += ml-imagesize.cc
 MSRCS += ml-security.cc
 MLDADD += -lmd
 #MSRCS += ml-fetch.cc
diff --git a/lib/memcursor.h b/lib/memcursor.h
new file mode 100644 (file)
index 0000000..ab9aede
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef MEMCURSOR_H
+#define MEMCURSOR_H
+
+class  MemCursor {
+ public:
+    uiterator  b;
+    uiterator  e;
+    int  bitOffset;
+    uint32_t  bitPool;
+
+    MemCursor (const ustring* data) {
+       b = data->begin ();
+       e = data->end ();
+    };
+    virtual  ~MemCursor () {};
+
+    virtual bool  empty () {
+       return b >= e;
+    };
+    virtual ssize_t  size () {
+       return e - b;
+    };
+//    virtual bool  cap (size_t size) {
+//     return b + size <= e;
+//    };
+    virtual uint32_t  ui8 () {
+       uint8_t  ans = *b;
+       ++ b;
+       return ans;
+    };
+    virtual uint32_t  ui16n () {
+       return ui8 () * 256 + ui8 ();
+    };
+    virtual uint32_t  ui16 () {
+       return ui8 () + ui8 () * 256;
+    };
+    virtual uint32_t  ui32n () {
+       return ((ui8 () * 256 + ui8 ()) * 256 + ui8 ()) * 256 + ui8 ();
+    };
+//    virtual uint32_t  ui32 ();
+//    virtual int32_t  si16 ();
+//    virtual int32_t  si32 ();
+//    virtual ustring  block (size_t len);
+//    virtual ustring  block ();
+    virtual void  skip (size_t len) {
+       b += len;
+    };
+//    virtual ustring  cstring ();
+//    virtual ustring  pstring ();
+    virtual bool  matchSkip (const char* t, size_t s) {
+       return ::matchSkip (b, e, t, s);
+    };
+    virtual void  initBit () {
+       bitOffset = 0;
+    };
+    virtual uint32_t  ub (int n) {
+       uint32_t  ans = 0;
+       int  nc = n;
+       
+       while (nc > 0) {
+           if (bitOffset == 0) {
+               bitPool = ui8 ();
+               bitOffset = 8;
+           }
+           if (nc >= bitOffset) {
+               nc -= bitOffset;
+               ans |= bitPool << nc;
+               bitOffset = 0;
+           } else {
+               bitOffset -= nc;
+               ans |= bitPool >> bitOffset;
+               bitPool &= (1 << bitOffset) - 1;
+               nc = 0;
+           }
+       }
+       return ans;
+    };
+    virtual int32_t  sb (int n) {
+       int32_t  ans = 0;
+       
+       if (n > 0) {
+           if (ub (1)) {
+               ans = ub (n - 1) - (1L << (n - 1));
+           } else {
+               ans = ub (n - 1);
+           }
+       } else {
+           ans = 0;
+       }
+       return ans;
+    };
+};
+
+#endif /* MEMCURSOR_H */
diff --git a/modules/ml-imagesize.cc b/modules/ml-imagesize.cc
new file mode 100644 (file)
index 0000000..7779df6
--- /dev/null
@@ -0,0 +1,187 @@
+#include "ml-imagesize.h"
+#include "ml-store.h"
+#include "ml.h"
+#include "mlenv.h"
+#include "expr.h"
+#include "util_string.h"
+#include "util_const.h"
+#include "memcursor.h"
+#include "ustring.h"
+#include "filemacro.h"
+
+/*DOC:
+==image size function==
+画像ファイルのサイズを取得する。
+
+*/
+
+static bool  gifSize (ustring* data, size_t& x, size_t& y) {
+    MemCursor  csr (data);
+
+    csr.skip (6);
+//    if (csr.cap (4)) {
+    if (csr.size () >= 4) {
+       x = csr.ui16 ();
+       y = csr.ui16 ();
+       return true;
+    }
+    return false;
+}
+
+static bool  jpegSize (ustring* data, size_t& x, size_t& y) {
+    MemCursor  csr (data);
+    int  n;
+    uint32_t  marker, code;
+
+    csr.skip (2);
+#ifdef MSJFIFHACK
+    if (matchSkip (b, e, CharConst ("\xff\xfe"))) { // JPEG_COM
+       n = readWord (b, e);
+       b += n;
+    }
+#endif
+    while (! csr.empty ()) {
+       marker = csr.ui8 ();
+       code = csr.ui8 ();
+       while (code == 0xff) {
+           code = csr.ui8 ();
+       }
+       n = csr.ui16n ();
+       if (marker != 0xff || csr.empty ())
+           return false;
+       if (0xc0 <= code && code <= 0xc3) {
+           csr.ui8 ();
+           y = csr.ui16n ();
+           x = csr.ui16n ();
+           return true;
+       }
+       csr.skip (n - 2);
+    }
+}
+
+static bool  pngSize (ustring* data, size_t& x, size_t& y) {
+    MemCursor  csr (data);
+
+    csr.skip (12);
+    if (csr.matchSkip (CharConst ("IHDR"))) {
+//     if (csr.cap (8)) {
+       if (csr.size () >= 8) {
+           x = csr.ui32n ();
+           y = csr.ui32n ();
+           return true;
+       }
+    }
+    return false;
+}
+
+static bool  swfSize (ustring* data, size_t& x, size_t& y) {
+    MemCursor  csr (data);
+    int  n;
+    int  minx, maxx, miny, maxy;
+
+    csr.b += 8;
+    csr.initBit ();
+    n = csr.ub (5);
+    minx = csr.sb (n);
+    maxx = csr.sb (n);
+    miny = csr.sb (n);
+    maxy = csr.sb (n);
+    if (! csr.empty ()) {
+       x = (maxx - minx) / 20. + 0.5;
+       y = (maxy - miny) / 20. + 0.5;
+       return true;
+    } else {
+       return false;
+    }
+}
+
+static bool  imageSize (ustring* data, size_t& x, size_t& y, ustring& type) {
+    if (matchHead (*data, CharConst ("GIF87a"))) {
+       type.assign (CharConst ("gif"));
+       return gifSize (data, x, y);
+    } else if (matchHead (*data, CharConst ("GIF89a"))) {
+       type.assign (CharConst ("gif"));
+       return gifSize (data, x, y);
+    } else if (matchHead (*data, CharConst ("\xFF\xD8"))) {
+       type.assign (CharConst ("jpeg"));
+       return jpegSize (data, x, y);
+    } else if (matchHead (*data, CharConst ("\x89PNG\x0d\x0a\x1a\x0a"))) {
+       type.assign (CharConst ("png"));
+       return pngSize (data, x, y);
+#if 0
+    } else if (matchHead (*data, CharConst ("MM\x00\x2a"))) {
+       type.assign (CharConst ("tiff"));
+       return tiffSize (data, x, y);
+    } else if (matchHead (*data, CharConst ("II\x2a\x00"))) {
+       type.assign (CharConst ("tiff"));
+       return tiffSize (data, x, y);
+    } else if (matchHead (*data, CharConst ("BM"))) {
+       type.assign (CharConst ("bmp"));
+       return bmpSize (data, x, y);
+#endif
+    } else if (matchHead (*data, CharConst ("FWS"))) {
+       type.assign (CharConst ("swf"));
+       return swfSize (data, x, y);
+#if 0
+    } else if (matchHead (*data, CharConst ("CWS"))) {
+       type.assign (CharConst ("swf"));
+       return cswfSize (data, x, y);
+#endif
+    } else {
+       type = uEmpty;
+       return false;
+    }
+}
+
+/*DOC:
+===image-size===
+ (image-size FILENAME [#serial | #named | #static | :serial BOOL | :named BOOL | :static BOOL]) -> (WIDTH HEIGHT TYPE) or NIL
+
+TYPEは、gif, jpeg, png, swf。
+
+*/
+//#AFUNC       image-size      ml_image_size
+MNode*  ml_image_size (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    ustring  filename;
+    StoreType  storetype;
+    ustring  src;
+    std::vector<MNode*>  params;
+    std::vector<MNode*>  keywords;
+    static paramList  kwlist[] = {
+       {CharConst ("serial"), true},
+       {CharConst ("named"), true},
+       {CharConst ("static"), true},
+       {NULL, 0, 0}
+    };
+
+    setParams (arg, 1, &params, kwlist, &keywords, NULL);
+    filename = eval_str (params[0], mlenv);
+    if (keywords[0] && eval_bool (keywords[0], mlenv)) // serial
+       storetype.setSerial ();
+    if (keywords[1] && eval_bool (keywords[1], mlenv)) // named
+       storetype.setNamed ();
+    if (keywords[2] && eval_bool (keywords[2], mlenv)) // static
+       storetype.setStatic ();
+    src = storetype.src (mlenv, filename);
+
+    if (src.length () > 0) {
+       FileMacro  f;
+       ustring  data;
+       size_t  x, y;
+       ustring  type;
+
+       if (f.openRead (src.c_str ())) {
+           data.resize (32768);
+           data.resize (f.read ((char*)data.data (), 32768));
+           if (imageSize (&data, x, y, type)) {
+               MNodeList  ans;
+               ans.append (newMNode_num (x));
+               ans.append (newMNode_num (y));
+               ans.append (newMNode_str (new ustring (type)));
+               return ans.release ();
+           }
+       }
+    }
+    return NULL;
+}
diff --git a/modules/ml-imagesize.h b/modules/ml-imagesize.h
new file mode 100644 (file)
index 0000000..2f6bbc8
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef ML_IMAGESIZE_H
+#define ML_IMAGESIZE_H
+
+#include "ml.h"
+
+class  MNode;
+class  MlEnv;
+
+MNode*  ml_image_size (MNode* cell, MlEnv* mlenv);
+
+#endif /* ML_IMAGESIZE_H */