Bitmap優(yōu)化

網(wǎng)絡(luò)的優(yōu)化

1.請求的緩存冈在。
Http請求是可以做緩存的空闲。

三級緩存
內(nèi)存緩存卿操、外部緩存
算法LruCache
+自定的 一周過期等等叔汁。
Sqlite緩存+加密


BitmapFactory.Options:參數(shù):
inDensity:bitmap的像素密度
inTargetDensity:bitmap最終的像素密度
DensityDpi(屏幕的像素密度) 分辨率 Density
160dpi 320x533 1
px = dp*Density

手機像素表

圖片存在的幾種形式:

  • File
  • 流的形式
  • Bitmap的形式---內(nèi)存

圖片壓縮方式

1.質(zhì)量壓縮

AB
CD
壓縮后
AA
AA
原理:通過算法摳掉(同化)了圖片中的一些某個些點附近相近的像素,達到降低質(zhì)量介紹文件大小的目的乘碑。
減小了圖片質(zhì)量
** 注意:*它其實只能實現(xiàn)對file的影響挖息,對加載這個圖片出來的bitmap內(nèi)存是無法節(jié)省的,還是那么大兽肤。 因為bitmap在內(nèi)存中的大小是按照像素計算的套腹,也就是widthheight,對于質(zhì)量壓縮资铡,并不會改變圖片的真實的像素(像素大小不會變)电禀。

** 使用場景:**
將圖片壓縮后保存到本地,或者將圖片上傳到服務器笤休。根據(jù)實際需求來尖飞。

