java圖像處理干貨篇

java圖像處理干貨篇

繪制圖像

繪制圖像主要用到的是Graphics類中drawImage方法,當然Graphics2D中也有相應的方法

主要的用法:

  • public abstract boolean drawImage(Image img,x,y,ImageObserver observer):img是Image對象,x,y起始坐標,observer是觀察對象
  • drawImage(Image img,int x,int y,int width,int height,Imageobersver observer):widthheight是指定圖像的寬度和高度,主要的作用是放大和縮小圖像
  • drawImage(Image img,int dx1,int dy1,int dx2,int dx2,int sx1,int sy1,int sx2,int sy2,ImageObserver observer):主要用來翻轉圖形,通過互換源矩形的第一個和第二個角的x坐標可以實現水平翻轉,通過互換源矩形的第一個和第二個角的y坐標可以實現垂直翻轉

翻轉圖像

package com.zzk;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PartImageFrame extends JFrame {
    private Image img = null;  // 聲明圖像對象
    private PartImagePanel imagePanel = null;  // 聲明圖像面板對象
    private int dx1, dy1, dx2, dy2;   // 目標矩形第一個角與第二個角的X、Y坐標
    private int sx1, sy1, sx2, sy2;   // 源矩形第一個角與第二個角的X、Y坐標
    public static void main(String args[]) {
        PartImageFrame frame = new PartImageFrame();
        frame.setVisible(true);
    }
    public PartImageFrame() {
        super();
        URL imgUrl = PartImageFrame.class.getResource("/img/image.jpg");// 獲取圖片資源的路徑
        img = Toolkit.getDefaultToolkit().getImage(imgUrl); // 獲取圖像資源
        dx2 = sx2 = 340; // 初始化圖像大小
        dy2 = sy2 = 200; // 初始化圖像大小
        imagePanel = new PartImagePanel();  // 創建圖像面板對象
        this.setBounds(200, 160, 355, 276); // 設置窗體大小和位置
        this.add(imagePanel); // 在窗體中部位置添加圖像面板對象
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 設置窗體關閉模式
        this.setTitle("翻轉圖像"); // 設置窗體標題
        final JPanel panel = new JPanel();
        getContentPane().add(panel, BorderLayout.SOUTH);
        final JButton btn_h = new JButton();
        btn_h.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                // 下面3行代碼用于交換sx1和sx2的值
                int x = sx1;
                sx1 = sx2;
                sx2 = x;
                imagePanel.repaint();  // 重新調用面板類的paint()方法
            }
        });
        btn_h.setText("水平翻轉");
        panel.add(btn_h);
        final JButton btn_v = new JButton();
        btn_v.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                // 下面3行代碼用于交換sy1和sy2的值
                int y = sy1;
                sy1 = sy2;
                sy2 = y;
                imagePanel.repaint();// 重新調用面板類的paint()方法
            }
        });
        btn_v.setText("垂直翻轉");
        panel.add(btn_v);
    }
    // 創建面板類
    class PartImagePanel extends JPanel {
        public void paint(Graphics g) {
            g.clearRect(0, 0, this.getWidth(), this.getHeight());// 清除繪圖上下文的內容
            g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, this);// 繪制圖像

        }
    }
}

旋轉圖像

主要用到的是Graphics2D類中的rotate函數,定義如下:public abstract void rotate(double theta): theta是角度,以弧度為單位
代碼如下

package com.zzk;
import java.awt.*;
import java.net.URL;
import javax.swing.*;
public class RotateImageFrame extends JFrame {
    private Image img = null;
    private RotatePanel rotatePanel = null;
    public RotateImageFrame() {
        URL imgUrl = RotateImageFrame.class.getResource("/img/image.jpg");// 獲取圖片資源的路徑
        img = Toolkit.getDefaultToolkit().getImage(imgUrl);   // 獲取圖片資源
        rotatePanel = new RotatePanel();  // 創建旋轉圖像的面板對象
        this.setBounds(150, 120, 380, 310);                 // 設置窗體大小和位置
        add(rotatePanel);// 在窗體上放置圖像面板
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  // 設置窗體關閉模式
        this.setTitle("旋轉圖像");                     // 設置窗體標題
    }
    public static void main(String[] args) {
        new RotateImageFrame().setVisible(true);
    }
    class RotatePanel extends JPanel {
        public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;         // 獲得Graphics2D對象
            g2.drawImage(img, 80, 10, 260, 150, this);      // 繪制指定大小的圖片
            g2.rotate(Math.toRadians(10));                 // 將圖片旋轉10度
            g2.drawImage(img, 80, 10, 260, 150, this);      // 繪制指定大小的圖片
            g2.rotate(Math.toRadians(10));                // 將圖片旋轉10度
            g2.drawImage(img, 80, 10, 260, 150, this);      // 繪制指定大小的圖片
        }
    }
}

