簡潔高效的代碼實現同樣紧要,亮度變化、灰度圖、對比度、高斯模糊

源碼下載:http://yunpan.cn/c3iNuHFFAcr8h  访问密码
8e48

作者:Mikeva链接:https://zhuanlan.zhihu.com/p/26762012来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

自己觉着那道题的焦点应该是模拟,不过借使说他是二维链表的話也不為過。這道題的主體思路就是把原來旋轉點的O(n^2)變成了旋轉邊界的O(n)。怎麼旋轉邊界呢,就恍如是把原來的那一个點都於上下左右四個點連線,形成一個大網,我們要做的就是把要旋轉的正方形的周围的線都剪斷,然後轉一下再練上,實現的話就是二維點化一維點,所有的點自由化,然後每便找正方形從一個邊界點開始走進去走出來他的邊界,這裡只要注意記錄真實方向即可(只要能即時獲得即可)。

還是先來看下截圖:

一、目的

這篇就是要教我们怎么样實作出水平的TableView。

就如下圖上边那一塊,可以當作第二層的Tab Bar 使用。

图片 1

iOS預定地TableView是笔直滑動的成效,也就是由上往下看的動線。

唯独當后天我們的UI需要是一個档次的呈現,很直覺的會想到用UICollectionView去實作,

但其實用UITableView來改造,我個人覺得尤其不难,多一個實作選項也未嘗倒霉。

思路尽管首要,簡潔高效的代碼實現同樣主要,代碼實現同樣须要注入思考。

图片 2

二、原理

原理其實很簡單,就是靠旋轉。

若果圖片的规律看得懂的話,就足以平昔跳過這邊,到下一段落看Code的實作。

图片 3

其實1.2.3步驟交換是沒有問題的。