public static void compressImageToFile(Bitmap bmp,File file){
    //0~100
    int quality = 50;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.JPEG, quality , baos );
    try {
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(baos.toByteArray());
        fos.flush();
        fos.close();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
2.尺寸壓縮

通過減少單位尺寸的像素值,真正意義上的降低像素店雅。1020*8880

** 使用場景:** 緩存縮略圖的時候(頭像處理)

public static void compressBitmapToFileBySize(Bitmap bmp,File file){
    //壓縮尺寸倍數(shù)政基,值越大,圖片的尺寸就越小
    int ratio = 4;
    Bitmap result = Bitmap.createBitmap(bmp.getWidth()/ratio, 
              bmp.getHeight()/ratio, Bitmap.Config.ARGB_8888);
    
    Canvas canvas = new Canvas(result);
    RectF rect = new RectF(0, 0, bmp.getWidth()/ratio, bmp.getHeight()/ratio);
    canvas.drawBitmap(bmp, null, rect , null);
    
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    result.compress(Bitmap.CompressFormat.JPEG, 100, baos);
    try {
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(baos.toByteArray());
        fos.flush();
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    
}
3.采樣率壓縮
4.終極壓縮(NDK層壓縮)

1.IOS拍照1M的圖片要比安卓拍照排出來的5M的圖片還要清晰闹啦。
都是在同一個環(huán)境下沮明,保存的都是JPEG。為什么窍奋?

2.圖像處理引擎
95年 JPEG處理引擎荐健,用于最初的在PC上面處理圖片的引擎。
05年 skia開源的引擎, 開發(fā)了一套基于JPEG處理引擎的第二次開發(fā)琳袄。便于瀏覽器的使用江场。

07年, 安卓上面用的什么引擎挚歧?
skia引擎扛稽,閹割版
谷歌拿了skia 思考了半天做了一個決定,去掉一個編碼算法---哈夫曼算法滑负。采用定長編碼算法在张。但是解碼還是保留了哈夫曼算法。導致了圖片處理后文件變大了矮慕。

理由:當時由于CPU和內(nèi)存在手機上都非常吃緊 性能差帮匾,而哈夫曼算法非常吃CPU,被迫用了其他的算法痴鳄。

我們的優(yōu)化:
繞過安卓Bitmap API層瘟斜,來自己編碼實現(xiàn)----修復使用哈夫曼算法。

argb
一個像素點包涵四個信息:alpha,red,green螺句,blue

a b c d e

abcde acdbe bacde ……

101010100011100
a:001
b:010
c:011
d:100
e:101
用3位來表示一個字符信息虽惭,屬于定長編碼的最優(yōu)。

abcde
001 010 011 100 101
加權(quán)信息編碼

a:80%
b:10%
c:10%
d:0%
e:0%
這種情況蛇尚,編碼就可以優(yōu)化了
a:01
b:10
c:11
優(yōu)化后的abc:01 10 11
優(yōu)化前的abc:001 010 011

通過加權(quán)可以知道那個信息為0(即沒有)芽唇,那么就表示可以省略“一位”,這樣數(shù)據(jù)量信息就會減少取劫,從而使圖片變得更小匆笤。

那么如何得到每一個字母出現(xiàn)的權(quán)重?
哈夫曼編碼:需要去掃描每個信息(圖片信息--每一個像素包括ARGB)谱邪,需要大量計算炮捧,很吃CPU。
1280800像素4

如何實現(xiàn)惦银?

下載JPEG引擎使用的庫---libjpeg庫
http://www.ijg.org/

基于該引擎來做一定的開發(fā)----自己實現(xiàn)編碼咆课。

1.導入庫文件libjpegbither.so
2.導入頭文件
3.寫mk文件
Android.mk
Applicatoin.mk
4.寫代碼
C++: XX.cpp
C: XX.c

操作步驟:
1.將android的bitmap解碼,并轉(zhuǎn)換成RGB數(shù)據(jù)璧函,一個圖片信息---像素點(argb)傀蚌,把alpha去掉。
2.JPEG對象分配空間以及初始化
3.指定壓縮數(shù)據(jù)源
4.獲取文件信息
5.為壓縮設(shè)置參數(shù)蘸吓,比如圖像大小善炫、類型、顏色空間
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
6.開始壓縮
jpeg_start_compress()
7.壓縮結(jié)束
jpeg_finish_compress()
8.釋放資源


/*
 * Copyright 2014 http://Bither.net
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.bither.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.util.Log;

public class NativeUtil {
     private static int DEFAULT_QUALITY = 95;

        /**
         * @param bit      bitmap對象
         * @param fileName 指定保存目錄名
         * @param optimize 是否采用哈弗曼表數(shù)據(jù)計算 品質(zhì)相差5-10倍
         * @Description: JNI基本壓縮
         */
        public static void compressBitmap(Bitmap bit, String fileName, boolean optimize) {
            saveBitmap(bit, DEFAULT_QUALITY, fileName, optimize);
        }

        /**
         * @param image    bitmap對象
         * @param filePath 要保存的指定目錄
         * @Description: 通過JNI圖片壓縮把Bitmap保存到指定目錄
         */
        public static void compressBitmap(Bitmap image, String filePath) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // 質(zhì)量壓縮方法库继,這里100表示不壓縮箩艺,把壓縮后的數(shù)據(jù)存放到baos中
            int options = 20;
            // JNI調(diào)用保存圖片到SD卡 這個關(guān)鍵
            NativeUtil.saveBitmap(image, options, filePath, true);
        }

        /**
         * 計算縮放比
         *
         * @param bitWidth  當前圖片寬度
         * @param bitHeight 當前圖片高度
         * @return
         * @Description:函數(shù)描述
         */
        public static int getRatioSize(int bitWidth, int bitHeight) {
            // 圖片最大分辨率
            int imageHeight = 1920;
            int imageWidth = 1080;
            // 縮放比
            int ratio = 1;
            // 縮放比,由于是固定比例縮放,只用高或者寬其中一個數(shù)據(jù)進行計算即可
            if (bitWidth > bitHeight && bitWidth > imageWidth) {
                // 如果圖片寬度比高度大,以寬度為基準
                ratio = bitWidth / imageHeight;
            } else if (bitWidth < bitHeight && bitHeight > imageHeight) {
                // 如果圖片高度比寬度大宪萄,以高度為基準
                ratio = bitHeight / imageHeight;
            }
            // 最小比率為1
            if (ratio <= 0)
                ratio = 1;
            return ratio;
        }

        /**
         * 調(diào)用native方法
         *
         * @param bit
         * @param quality
         * @param fileName
         * @param optimize
         * @Description:函數(shù)描述
         */
        public static void saveBitmap(Bitmap bit, int quality, String fileName, boolean optimize) {
            compressBitmap(bit, bit.getWidth(), bit.getHeight(), quality, fileName.getBytes(), optimize);
        }

        /**
         * 調(diào)用底層 bitherlibjni.c中的方法
         *
         * @param bit
         * @param w
         * @param h
         * @param quality
         * @param fileNameBytes
         * @param optimize
         * @return
         * @Description:函數(shù)描述
         */
        public static native String compressBitmap(Bitmap bit, int w, int h, int quality, byte[] fileNameBytes,
                                                    boolean optimize);

        /**
         * 加載lib下兩個so文件
         */
        static {
            System.loadLibrary("jpegbither");
            System.loadLibrary("bitherjni");
        }


        /**
         * 1. 質(zhì)量壓縮
                 設(shè)置bitmap options屬性艺谆,降低圖片的質(zhì)量,像素不會減少
                 第一個參數(shù)為需要壓縮的bitmap圖片對象拜英,第二個參數(shù)為壓縮后圖片保存的位置
                 設(shè)置options 屬性0-100静汤,來實現(xiàn)壓縮
         * @param bmp
         * @param file
         */
        public static void compressImageToFile(Bitmap bmp,File file) {
            // 0-100 100為不壓縮
            int options = 20;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // 把壓縮后的數(shù)據(jù)存放到baos中
            bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
            try {
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(baos.toByteArray());
                fos.flush();
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        /**
         *
         * 2. 尺寸壓縮
         通過縮放圖片像素來減少圖片占用內(nèi)存大小
         * @param bmp
         * @param file
         */

        public static void compressBitmapToFile(Bitmap bmp, File file){
            // 尺寸壓縮倍數(shù),值越大,圖片尺寸越小
            int ratio = 8;
            // 壓縮Bitmap到對應尺寸
            Bitmap result = Bitmap.createBitmap(bmp.getWidth() / ratio, bmp.getHeight() / ratio, Config.ARGB_8888);
            Canvas canvas = new Canvas(result);
            Rect rect = new Rect(0, 0, bmp.getWidth() / ratio, bmp.getHeight() / ratio);
            canvas.drawBitmap(bmp, null, rect, null);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // 把壓縮后的數(shù)據(jù)存放到baos中
            result.compress(Bitmap.CompressFormat.JPEG, 100 ,baos);
            try {
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(baos.toByteArray());
                fos.flush();
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


        /**
         * 設(shè)置圖片的采樣率居凶,降低圖片像素
         * @param filePath
         * @param file
         */
        public static void compressBitmap(String filePath, File file){
            // 數(shù)值越高虫给,圖片像素越低
            int inSampleSize = 8;
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = false;
//          options.inJustDecodeBounds = true;//為true的時候不會真正加載圖片,而是得到圖片的寬高信息侠碧。
            //采樣率
            options.inSampleSize = inSampleSize;
            Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // 把壓縮后的數(shù)據(jù)存放到baos中
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100 ,baos);
            try {
                if(file.exists())
                {
                    file.delete();
                }
                else {
                    file.createNewFile();
                }
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(baos.toByteArray());
                fos.flush();
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
}

#include "bitherlibjni.h"
#include <string.h>
#include <android/bitmap.h>
#include <android/log.h>
#include <stdio.h>
#include <setjmp.h>
#include <math.h>
#include <stdint.h>
#include <time.h>

//統(tǒng)一編譯方式
extern "C" {
#include "jpeg/jpeglib.h"
#include "jpeg/cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
#include "jpeg/jversion.h"      /* for version message */
#include "jpeg/android/config.h"
}


#define LOG_TAG "jni"
#define LOGW(...)  __android_log_write(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

#define true 1
#define false 0

typedef uint8_t BYTE;

char *error;
struct my_error_mgr {
  struct jpeg_error_mgr pub;
  jmp_buf setjmp_buffer;
};

typedef struct my_error_mgr * my_error_ptr;

METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
  my_error_ptr myerr = (my_error_ptr) cinfo->err;
  (*cinfo->err->output_message) (cinfo);
  error=(char*)myerr->pub.jpeg_message_table[myerr->pub.msg_code];
  LOGE("jpeg_message_table[%d]:%s", myerr->pub.msg_code,myerr->pub.jpeg_message_table[myerr->pub.msg_code]);
 // LOGE("addon_message_table:%s", myerr->pub.addon_message_table);
//  LOGE("SIZEOF:%d",myerr->pub.msg_parm.i[0]);
//  LOGE("sizeof:%d",myerr->pub.msg_parm.i[1]);
  longjmp(myerr->setjmp_buffer, 1);
}

int generateJPEG(BYTE* data, int w, int h, int quality,
        const char* outfilename, jboolean optimize) {

    //jpeg的結(jié)構(gòu)體抹估,保存的比如寬、高弄兜、位深药蜻、圖片格式等信息瓷式,相當于java的類
    struct jpeg_compress_struct jcs;

    //當讀完整個文件的時候就會回調(diào)my_error_exit這個退出方法。setjmp是一個系統(tǒng)級函數(shù)语泽,是一個回調(diào)贸典。
    struct my_error_mgr jem;
    jcs.err = jpeg_std_error(&jem.pub);
    jem.pub.error_exit = my_error_exit;
    if (setjmp(jem.setjmp_buffer)) {
        return 0;
    }

    //初始化jsc結(jié)構(gòu)體
    jpeg_create_compress(&jcs);
    //打開輸出文件 wb:可寫byte
    FILE* f = fopen(outfilename, "wb");
    if (f == NULL) {
        return 0;
    }
    //設(shè)置結(jié)構(gòu)體的文件路徑
    jpeg_stdio_dest(&jcs, f);
    jcs.image_width = w;//設(shè)置寬高
    jcs.image_height = h;
//  if (optimize) {
//      LOGI("optimize==ture");
//  } else {
//      LOGI("optimize==false");
//  }

    //看源碼注釋,設(shè)置哈夫曼編碼:/* TRUE=arithmetic coding, FALSE=Huffman */
    jcs.arith_code = false;
    int nComponent = 3;
    /* 顏色的組成 rgb踱卵,三個 # of color components in input image */
    jcs.input_components = nComponent;
    //設(shè)置結(jié)構(gòu)體的顏色空間為rgb
    jcs.in_color_space = JCS_RGB;
//  if (nComponent == 1)
//      jcs.in_color_space = JCS_GRAYSCALE;
//  else
//      jcs.in_color_space = JCS_RGB;

    //全部設(shè)置默認參數(shù)/* Default parameter setup for compression */
    jpeg_set_defaults(&jcs);
    //是否采用哈弗曼表數(shù)據(jù)計算 品質(zhì)相差5-10倍
    jcs.optimize_coding = optimize;
    //設(shè)置質(zhì)量
    jpeg_set_quality(&jcs, quality, true);
    //開始壓縮瓤漏,(是否寫入全部像素)
    jpeg_start_compress(&jcs, TRUE);

    JSAMPROW row_pointer[1];
    int row_stride;
    //一行的rgb數(shù)量
    row_stride = jcs.image_width * nComponent;
    //一行一行遍歷
    while (jcs.next_scanline < jcs.image_height) {
        //得到一行的首地址
        row_pointer[0] = &data[jcs.next_scanline * row_stride];

        //此方法會將jcs.next_scanline加1
        jpeg_write_scanlines(&jcs, row_pointer, 1);//row_pointer就是一行的首地址,1:寫入的行數(shù)
    }
    jpeg_finish_compress(&jcs);//結(jié)束
    jpeg_destroy_compress(&jcs);//銷毀 回收內(nèi)存
    fclose(f);//關(guān)閉文件

    return 1;
}

/**
 * byte數(shù)組轉(zhuǎn)C的字符串
 */
char* jstrinTostring(JNIEnv* env, jbyteArray barr) {
    char* rtn = NULL;
    jsize alen = env->GetArrayLength( barr);
    jbyte* ba = env->GetByteArrayElements( barr, 0);
    if (alen > 0) {
        rtn = (char*) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements( barr, ba, 0);
    return rtn;
}

jstring Java_net_bither_util_NativeUtil_compressBitmap(JNIEnv* env,
        jclass thiz, jobject bitmapcolor, int w, int h, int quality,
        jbyteArray fileNameStr, jboolean optimize) {
    BYTE *pixelscolor;
    //1.將bitmap里面的所有像素信息讀取出來,并轉(zhuǎn)換成RGB數(shù)據(jù),保存到二維byte數(shù)組里面
    //處理bitmap圖形信息方法1 鎖定畫布
    AndroidBitmap_lockPixels(env,bitmapcolor,(void**)&pixelscolor);

    //2.解析每一個像素點里面的rgb值(去掉alpha值)颊埃,保存到一維數(shù)組data里面
    BYTE *data;
    BYTE r,g,b;
    data = (BYTE*)malloc(w*h*3);//每一個像素都有三個信息RGB
    BYTE *tmpdata;
    tmpdata = data;//臨時保存data的首地址
    int i=0,j=0;
    int color;
    for (i = 0; i < h; ++i) {
        for (j = 0; j < w; ++j) {
            //解決掉alpha
            //獲取二維數(shù)組的每一個像素信息(四個部分a/r/g/b)的首地址
            color = *((int *)pixelscolor);//通過地址取值
            //0~255:
//          a = ((color & 0xFF000000) >> 24);
            r = ((color & 0x00FF0000) >> 16);
            g = ((color & 0x0000FF00) >> 8);
            b = ((color & 0x000000FF));
            //改值!5恪班利!----保存到data數(shù)據(jù)里面
            *data = b;
            *(data+1) = g;
            *(data+2) = r;
            data = data + 3;
            //一個像素包括argb四個值,每+4就是取下一個像素點
            pixelscolor += 4;
        }
    }
    //處理bitmap圖形信息方法2 解鎖
    AndroidBitmap_unlockPixels(env,bitmapcolor);
    char* fileName = jstrinTostring(env,fileNameStr);
    //調(diào)用libjpeg核心方法實現(xiàn)壓縮
    int resultCode = generateJPEG(tmpdata,w,h,quality,fileName,optimize);
    if(resultCode ==0){
        jstring result = env->NewStringUTF("-1");
        return result;
    }
    return env->NewStringUTF("1");
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末榨呆,一起剝皮案震驚了整個濱河市罗标,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌积蜻,老刑警劉巖闯割,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異竿拆,居然都是意外死亡宙拉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門丙笋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谢澈,“玉大人,你說我怎么就攤上這事御板∽斗蓿” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵怠肋,是天一觀的道長敬鬓。 經(jīng)常有香客問我,道長笙各,這世上最難降的妖魔是什么钉答? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮酪惭,結(jié)果婚禮上希痴,老公的妹妹穿的比我還像新娘。我一直安慰自己春感,他們只是感情好砌创,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布虏缸。 她就那樣靜靜地躺著,像睡著了一般嫩实。 火紅的嫁衣襯著肌膚如雪刽辙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天甲献,我揣著相機與錄音宰缤,去河邊找鬼。 笑死晃洒,一個胖子當著我的面吹牛慨灭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播球及,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼氧骤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吃引?” 一聲冷哼從身側(cè)響起筹陵,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎镊尺,沒想到半個月后朦佩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡庐氮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年语稠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旭愧。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡颅筋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出输枯,到底是詐尸還是另有隱情议泵,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布桃熄,位于F島的核電站先口,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏瞳收。R本人自食惡果不足惜碉京,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望螟深。 院中可真熱鬧谐宙,春花似錦、人聲如沸界弧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至划栓,卻和暖如春兑巾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背忠荞。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工蒋歌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人委煤。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓堂油,卻偏偏與公主長得像,于是被迫代替她去往敵國和親碧绞。 傳聞我的和親對象是個殘疾皇子称诗,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容