2009年10月26日 星期一

圖像縮放


底下 code 僅用以呈現初始算法概念,由於 GetPixel、SetPixel 速度極慢,
實際上處理時會 LockBits 直接修改 raw pixels。
#pragma comment (lib, "gdiplus.lib")
#include <windows.h>
#include <stdio.h>
#include <gdiplus.h>
#define ex_by_daviddr 97

extern "C" WINBASEAPI HWND WINAPI GetConsoleWindow();
using namespace Gdiplus;
typedef unsigned char Byte;
typedef int PixelType;

void setSize (int w=1000, int h=800)
{
    HANDLE     hOut = GetStdHandle (STD_OUTPUT_HANDLE);
    SMALL_RECT rc   = {0, 0, w/8 ,h/16};
    COORD      size = {w/8+1 ,h/16+1};
    SetConsoleScreenBufferSize (hOut, size);
    SetConsoleWindowInfo (hOut, 1,&rc);
}
struct GDIp 
{
    GdiplusStartupInput in;
    ULONG_PTR tok;
    GDIp() {GdiplusStartup (&tok, &in, 0);}
   ~GDIp() {GdiplusShutdown (tok);}
} GDIp;

template <typename T, PixelFormat fmt> 
void scale ( Bitmap& const in, Bitmap& out, float sx, float sy)
{
    Color c1, c2, c3, c4;
    int   x, y, r,g,b, 
          iw = in.GetWidth(),  w = iw*sx, 
          ih = in.GetHeight(), h = ih*sy;
    float dx = float(iw)/w, 
          dy = float(ih)/h, 
          ix, iy, s,t, p1,p2,p3,p4;

    for (y=0; y<h; ++y)
        for (x=0; x<w; ++x) {
            ix = dx*x; s = ix - int(ix);
            iy = dy*y; t = iy - int(iy);
            in.GetPixel (ix,  iy,  &c1);  p1 = (1-s)*(1-t); 
            in.GetPixel (ix,  iy+1,&c2);  p2 = (1-s)*t; 
            in.GetPixel (ix+1,iy,  &c3);  p3 = s*(1-t); 
            in.GetPixel (ix+1,iy+1,&c4);  p4 = s*t;
            r = c1.GetR()*p1+ c2.GetR()*p2+ c3.GetR()*p3+ c4.GetR()*p4;
            g = c1.GetG()*p1+ c2.GetG()*p2+ c3.GetG()*p3+ c4.GetG()*p4;
            b = c1.GetB()*p1+ c2.GetB()*p2+ c3.GetB()*p3+ c4.GetB()*p4;
            out.SetPixel (x,y, Color(r,g,b));    
        }
}
int main()
{
    setSize();
    Graphics gp (GetDC (GetConsoleWindow()));
    gp.SetInterpolationMode (InterpolationModeHighQualityBicubic);
    Bitmap in (L"d:/img.jpg");
    Bitmap out (800, 600);             //畫布
    scale <PixelType, PixelFormat32bppRGB> (in, out, 1.0/2, 2);
    gp.DrawImage (&in, 0,0); 
    gp.DrawImage (&out, in.GetWidth(), 0); 
    return getchar();     
}

沒有留言:

張貼留言