Browse Source

Added SetSubimage to copy contents of an image to a rect in another image, scaling if necessary. Exposed Image.SetSize to script

Matt Benic 9 years ago
parent
commit
225e74ab92

+ 2 - 1
Script/Packages/Atomic/Resource.json

@@ -4,7 +4,8 @@
 	"classes" : ["Resource", "ResourceCache", "XMLFile", "PListFile", "JSONFile", "Image"],
 	"overloads": {
 		"Image": {
-			"GetPixel": ["int", "int"]
+			"GetPixel": ["int", "int"],
+			"SetSize": ["int", "int", "int", "unsigned"]
 		}
 	}
 }

+ 58 - 0
Source/Atomic/Resource/Image.cpp

@@ -2094,6 +2094,64 @@ Image* Image::GetSubimage(const IntRect& rect) const
     }
 }
 
+bool Image::SetSubimage(const Image* image, const IntRect& rect) const
+{
+    if (!data_)
+        return false;
+
+    if (depth_ > 1 || IsCompressed())
+    {
+        LOGERROR("SetSubimage not supported for Compressed or 3D images");
+        return false;
+    }
+
+    if (rect.left_ < 0 || rect.top_ < 0 || rect.right_ > width_ || rect.bottom_ > height_ || !rect.Width() || !rect.Height())
+    {
+        LOGERROR("Can not set subimage in image " + GetName() + " with invalid region");
+        return false;
+    }
+
+    int width = rect.Width();
+    int height = rect.Height();
+    if (width == image->GetWidth() && height == image->GetHeight())
+    {
+        int components = Min((int)components_, (int)image->components_);
+
+        unsigned char* src = image->GetData();
+        unsigned char* dest = data_.Get() + (rect.top_ * width_ + rect.left_) * components_;
+        for (int i = 0; i < height; ++i)
+        {
+            memcpy(dest, src, width * components);
+                
+            src += width * image->components_;
+            dest += width_ * components_;
+        }
+    }
+    else
+    {
+        unsigned uintColor;
+        unsigned char* dest = data_.Get() + (rect.top_ * width_ + rect.left_) * components_;
+        unsigned char* src = (unsigned char*)&uintColor;
+        for (int y = 0; y < height; ++y)
+        {
+            for (int x = 0; x < width; ++x)
+            {
+                // Calculate float coordinates between 0 - 1 for resampling
+                float xF = (image->width_ > 1) ? (float)x / (float)(width - 1) : 0.0f;
+                float yF = (image->height_ > 1) ? (float)y / (float)(height - 1) : 0.0f;
+                uintColor = image->GetPixelBilinear(xF, yF).ToUInt();
+
+                memcpy(dest, src, components_);
+
+                dest += components_;
+            }
+            dest += (width_ - width) * components_;
+        }
+    }
+
+    return true;
+}
+
 SDL_Surface* Image::GetSDLSurface(const IntRect& rect) const
 {
     if (!data_)

+ 2 - 0
Source/Atomic/Resource/Image.h

@@ -198,6 +198,8 @@ public:
     CompressedLevel GetCompressedLevel(unsigned index) const;
     /// Return subimage from the image by the defined rect or null if failed. 3D images are not supported. You must free the subimage yourself.
     Image* GetSubimage(const IntRect& rect) const;
+    /// Copy contents of the image into the defined rect, scaling if necessary. This image should already be large enough to include the rect. Compressed and 3D images are not supported.
+    bool SetSubimage(const Image* image, const IntRect& rect) const;
     /// Return an SDL surface from the image, or null if failed. Only RGB images are supported. Specify rect to only return partial image. You must free the surface yourself.
     SDL_Surface* GetSDLSurface(const IntRect& rect = IntRect::ZERO) const;
     /// Precalculate the mip levels. Used by asynchronous texture loading.