傾斜圖像

主要用到的是Graphics2D中的shear函數定義如:public abstract void shear(doubel shx,double shy):shx是在正x軸上移動坐標的乘數,它可以作為其縱坐標的值,shy是在正y軸方形移動坐標的乘數,它可以作為其x坐標的函數。
本人的理解:
傾斜畫布,如果shx>0就是向正方向平移,平移的長度為shx
height(圖形縱坐標的值,如果是矩形就是乘以矩形的高)
相同的對于shy是乘以矩形寬
*

package com.zzk;
import java.awt.*;
import java.net.URL;
import javax.swing.*;
public class ShearImageFrame extends JFrame {
    private Image img;
    private ShearImagePanel canvasPanel = null;
    public ShearImageFrame() {
        URL imgUrl = ShearImageFrame.class.getResource("/img/image.jpg");// 獲取圖片資源的路徑
        img = Toolkit.getDefaultToolkit().getImage(imgUrl);  // 獲取圖片資源
        canvasPanel = new ShearImagePanel();     // 創建繪制傾斜圖像的面板對象
        this.setBounds(100, 100, 360, 240);                // 設置窗體大小和位置
        add(canvasPanel);// 在窗體上添加面板對象
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 設置窗體關閉模式
        this.setTitle("傾斜圖像");                    // 設置窗體標題
    }
    public static void main(String[] args) {
        new ShearImageFrame().setVisible(true);
    }
    class ShearImagePanel extends JPanel {// 繪制傾斜圖像的面板類
        public void paint(Graphics g) {
            Graphics2D g2=(Graphics2D) g;// 獲得Graphics2D對象
            g2.shear(0, -0.5);// 傾斜圖像
            g2.drawImage(img, 10, 20, 220, 160, this);     // 繪制指定大小的圖片
        }
    }
}

裁剪圖片

public BufferedImage createScreenCapture(Rectangle screenRect):返回的是一個BufferedImage對象,參數是Rectangle對象,這個函數是Robot類中的,主要用于裁剪圖形

package com.zzk;
import java.awt.AWTException;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;

public class CutImageFrame extends JFrame {
    private Image img = null; // 聲明圖像對象
    private OldImagePanel oldImagePanel = null; // 聲明圖像面板對象
    private int pressPanelX = 0, pressPanelY = 0;// 鼠標按下點的X、Y坐標 
    private int pressX = 0, pressY = 0;// 鼠標按下點在屏幕上的X、Y坐標
    private int releaseX = 0, releaseY = 0;// 鼠標釋放點在屏幕上的X、Y坐標
    private Robot robot = null;  // 聲明Robot對象
    private BufferedImage buffImage = null; // 聲明緩沖圖像對象
    private CutImagePanel cutImagePanel = new CutImagePanel(); // 創建繪制裁剪結果的面板
    private boolean flag = false;  // 聲明標記變量,為true時顯示選擇區域的矩形,否則不顯示

    public static void main(String args[]) {
        CutImageFrame frame = new CutImageFrame();
        frame.setVisible(true);
    }

