I am developing a small program that can draw a rectangle in different videos modes (for example 1920 x 1080 -> 640 x 480). I can resize a rectangle. But I am getting stuck, because I cannot find a clear method to achieve the problem. I am currently trying to create a matrix to perform a scale operation over the pixels but I cannot get the right answer. Part of the problem seems to be that TransformMatrix::transform is not scaling correctly.
#include <iostream>
typedef struct _Pixel
{
_Pixel():X(1920)
,Y(1080)
{}
unsigned X;
unsigned Y;
}Pixel;
typedef struct TransformMatrix
{
constexpr TransformMatrix(const float aWeigth = 0.3f
,const float aHeigth = 0.225f):W(aWeigth)
,H(aHeigth)
{}
void transform( const Pixel & aPixel)
{
auto x_value=static_cast<float>(aPixel.X)*W;
auto y_value=static_cast<float>(aPixel.Y)*H;
std::cout<<"x_value: "<<x_value<<std::endl;
std::cout<<"y_value: "<<y_value<<std::endl;
}
const float W;
const float H;
}TransformMatrix;
int main()
{
Pixel aPixel;
TransformMatrix _TransformMatrix;
_TransformMatrix.transform(aPixel);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
The actual result:
x_value: 576
y_value: 243
The expected result:
x_value: 640
y_value: 480
How can I perform the right operation? Is it just a change of basis? Should I scale only or also do a transformation operation?
Wokay, since people urged me, let me explain the most important style improvements here:
C, and obsolete in C++ ever since C++98operator<< for iostreams)Pure Functions: make transform return a modified value, instead of mutating the argument. In general this makes code a lot safer, and it can enable a class of optimizations. In the rare case where you wanted to update the pixel in-place you'd simply write
pixel = transform(pixel); // the optimizer will see right through this
Run Code Online (Sandbox Code Playgroud)Make TransformMatrix a calleable object (by implementing transform as operator() instead. This way, you can simply use it as a function, e.g. in an algorithm:
std::vector<Pixel> poly1, poly2;
std::transform(poly1.begin(), poly1.end(),
back_inserter(poly2), TransformMatrix());
Run Code Online (Sandbox Code Playgroud)
Which simply transforms all pixels in poly1 to poly2.
Exercise for the reader: name TransformMatrix so it does what it says. Right now, it's more like ScalePixel
#include <iostream>
struct Pixel {
Pixel(unsigned x = 1920, unsigned y = 1080) : X(x), Y(y) {}
unsigned X;
unsigned Y;
friend std::ostream& operator<<(std::ostream& os, Pixel const& p) {
return os << "Pixel(" << p.X << ", " << p.Y << ")";
}
};
struct TransformMatrix {
constexpr TransformMatrix(float aWidth = 640/1920.f, float aHeigth = 480/1080.f) : W(aWidth), H(aHeigth) {}
Pixel operator()(const Pixel &aPixel) const {
return { static_cast<unsigned>(aPixel.X * W), static_cast<unsigned>(aPixel.Y * H) };
}
float W;
float H;
};
int main() {
Pixel aPixel;
TransformMatrix xfrm;
std::cout << aPixel << " -> " << xfrm(aPixel) << "\n";
}
Run Code Online (Sandbox Code Playgroud)
Prints:
Pixel(1920, 1080) -> Pixel(640, 480)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
496 次 |
| 最近记录: |