#pragma GCC optimize("O3")
#include <cstdio>
#define shang(a) (p[(a)].t[p[(a)].f])
#define xia(a) (p[(a)].t[(p[(a)].f+2)%4])
#define zuo(a) (p[(a)].t[(p[(a)].f+1)%4])
#define you(a) (p[(a)].t[(p[(a)].f+3)%4])
inline void read(int &sum){
  register char ch=getchar();
  for(sum=0;ch<'0'||ch>'9';ch=getchar());
  for(;ch>='0'&&ch<='9';sum=(sum<<1)+(sum<<3)+ch-'0',ch=getchar());
}
const int N=2010;
struct Point{
  int t[4],f,v;
}p[N*N];
int hash[N][N],sz;
int n,m,q,tb[N],pg[N],zs[N],ys[N];
inline int toward(int x,int y){
  for(int i=0;i<4;++i)
    if(p[x].t[i]==y)
      return i;
}
inline void get_fs(int x,int y){
  int j=toward(y,x);
  if(j==2)p[y].f=0;
  else if(j==0)p[y].f=2;
  else if(j==1)p[y].f=3;
  else p[y].f=1;
}
inline void get_fx(int x,int y){
  int j=toward(y,x);
  if(j==0)p[y].f=0;
  else if(j==2)p[y].f=2;
  else if(j==1)p[y].f=1;
  else p[y].f=3;
}
inline void get_fz(int x,int y){
  int j=toward(y,x);
  if(j==0)p[y].f=1;
  else if(j==2)p[y].f=3;
  else if(j==1)p[y].f=2;
  else p[y].f=0;
}
inline void get_fy(int x,int y){
  int j=toward(y,x);
  if(j==0)p[y].f=3;
  else if(j==2)p[y].f=1;
  else if(j==1)p[y].f=0;
  else p[y].f=2;
}
inline void print(){
  for(int i=1,now;i<=n;++i){
    now=hash[i][0];
    for(int j=1;j<=m;++j)
      get_fy(now,you(now)),now=you(now),printf("%d ",p[now].v);
    puts("");
  }
}
inline void read_pre(){
  read(n),read(m),read(q);
  for(int i=0;i<=n+1;++i)
    for(int j=0;j<=m+1;++j)
      hash[i][j]=++sz;
  for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j)
      read(p[hash[i][j]].v),
      p[hash[i][j]].t[0]=hash[i-1][j],
      p[hash[i][j]].t[2]=hash[i+1][j],
      p[hash[i][j]].t[1]=hash[i][j-1],
      p[hash[i][j]].t[3]=hash[i][j+1];
  for(int i=1;i<=n;++i)
    p[hash[i][0]].t[0]=hash[i-1][0],
    p[hash[i][0]].t[2]=hash[i+1][0],
    p[hash[i][0]].t[3]=hash[i][1],
    p[hash[i][m+1]].t[0]=hash[i-1][m+1],
    p[hash[i][m+1]].t[2]=hash[i+1][m+1],
    p[hash[i][m+1]].t[1]=hash[i][m];
  for(int i=1;i<=m;++i)
    p[hash[0][i]].t[1]=hash[0][i-1],
    p[hash[0][i]].t[3]=hash[0][i+1],
    p[hash[0][i]].t[2]=hash[1][i],
    p[hash[n+1][i]].t[1]=hash[n+1][i-1],
    p[hash[n+1][i]].t[3]=hash[n+1][i+1],
    p[hash[n+1][i]].t[0]=hash[n][i];
  p[hash[0][0]].t[3]=hash[0][1],
  p[hash[0][0]].t[2]=hash[1][0],
  p[hash[0][m+1]].t[1]=hash[0][m],
  p[hash[0][m+1]].t[2]=hash[1][m+1],
  p[hash[n+1][0]].t[0]=hash[n][0],
  p[hash[n+1][0]].t[3]=hash[n+1][1],
  p[hash[n+1][m+1]].t[0]=hash[n][m+1],
  p[hash[n+1][m+1]].t[1]=hash[n+1][m];
}
inline void work(){
  int x,y,l,now;
  while(q--){
    read(x),read(y),read(l);
    if(l==1)continue;
    int now=hash[x][0];
    for(int i=1;i<=y;++i)
      get_fy(now,you(now)),now=you(now);
    zs[1]=now;
    for(int i=2;i<=l;++i)
      get_fx(now,xia(now)),now=xia(now),zs[i]=now;
    for(int j=2;j<l;++j)
      get_fy(now,you(now)),now=you(now),pg[j]=now;
    get_fy(now,you(now)),now=you(now),ys[1]=now;
    for(int i=2;i<=l;++i)
      get_fs(now,shang(now)),now=shang(now),ys[i]=now;
    for(int j=2;j<l;++j)
      get_fz(now,zuo(now)),now=zuo(now),tb[j]=now;
    for(int i=2;i<l;++i)
      get_fs(tb[i],shang(tb[i])),xia(shang(tb[i]))=zs[i],
      get_fy(ys[i],you(ys[i])),zuo(you(ys[i]))=tb[i],
      get_fx(pg[i],xia(pg[i])),shang(xia(pg[i]))=ys[i],
      get_fz(zs[i],zuo(zs[i])),you(zuo(zs[i]))=pg[i];
    for(int i=2,temp;i<l;++i)
      temp=zuo(zs[i]),
      zuo(zs[i])=shang(tb[i]),
      shang(tb[i])=you(ys[i]),
      you(ys[i])=xia(pg[i]),
      xia(pg[i])=temp;
    get_fz(zs[1],zuo(zs[1])),you(zuo(zs[1]))=zs[l],
    get_fs(zs[1],shang(zs[1])),xia(shang(zs[1]))=zs[l],
    get_fy(ys[l],you(ys[l])),zuo(you(ys[l]))=zs[1],
    get_fs(ys[l],shang(ys[l])),xia(shang(ys[l]))=zs[1],
    get_fy(ys[1],you(ys[1])),zuo(you(ys[1]))=ys[l],
    get_fx(ys[1],xia(ys[1])),shang(xia(ys[1]))=ys[l],
    get_fz(zs[l],zuo(zs[l])),you(zuo(zs[l]))=ys[1],
    get_fx(zs[l],xia(zs[l])),shang(xia(zs[l]))=ys[1];
    int temp=shang(zs[1]);
    shang(zs[1])=you(ys[l]),
    you(ys[l])=xia(ys[1]),
    xia(ys[1])=zuo(zs[l]),
    zuo(zs[l])=temp;
    temp=zuo(zs[1]),
    zuo(zs[1])=shang(ys[l]),
    shang(ys[l])=you(ys[1]),
    you(ys[1])=xia(zs[l]),
    xia(zs[l])=temp;
  }
}
int main(){
  read_pre(),work(),print();
  return 0;
}

 

1. 旋轉 270度 or – PI/2

先是步就是旋轉,270度也就是-PI/2照旧3PI/2都是一樣的。但是會發現,他的旋轉是依據主题點做旋轉。

 

實現了幾個效果:放大、縮小、旋轉、左右翻轉、上下翻轉,亮度變化、灰度圖、對比度、高斯模糊。

2. 移動到要的职位

接著就是要移動。依據跟原來的Table距離來看,

我們须要往左(+x方向)半個Table的長度然後往右半個Table的寬度(-x方向)

同理,我們還需求向上半個(-y方向)半個Table的長度然後往下半個Table的寬度(+y方向)

 

3. 旋轉Cell

最後別忘了Cell因為被旋轉了,所以我們得把她轉回來,才能讓使用者看到正確的顯示。剛剛轉了-PI/2,現在我們讓他轉PI/2來矯正方向。

放手、縮小代碼:

三、程式碼實現(斯维夫特)

說這麼多,直接來上Code最明亮。

private void scale(float x)
{
    scale_ *= x;
    using (var ds = board_.CreateDrawingSession())
    {
        ds.Transform = Matrix3x2.CreateScale(scale_);
        ds.Clear(Colors.Black);
        ds.DrawImage(oriImage_);
    }

    transform.Invalidate();
}

private void zoomIn_Click(object sender, RoutedEventArgs e)
{
    scale(1.1f);
}

private void zoomOut_Click(object sender, RoutedEventArgs e)
{
    scale(1 / 1.1f);
}