    public CutImageFrame() {
        super();
        URL imgUrl = CutImageFrame.class.getResource("/img/image.jpg");// 獲取圖片資源的路徑
        img = Toolkit.getDefaultToolkit().getImage(imgUrl); // 獲取圖像資源
        oldImagePanel = new OldImagePanel(); // 創建圖像面板對象
        this.setBounds(200, 160, 355, 276); // 設置窗體大小和位置
        final JSplitPane splitPane = new JSplitPane();
        splitPane.setDividerLocation((this.getWidth() / 2) - 10);
        getContentPane().add(splitPane, BorderLayout.CENTER);
        splitPane.setLeftComponent(oldImagePanel);
        splitPane.setRightComponent(cutImagePanel);
        oldImagePanel.addMouseListener(new MouseAdapter() {
            public void mousePressed(final MouseEvent e) {  // 鼠標鍵按下事件
                pressPanelX = e.getX(); // 獲得鼠標按下點的X坐標 
                pressPanelY = e.getY();// 獲得鼠標按下點的Y坐標 
                pressX = e.getXOnScreen() + 1;// 鼠標按下點在屏幕上的X坐標加1,即去除選擇線
                pressY = e.getYOnScreen() + 1;// 鼠標按下點在屏幕上的Y坐標加1,即去除選擇線
                flag = true;// 為標記變量賦值為true
            }

            public void mouseReleased(final MouseEvent e) { // 鼠標鍵釋放事件
                releaseX = e.getXOnScreen() - 1;// 鼠標釋放點在屏幕上的X坐標減1,即去除選擇線
                    releaseY = e.getYOnScreen() - 1;// 鼠標釋放點在屏幕上的Y坐標減1,即去除選擇線
                    try {
                    robot = new Robot();// 創建Robot對象
                    if (releaseX - pressX > 0 && releaseY - pressY > 0) {
                        Rectangle rect = new Rectangle(pressX, pressY, releaseX
                                - pressX, releaseY - pressY);// 創建Rectangle對象
                        buffImage = robot.createScreenCapture(rect);// 獲得緩沖圖像對象
                        cutImagePanel.repaint(); // 調用CutImagePanel面板的paint()方法
                    }
                } catch (AWTException e1) {
                    e1.printStackTrace();
                }
                flag = false;// 為標記變量賦值為false
            }
        });
        oldImagePanel.addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseDragged(final MouseEvent e) {// 鼠標拖動事件
                if (flag) {
                    releaseX = e.getXOnScreen();// 獲得鼠標釋放點在屏幕上的X坐標
                    releaseY = e.getYOnScreen();// 獲得鼠標釋放點在屏幕上的Y坐標
                    oldImagePanel.repaint();// 調用OldImagePanel面板的paint()方法
                }
            }
        });
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 設置窗體關閉模式
        this.setTitle("裁剪圖片"); // 設置窗體標題
    }




    class OldImagePanel extends JPanel {// 創建繪制原圖像的面板類

        public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            g2.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);// 繪制圖像
            g2.setColor(Color.WHITE);
            if (flag) {
                float[] arr = {5.0f}; // 創建虛線模式的數組
                BasicStroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
                        BasicStroke.JOIN_BEVEL, 1.0f, arr, 0); // 創建寬度是1的平頭虛線筆畫對象
                g2.setStroke(stroke);// 設置筆畫對象
                g2.drawRect(pressPanelX, pressPanelY, releaseX - pressX,
                        releaseY - pressY);// 繪制矩形選區
            }
        }
    }

    class CutImagePanel extends JPanel {// 創建繪制裁剪結果的面板類

        public void paint(Graphics g) {
            g.clearRect(0, 0, this.getWidth(), this.getHeight());// 清除繪圖上下文的內容
            g.drawImage(buffImage, 0, 0, releaseX - pressX, releaseY - pressY,
                    this);// 繪制圖像
        }




    }
}

調整圖片的亮度

RescaleOp類中的filter方法原緩沖圖像進行重縮放,定義如下
public abstract BufferedImage filter(BufferedImage src,BufferedImage dst):src是要過濾的源對象,dst是目標對象,或則為null

package com.zzk;

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImageBrightenFrame extends JFrame {
    private BufferedImage image;// 用于調整亮度的緩沖圖像對象
    private BufferedImage oldImage;// 用于存放調整亮度之前的原緩沖圖像對象
    private ImageBrightenPanel imageBrightenPanel = new ImageBrightenPanel();
    
    public static void main(String args[]) {
        ImageBrightenFrame frame = new ImageBrightenFrame();
        frame.setVisible(true);
    }
    
    public ImageBrightenFrame() {
        super();
        setBounds(100, 100, 357, 276);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("調整圖片的亮度");
        Image img = null;
        try {
            img = ImageIO.read(new File("src/img/image.jpg"));  // 創建圖像對象
        } catch (IOException e) {
            e.printStackTrace();
        }
        image = new BufferedImage(img.getWidth(this), img.getHeight(this),
        BufferedImage.TYPE_INT_RGB);// 創建緩沖圖像對象
        image.getGraphics().drawImage(img, 0, 0, null);// 在緩沖圖像對象上繪制圖像
        oldImage = image;// 存儲原來的圖像對象,用于以后的恢復操作
        getContentPane().add(imageBrightenPanel, BorderLayout.CENTER);
        
        final JPanel panel = new JPanel();
        getContentPane().add(panel, BorderLayout.SOUTH);

        final JButton button = new JButton();
        button.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                float a = 1.0f;// 定義縮放因子
                float b = 5.0f;// 定義偏移量
                RescaleOp op = new RescaleOp(a,b,null);// 創建具有指定縮放因子和偏移量的 RescaleOp對象
                image = op.filter(image, null);// 對源圖像中的數據進行逐像素重縮放,達到變亮的效果
                repaint();// 重新繪制圖像
            }
        });
        button.setText("變    亮");
        panel.add(button);

        final JButton button_3 = new JButton();
        button_3.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                float a = 1.0f;// 定義縮放因子
                float b = -5.0f;// 定義偏移量
                RescaleOp op = new RescaleOp(a,b,null);// 創建具有指定縮放因子和偏移量的 RescaleOp對象
                image = op.filter(image, null);// 對源圖像中的數據進行逐像素重縮放,達到變暗的效果
                repaint();// 重新繪制圖像
            }
        });
        button_3.setText("變    暗");
        panel.add(button_3);

        final JButton button_2 = new JButton();
        button_2.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                image = oldImage;  // 獲得變亮前的圖像
                imageBrightenPanel.repaint();// 重新繪制原圖像,即恢復為變亮前的圖像
            }
        });
        button_2.setText("恢    復");
        panel.add(button_2);

        final JButton button_1 = new JButton();
        button_1.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                System.exit(0);
            }
        });
        button_1.setText("退    出");
        panel.add(button_1);
  }
    
    class ImageBrightenPanel extends JPanel {
        public void paint(Graphics g) {
            if (image != null) {
                g.drawImage(image, 0, 0, null);  // 將緩沖圖像對象繪制到面板上
            }
        }
    }
}

