Commits

Lars Viklund  committed 8a673a3

Expose MAXRECTS-BSSF-BNF packing method

  • Participants
  • Parent commits b77c1bc

Comments (0)

Files changed (2)

File Katla/CMakeLists.txt

 cmake_minimum_required(VERSION 2.8)
 
-include_directories(src ${KATLA_SOURCE_DIR}/Jansson/src ${KATLA_SOURCE_DIR}/STBImage/src)
+include_directories(src
+	${KATLA_SOURCE_DIR}/Jansson/src
+	${KATLA_SOURCE_DIR}/STBImage/src
+	${KATLA_SOURCE_DIR}/CLB/src
+	)
+
 add_executable(katlayout src/layout.cc)
 target_link_libraries(katlayout Jansson STBImage CLBRectBinPack)
 

File Katla/src/layout.cc

 
 #include <stb_image.h>
 #include <jansson.h>
+#include <MaxRectsBinPack.h>
 
 #include <glob.h>
 
 
 std::ostream& operator << (std::ostream& os, AlgorithmInput const& input);
 
+AlgorithmOutput MAXRECTS_BSSF_BNF(AlgorithmInput input);
+
 AlgorithmOutput Homogeneous(AlgorithmInput input);
 void WriteOutput(std::ostream& os, AlgorithmOutput const& out);
 void ComputeHomogeneousPages(bool needPoT, int tileCount, int tileW, int tileH, int maxW, int maxH, std::vector<Page>& dims);
         char const* val = json_string_value(algorithm);
         if (! strcmp(val, "homogeneous"))
             input.algorithm = val;
+        else if (! strcmp(val, "clb-maxrects-bssf-bnf"))
+            input.algorithm = val;
         else
             missing.push_back("algorithm");
     }
     AlgorithmOutput output;
     if (input.algorithm == "homogeneous")
         output = Homogeneous(input);
+    else if (input.algorithm == "clb-maxrects-bssf-bnf")
+        output = MAXRECTS_BSSF_BNF(input);
     else
     {
         return 3;
     }
 };
 
+std::string BuildTilemapPath(std::string const& basename, int ch, int p)
+{
+    char buf[100] = {};
+    sprintf(buf, "-%dch-%d", ch, (int)p+1);
+    return basename + buf + ".png";
+}
+
+std::string BuildHomogeneousTilemapPath(std::string const& basename, int w, int h, int ch, int p)
+{
+    char buf[100] = {};
+    sprintf(buf, "-%dx%d-%dch-%d", w, h, ch, (int)p+1);
+    return basename + buf + ".png";
+}
+
 AlgorithmOutput Homogeneous(AlgorithmInput input)
 {
     AlgorithmOutput output;
          I != groups.end();
          ++I)
     {
-        char buf[100] = {};
         int w = I->first.width, h = I->first.height;
         int ch = I->first.channels;
         int tileCount = I->second.size();
         {
             TilemapDesc desc;
             Page const& page = dims[p];
-            sprintf(buf, "-%dx%d-%dch-%d", w, h, ch, (int)p+1);
-            desc.filename = input.tilemapBasename + buf + ".png";
+            desc.filename = BuildHomogeneousTilemapPath(input.tilemapBasename, w, h, ch, p);
             desc.width = page.xCount * w;
             desc.height = page.yCount * h;
 
     dims.push_back(page);
 }
 
+
+struct 
+DecreasingWidthDecreasingHeight
+{
+    bool operator () (ImageInfo const& a, ImageInfo const& b) const
+    {
+        if (a.width != b.width) return a.width > b.width;
+        if (a.height != b.height) return a.height > b.height;
+        if (a.channels != b.channels) return a.channels < b.channels;
+        return a.filename < b.filename;
+    }
+};
+
+AlgorithmOutput MAXRECTS_BSSF_BNF(AlgorithmInput input)
+{
+    AlgorithmOutput output;
+
+    typedef std::set<ImageInfo, DecreasingWidthDecreasingHeight> Group;
+    typedef std::map<int, Group> GroupsByChannel;
+    GroupsByChannel channelGroups;
+    for (std::vector<ImageInfo>::const_iterator I = input.imageInfos.begin();
+         I != input.imageInfos.end();
+         ++I)
+    {
+        channelGroups[I->channels].insert(*I);
+    }
+
+    for (GroupsByChannel::const_iterator I = channelGroups.begin();
+         I != channelGroups.end();
+         ++I)
+    {
+        int ch = I->first;
+        Group const& group = I->second;
+        int w = input.maxDimension, h = input.maxDimension;
+        int serial = 0;
+        TilemapDesc desc = {};
+        desc.filename = BuildTilemapPath(input.tilemapBasename, ch, serial++);
+        desc.width = w;
+        desc.height = h;
+        desc.channels = ch;
+
+        MaxRectsBinPack packer(input.maxDimension, input.maxDimension);
+        for (Group::const_iterator J = group.begin();
+             J != group.end();
+             /* missing increment intentional*/)
+        {
+            Rect r = packer.Insert(J->width, J->height, MaxRectsBinPack::RectBestShortSideFit);
+            if (r.height == J->height)
+            {
+                desc.images.push_back(*J);
+                TileInfo tile = { r.x, r.y };
+                desc.tiles.push_back(tile);
+                ++J;
+            }
+            else
+            {
+                output.tilemaps.push_back(desc);
+                desc.filename = BuildTilemapPath(input.tilemapBasename, ch, serial++);
+                desc.images.clear();
+                desc.tiles.clear();
+                packer.Init(input.maxDimension, input.maxDimension);
+            }
+        }
+        if (packer.Occupancy())
+        {
+            output.tilemaps.push_back(desc);
+        }
+    }
+    return output;
+}
+
 void Usage()
 {
     std::cerr << "Input file format - JSON object with the following fields:\n"