1. 旋轉 270度 or – PI/2 (UITableView)

self.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi/2))

 

2. 移動到要的岗位 (UITableView)

這邊要专注的是,因為我們做了旋轉,所以顯示下边的長寬跟實際的長寬是顛倒的。

let xOrigin = (frame.size.width – frame.size.height) / 2.0;

let yOrigin = (frame.size.height – frame.size.width) / 2.0;

self.frame = CGRect(x: xOrigin, y: yOrigin, width: frame.size.height,
height: frame.size.width);

旋轉代碼(注意,默認轉動方向是鐘錶方向——順時針):

3. 旋轉Cell (UITableViewCell)

self.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi/2)

完整程式碼連結

private void rotate_Click(object sender, RoutedEventArgs e)
{
    rotate_radians_ += 90;
    using (var ds = board_.CreateDrawingSession())
    {
        ds.Transform = Matrix3x2.CreateRotation(rotate_radians_ * (float)Math.PI / 180, new Vector2((float)oriImageRc_.Width / 2.0f, (float)oriImageRc_.Height / 2.0f));
        ds.Clear(Colors.Black);
        ds.DrawImage(oriImage_);
    }

    transform.Invalidate();
}

四、小結

有沒有覺得其實很簡單,不要求去處理UICollection的layout也是不錯的啊!

 

左右、上下翻轉代碼:

private void left_right_Click(object sender, RoutedEventArgs e)
{
    left_right_direction_ = -left_right_direction_;

    using (var ds = board_.CreateDrawingSession())
    {
        ds.Transform = Matrix3x2.CreateScale(new Vector2(left_right_direction_, top_bottom_direction_), new Vector2((float)oriImageRc_.Width / 2.0f, (float)oriImageRc_.Height / 2.0f));
        ds.Clear(Colors.Black);
        ds.DrawImage(oriImage_);
    }

    transform.Invalidate();
}

private void top_bottom_Click(object sender, RoutedEventArgs e)
{
    top_bottom_direction_ = -top_bottom_direction_;

    using (var ds = board_.CreateDrawingSession())
    {
        ds.Transform = Matrix3x2.CreateScale(new Vector2(left_right_direction_, top_bottom_direction_), new Vector2((float)oriImageRc_.Width / 2.0f, (float)oriImageRc_.Height / 2.0f));
        ds.Clear(Colors.Black);
        ds.DrawImage(oriImage_);
    }

    transform.Invalidate();
}

 

亮度、灰度、對比度、高斯,均选用Effect效果,其职能放在名字空間:

Microsoft.Graphics.Canvas.Effects

具體代碼:

亮度,注意,我利用了惠特ePoint,還有布莱克(Black)Point,請讀者自己試驗效果。而且亮度的範圍為:[0-1),注意閉包關係。

private void lightSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
        {
            if (board_ == null) return;

            using (var ds = board_.CreateDrawingSession())
            {
                Microsoft.Graphics.Canvas.Effects.BrightnessEffect brightness = new Microsoft.Graphics.Canvas.Effects.BrightnessEffect();
                if (e.NewValue >= 0.000001)
                {
                    brightness.WhitePoint = new Vector2(0, (float)e.NewValue);
                }
                else
                {
                    brightness.WhitePoint = new Vector2(-(float)e.NewValue, 0);
                }

                brightness.Source = oriImage_;

                ds.Clear(Colors.Black);
                ds.DrawImage(brightness);
            }

            transform.Invalidate();
        }

 

灰度:

        private void gray_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Graphics.Canvas.Effects.GrayscaleEffect grayEffect = new Microsoft.Graphics.Canvas.Effects.GrayscaleEffect();
            grayEffect.Source = oriImage_;

            using (var ds = board_.CreateDrawingSession())
            {
                ds.Clear(Colors.Black);
                ds.DrawImage(grayEffect);
            }
            transform.Invalidate();
        }

 

對比度:

        private void constrastSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
        {
            if (board_ == null) return;

            Microsoft.Graphics.Canvas.Effects.ContrastEffect constrastEffect = new Microsoft.Graphics.Canvas.Effects.ContrastEffect();
            constrastEffect.Contrast = (float)e.NewValue;
            constrastEffect.Source = oriImage_;

            using (var ds = board_.CreateDrawingSession())
            {
                ds.Clear(Colors.Black);
                ds.DrawImage(constrastEffect);
            }
            transform.Invalidate();
        }

 

高斯:

private void gaussianSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
        {
            if (board_ == null) return;

            Microsoft.Graphics.Canvas.Effects.GaussianBlurEffect gaussianEffect = new Microsoft.Graphics.Canvas.Effects.GaussianBlurEffect();
            gaussianEffect.BlurAmount = (float)e.NewValue;
            gaussianEffect.Source = oriImage_;

            using (var ds = board_.CreateDrawingSession())
            {
                ds.Clear(Colors.Black);
                ds.DrawImage(gaussianEffect);
            }
            transform.Invalidate();
        }

 

相关文章