補充說明:這里的RescaleOp類可以調整色數,其原理是每一個樣本值乘以一個縮放因子然后加上偏移量就是縮放的數,如果要變亮的話就將偏移量為正,反之為負,這里將縮放因子設置為1.0f是因為不想那么快速的變亮,如果你設置的大一點,就會很快變得很亮,反之亦然

轉換彩色圖片為灰色圖片

主要使用ColorConvertOp類,其構造函數如下
public ColorConvertOp(ColorSpace src,ColorSpace dst,RenderingHints hints):src是原顏色空間對象,dst是目標顏色空間對象,hints是用于控制顏色轉換的RenderingHints對象,可以為null
使用ColorConvertOp類中的filter方法將彩色圖像轉換成灰色圖像,定義如下:
public final BufferedImage filter(BufferedImage src,BufferedImage dst):scr要過濾的對象,dst目標空間對象

package com.zzk;

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.color.ColorSpace;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MultiColorToGrayFrame extends JFrame {
    private BufferedImage image;
    private ColorToGrayPanel colorToGrayPanel = new ColorToGrayPanel();
    
    public static void main(String args[]) {
        MultiColorToGrayFrame frame = new MultiColorToGrayFrame();
        frame.setVisible(true);
    }
    
    public MultiColorToGrayFrame() {
        super();
        setBounds(100, 100, 357, 276);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("彩色圖像轉換為灰度");
        Image img = null;
        try {
            img = ImageIO.read(new File("src/img/image.jpg"));  // 創建圖像對象
        } catch (IOException e) {
            e.printStackTrace();
        }
        image = new BufferedImage(img.getWidth(this), img.getHeight(this),
                BufferedImage.TYPE_INT_RGB);// 創建緩沖圖像對象
        image.getGraphics().drawImage(img, 0, 0, null);// 在緩沖圖像對象上繪制圖像
        
        getContentPane().add(colorToGrayPanel, BorderLayout.CENTER);
        
        final JPanel panel = new JPanel();
        getContentPane().add(panel, BorderLayout.SOUTH);
        
        final JButton button = new JButton();
        button.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                ColorSpace colorSpace1 = ColorSpace.getInstance(ColorSpace.CS_GRAY);// 創建內置線性為灰度的顏色空間
                ColorSpace colorSpace2 = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);// 創建內置線性為 RGB的顏色空間
                ColorConvertOp op = new ColorConvertOp(colorSpace1,colorSpace2,
                        null);// 創建進行顏色轉換的對象
                image = op.filter(image, null);// 對緩沖圖像進行顏色轉換
            repaint();// 重新繪制圖像
        }
        });
        button.setText("轉換為灰度");
        panel.add(button);

        final JButton button_1 = new JButton();
        button_1.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                System.exit(0);
            }
        });
        button_1.setText("退    出");
        panel.add(button_1);
    }
    
    class ColorToGrayPanel extends JPanel {
        public void paint(Graphics g) {
            if (image != null) {
                g.drawImage(image, 0, 0, null);  // 將緩沖圖像對象繪制到面板上
            }
        }
    }
}

補充說明:這里的image.getGraphics().drawImage(img, 0, 0, null)是必須有的,這是繪制對緩沖圖像的繪制

總結:

從文件中讀取圖像的方法

  • URL imgUrl = CutImageFrame.class.getResource("/img/image.jpg");//得到的是URL
    img = Toolkit.getDefaultToolkit().getImage(imgUrl); //得到的是Image對象,同樣的想要得到BufferedImage對象可以進行轉 化
  • Image img=ImageIo(new File("path"));這里得到的是Image對象,如果想要得到BufferedImage對象,可以用BufferedImage的構造方法BufferedImage(int width,int height,)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容