c++ 坐标变化(像素 1920 x 1080 到 640 x 480)

Ric*_*arg 1 c++ 2d c++11

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?

seh*_*ehe 5

Wokay, since people urged me, let me explain the most important style improvements here:

  • Naming: don't start names with underscores: It's illegal and the program invokes undefined behaviour
  • struct tags: they're a thing of C, and obsolete in C++ ever since C++98
  • Single Responsibility Principle - don't make the transform function print things
  • Make the Pixel struct capable of printing itself (using operator<< 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

Live On Coliru

#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)