Quartz 2D編程指南 (三) —— 圖形上下文(三)

版本記錄

版本號 時間
V1.0 2018.09.03

前言

Quartz 2D框架相信大家都知道,也都一直在使用。Quartz 2D的API是純C語言的,它是一個二維繪圖引擎,同時支持iOS和Mac系統。Quartz 2D的API來自于Core Graphics框架,數據類型和函數基本都以CG作為前綴,接下來幾篇我們就一起來看一下這個框架。感興趣可以看上面幾篇文章。
1. Quartz 2D編程指南 (一) —— 簡介(一)
2. Quartz 2D編程指南 (二) —— Quartz 2D概覽(二)

Graphics Contexts - 圖形上下文

圖形上下文表示繪圖目的地。它包含繪圖參數和繪圖系統執行任何后續繪圖命令所需的所有特定于設備的信息。圖形上下文定義基本的繪圖屬性,例如繪制時使用的顏色,剪切區域,線寬和樣式信息,字體信息,合成選項以及其他幾種。

您可以使用Quartz上下文創建函數或使用某個Mac OS X框架或iOS中UIKit框架提供的更高級別函數來獲取圖形上下文。 Quartz提供各種Quartz圖形上下文函數,包括位圖和PDF,您可以使用它們來創建自定義內容。

本章介紹如何為各種繪圖目的地創建圖形上下文。圖形上下文在代碼中由數據類型CGContextRef表示,它是一種不透明的數據類型。獲取圖形上下文后,可以使用Quartz 2D函數繪制上下文,對上下文執行操作(如翻譯),以及更改圖形狀態參數,如線寬和填充顏色。


Drawing to a View Graphics Context in iOS - 在iOS中繪制視圖圖形上下文

要在iOS應用程序中繪制到屏幕,請設置UIView對象并實現其 drawRect: 方法以執行繪圖。當視圖在屏幕上可見并且其內容需要更新時,將調用視圖的drawRect:方法。在調用自定義drawRect:方法之前,視圖對象會自動配置其繪圖環境,以便您的代碼可以立即開始繪制。作為此配置的一部分,UIView對象為當前繪圖環境創建圖形上下文( CGContextRef opaque類型)。您可以通過調用UIKit函數UIGraphicsGetCurrentContextdrawRect:方法中獲取此圖形上下文。

整個UIKit使用的默認坐標系與Quartz使用的坐標系不同。在UIKit中,原點位于左上角,正y值指向下方。 UIView對象通過將原點轉換為視圖的左上角并通過將其乘以-1來反轉y軸來修改Quartz圖形上下文的CTM以匹配UIKit約定。有關修改坐標系統的更多信息以及您自己的繪圖代碼中的含義,請參閱Quartz 2D Coordinate Systems

UIView對象在適用于View Programming Guide for iOS中有詳細描述。


Creating a Window Graphics Context in Mac OS X - 在Mac OS X中創建窗口圖形上下文

Mac OS X中繪圖時,您需要創建適合您正在使用的框架的窗口圖形上下文。 Quartz 2D API本身不提供獲取Windows圖形上下文的函數。 相反,您使用Cocoa框架來獲取在Cocoa中創建的窗口的上下文。

您可以使用以下代碼行從Cocoa應用程序的drawRect:例程中獲取Quartz圖形上下文:

CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];

currentContext方法返回當前線程的NSGraphicsContext實例。 方法graphicsPort返回由接收器表示的低級,特定于平臺的圖形上下文,這是一個Quartz圖形上下文。 (不要對方法名稱感到困惑,它們是歷史原因。)有關更多信息,請參閱NSGraphicsContext Class Reference

獲取圖形上下文后,可以在Cocoa應用程序中調用任何Quartz 2D繪圖函數。 您還可以將Quartz 2D調用與Cocoa繪圖調用混合使用。 通過查看圖2-1,您可以看到Quartz 2D繪圖到Cocoa視圖的示例。 該圖由兩個重疊的矩形組成,一個是不透明的紅色,另一個是部分透明的藍色。您將了解有關Color and Color Spaces的更多信息。 控制多少“透視”顏色的能力是Quartz 2D的標志性功能之一。

Figure 2-1 A view in the Cocoa framework that contains Quartz drawing

要創建圖2-1中的繪圖,首先要創建一個Cocoa應用程序Xcode項目。 在Interface Builder中,將自定義視圖拖到窗口并將其子類化。 然后為子類視圖編寫一個實現,類似于LIsting 2-1所示。 對于此示例,子類視圖名為MyQuartzView。 視圖的drawRect:方法包含所有Quartz繪圖代碼。 列表后面會顯示每個編號行代碼的詳細說明。

注意:每次需要繪制視圖時,都會自動調用NSView類的drawRect:方法。 要了解有關覆蓋drawRect:方法的更多信息,請參閱NSView Class Reference

// Listing 2-1  Drawing to a window graphics context

@implementation MyQuartzView
 
- (id)initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    return self;
}
 
- (void)drawRect:(NSRect)rect
{
    CGContextRef myContext = [[NSGraphicsContext // 1
                                currentContext] graphicsPort];
   // ********** Your drawing code here ********** // 2
    CGContextSetRGBFillColor (myContext, 1, 0, 0, 1);// 3
    CGContextFillRect (myContext, CGRectMake (0, 0, 200, 100 ));// 4
    CGContextSetRGBFillColor (myContext, 0, 0, 1, .5);// 5
    CGContextFillRect (myContext, CGRectMake (0, 0, 100, 200));// 6
  }
 
@end

這是代碼的作用:

  • 1)獲取視圖的圖形上下文。
  • 2)這是您插入繪圖代碼的地方。 下面的四行代碼是使用Quartz 2D函數的示例。
  • 3)設置完全不透明的紅色填充顏色。 有關顏色和alpha(設置不透明度)的信息,請參閱Color and Color Spaces
  • 4)填充原點為(0,0)且寬度為200且高度為100的矩形。有關繪制矩形的信息,請參閱Paths
  • 5)設置部分透明的藍色填充顏色。
  • 6)填充一個矩形,其原點為(0,0),寬度為100,高度為200。

Creating a PDF Graphics Context - 創建一個PDF圖像上下文

當您創建PDF圖形上下文并繪制到該上下文時,Quartz會將您的繪圖記錄為一系列寫入文件的PDF繪圖命令。 您提供PDF輸出的位置和默認媒體框 - 指定頁面邊界的矩形。 圖2-2顯示了繪制到PDF圖形上下文然后在預覽中打開生成的PDF的結果。

Figure 2-2 A PDF created by using CGPDFContextCreateWithURL

Quartz 2D API提供了兩個創建PDF圖形上下文的函數:

  • CGPDFContextCreateWithURL,當您要將PDF輸出的位置指定為Core Foundation URL時使用。Listing 2-2顯示了如何使用此函數創建PDF圖形上下文。
  • CGPDFContextCreate,當您希望將PDF輸出發送給數據使用者時使用。 (有關更多信息,請參閱Data Management in Quartz 2D。)Listing 2-3顯示了如何使用此函數創建PDF圖形上下文。

每個列表后面的每個編號行代碼的詳細說明。

iOS注意:iOS中的PDF圖形上下文使用Quartz提供的默認坐標系,而不應用變換來匹配UIKit坐標系。如果您的應用程序計劃在PDF圖形上下文和UIView對象提供的圖形上下文之間共享繪圖代碼,則應用程序應修改PDF圖形上下文的CTM以修改坐標系。請參見 Quartz 2D Coordinate Systems

// Listing 2-2  Calling CGPDFContextCreateWithURL to create a PDF graphics context

CGContextRef MyPDFContextCreate (const CGRect *inMediaBox,
                                    CFStringRef path)
{
    CGContextRef myOutContext = NULL;
    CFURLRef url;
 
    url = CFURLCreateWithFileSystemPath (NULL, // 1
                                path,
                                kCFURLPOSIXPathStyle,
                                false);
    if (url != NULL) {
        myOutContext = CGPDFContextCreateWithURL (url,// 2
                                        inMediaBox,
                                        NULL);
        CFRelease(url);// 3
    }
    return myOutContext;// 4
}

這是代碼的作用:

  • 1)調用Core Foundation函數從提供給MyPDFContextCreate函數的CFString對象創建CFURL對象。 您將NULL作為第一個參數傳遞以使用默認分配器。 您還需要指定路徑樣式,對于此示例,路徑樣式是POSIX樣式的路徑名。
  • 2)調用Quartz 2D函數,使用剛剛創建的PDF位置(作為CFURL對象)和指定PDF邊界的矩形創建PDF圖形上下文。 矩形(CGRect)已傳遞給MyPDFContextCreate函數,并且是PDF的默認頁面媒體邊界框。
  • 3)釋放CFURL對象。
  • 4)返回PDF圖形上下文。 調用者必須在不再需要時釋放圖形上下文。
// Listing 2-3  Calling CGPDFContextCreate to create a PDF graphics context

CGContextRef MyPDFContextCreate (const CGRect *inMediaBox,
                                    CFStringRef path)
{
    CGContextRef        myOutContext = NULL;
    CFURLRef            url;
    CGDataConsumerRef   dataConsumer;
 
    url = CFURLCreateWithFileSystemPath (NULL, // 1
                                        path,
                                        kCFURLPOSIXPathStyle,
                                        false);
 
    if (url != NULL)
    {
        dataConsumer = CGDataConsumerCreateWithURL (url);// 2
        if (dataConsumer != NULL)
        {
            myOutContext = CGPDFContextCreate (dataConsumer, // 3
                                        inMediaBox,
                                        NULL);
            CGDataConsumerRelease (dataConsumer);// 4
        }
        CFRelease(url);// 5
    }
    return myOutContext;// 6
}

這是代碼的作用:

  • 1)調用Core Foundation函數從提供給MyPDFContextCreate函數的CFString對象創建CFURL對象。您將NULL作為第一個參數傳遞以使用默認分配器。您還需要指定路徑樣式,對于此示例,路徑樣式是POSIX樣式的路徑名。
  • 2)使用CFURL對象創建Quartz數據使用者對象。如果您不想使用CFURL對象(例如,您希望將PDF數據放在CFURL對象無法指定的位置),則可以從您在應用程序中實現的一組回調函數創建數據使用者。有關更多信息,請參閱Data Management in Quartz 2D
  • 3)調用Quartz 2D函數創建一個PDF圖形上下文,作為參數傳遞給數據使用者和傳遞給MyPDFContextCreate函數的矩形(CGRect類型)。此矩形是PDF的默認頁面媒體邊界框。
  • 4)釋放數據使用者。
  • 5)釋放CFURL對象。
  • 6)返回PDF圖形上下文。調用者必須在不再需要時釋放圖形上下文。

Listing 2-4顯示了如何調用MyPDFContextCreate例程并繪制它。列表后面會顯示每個編號行代碼的詳細說明。

// Listing 2-4  Drawing to a PDF graphics context

    CGRect mediaBox;// 1
 
    mediaBox = CGRectMake (0, 0, myPageWidth, myPageHeight);// 2
    myPDFContext = MyPDFContextCreate (&mediaBox, CFSTR("test.pdf"));// 3
 
    CFStringRef myKeys[1];// 4
    CFTypeRef myValues[1];
    myKeys[0] = kCGPDFContextMediaBox;
    myValues[0] = (CFTypeRef) CFDataCreate(NULL,(const UInt8 *)&mediaBox, sizeof (CGRect));
    CFDictionaryRef pageDictionary = CFDictionaryCreate(NULL, (const void **) myKeys,
                                                        (const void **) myValues, 1,
                                                        &kCFTypeDictionaryKeyCallBacks,
                                                        & kCFTypeDictionaryValueCallBacks);
    CGPDFContextBeginPage(myPDFContext, &pageDictionary);// 5
        // ********** Your drawing code here **********// 6
        CGContextSetRGBFillColor (myPDFContext, 1, 0, 0, 1);
        CGContextFillRect (myPDFContext, CGRectMake (0, 0, 200, 100 ));
        CGContextSetRGBFillColor (myPDFContext, 0, 0, 1, .5);
        CGContextFillRect (myPDFContext, CGRectMake (0, 0, 100, 200 ));
    CGPDFContextEndPage(myPDFContext);// 7
    CFRelease(pageDictionary);// 8
    CFRelease(myValues[0]);
    CGContextRelease(myPDFContext);

這是代碼的作用:

  • 1)聲明用于定義PDF媒體框的矩形的變量。
  • 2)將媒體框的原點設置為(0,0),將寬度和高度設置為應用程序提供的變量。
  • 3)調用函數MyPDFContextCreate(參見Listing 2-3)以獲取PDF圖形上下文,提供媒體框和路徑名。宏CFSTR將字符串轉換為CFStringRef數據類型。
  • 4)使用頁面選項設置字典。在此示例中,僅指定了媒體框。您不必傳遞用于設置PDF圖形上下文的相同矩形。您在此處添加的媒體框將取代您傳遞的矩形以設置PDF圖形上下文。
  • 5)表示頁面的開頭。此函數用于面向頁面的圖形,這是PDF繪圖。
  • 6)調用Quartz 2D繪圖函數。您可以使用適合您的應用程序的繪圖代碼替換此代碼和以下四行代碼。
  • 7)表示PDF頁面的結尾。
  • 8)在不再需要時候,釋放字典和PDF圖形上下文。

您可以將任何內容寫入適合您的應用程序的PDF - 圖像,文本,路徑繪圖 - 并且您可以添加鏈接和加密。有關更多信息,請參閱PDF Document Creation, Viewing, and Transforming


Creating a Bitmap Graphics Context - 創建位圖圖形上下文

位圖圖形上下文接受指向包含位圖存儲空間的內存緩沖區的指針。當您繪制到位圖圖形上下文時,緩沖區會更新。釋放圖形上下文后,您將以指定的像素格式獲得完全更新的位圖。

注意:位圖圖形上下文有時用于繪制屏幕外。在您決定使用位圖圖形上下文之前,請參閱Core Graphics Layer DrawingCGLayer對象(CGLayerRef)針對屏幕外繪圖進行了優化,因為只要有可能,Quartz就會在視頻卡上緩存圖層。

iOS注意:iOS應用程序應使用函數。UIGraphicsBeginImageContextWithOptions而不是使用此處描述的低級Quartz函數。如果您的應用程序使用Quartz創建屏幕外位圖,則位圖圖形上下文使用的坐標系是默認的Quartz坐標系。相反,如果您的應用程序通過調用函數UIGraphicsBeginImageContextWithOptions來創建圖像上下文,則UIKit將相同的變換應用于上下文的坐標系,就像對UIView對象的圖形上下文一樣。這允許您的應用程序使用相同的繪圖代碼,而無需擔心不同的坐標系。雖然您的應用程序可以手動調整坐標轉換矩陣以獲得正確的結果,但實際上,這樣做沒有性能優勢。

您可以使用函數CGBitmapContextCreate來創建位圖圖形上下文。此函數采用以下參數:

  • 1)data。在內存中提供指向要渲染圖形的目標的指針。此內存塊的大小應至少為(bytesPerRow * height)字節。
  • 2)width。指定位圖的寬度(以像素為單位)。
  • 3)height。指定位圖的高度(以像素為單位)。
  • 4)bitsPerComponent。指定內存中像素的每個組件使用的位數。例如,對于32位像素格式和RGB顏色空間,您將為每個組件指定8位的值。請參閱Supported Pixel Formats
  • 5)bytesPerRow。指定位圖每行使用的內存字節數。

提示:創建位圖圖形上下文時,如果確保數據和bytesPerRow是16字節對齊,則可以獲得最佳性能。

  • 6)colorspace。用于位圖上下文的顏色空間。創建位圖圖形上下文時,可以提供Gray, RGB, CMYK, 和 NULL顏色空間。有關顏色空間和顏色管理原則的詳細信息,請參閱顏 Color Management Overview。有關在Quartz中創建和使用顏色空間的信息,請參閱Color and Color Spaces。有關支持的顏色空間的信息,請參閱Bitmap Images and Image Masks一章中的Color Spaces and Bitmap Layout

  • 7)bitmapInfo。位圖布局信息,表示為CGBitmapInfo常量,指定位圖是否應包含alpha分量,像素中alpha分量(如果有)的相對位置,alpha分量是否預乘,以及顏色分量是整數或浮點值。有關這些常量的詳細信息,每個常量的使用時間以及位圖圖形上下文和圖像的Quartz支持的像素格式,請參閱Bitmap Images and Image Masks一章中的 Color Spaces and Bitmap Layout

Listing 2-5顯示了如何創建位圖圖形上下文。當您繪制到生成的位圖圖形上下文時,Quartz會將您的繪圖記錄為指定內存塊中的位圖數據。列表后面的每個編號行代碼的詳細說明。

// Listing 2-5  Creating a bitmap graphics context

CGContextRef MyCreateBitmapContext (int pixelsWide,
                            int pixelsHigh)
{
    CGContextRef    context = NULL;
    CGColorSpaceRef colorSpace;
    void *          bitmapData;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;
 
    bitmapBytesPerRow   = (pixelsWide * 4);// 1
    bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);
 
    colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);// 2
    bitmapData = calloc( bitmapByteCount, sizeof(uint8_t) );// 3
    if (bitmapData == NULL)
    {
        fprintf (stderr, "Memory not allocated!");
        return NULL;
    }
    context = CGBitmapContextCreate (bitmapData,// 4
                                    pixelsWide,
                                    pixelsHigh,
                                    8,      // bits per component
                                    bitmapBytesPerRow,
                                    colorSpace,
                                    kCGImageAlphaPremultipliedLast);
    if (context== NULL)
    {
        free (bitmapData);// 5
        fprintf (stderr, "Context not created!");
        return NULL;
    }
    CGColorSpaceRelease( colorSpace );// 6
 
    return context;// 7
}

這是代碼的作用:

  • 1)聲明一個變量來表示每行的字節數。本例中位圖中的每個像素由4個字節表示:紅色,綠色,藍色和alpha各8位。
  • 2)創建通用RGB顏色空間。您還可以創建CMYK顏色空間。有關更多信息以及有關通用顏色空間與設備相關顏色空間的討論,請參閱Color and Color Spaces
  • 3)調用calloc函數來創建和清除用于存儲位圖數據的內存塊。此示例創建一個32位RGBA位圖(即,每像素32位的數組,每個像素包含紅色,綠色,藍色和alpha信息各8位)。位圖中的每個像素占用4個字節的內存。在Mac OS X 10.6和iOS 4中,可以省略此步驟 - 如果將NULL作為位圖數據傳遞,Quartz會自動為位圖分配空間。
  • 4)創建位圖圖形上下文,提供位圖數據,位圖的寬度和高度,每個組件的位數,每行的字節數,顏色空間,以及指定位圖是否應包含alpha通道的常量以及它在像素中的相對位置。kCGImageAlphaPremultipliedLast表示alpha分量存儲在每個像素的最后一個字節中,并且顏色分量已經乘以此alpha值。有關預乘alpha的更多信息,請參閱The Alpha Value
  • 5)如果由于某種原因未創建上下文,則釋放為位圖數據分配的內存。
  • 6)釋放色彩空間。
  • 7)返回位圖圖形上下文。調用者必須在不再需要時釋放圖形上下文。

Listing 2-6顯示了調用MyCreateBitmapContext來創建位圖圖形上下文的代碼,使用位圖圖形上下文創建CGImage對象,然后將生成的圖像繪制到窗口圖形上下文中。圖2-3顯示了繪制到窗口的圖像。列表后面的每個編號行代碼的詳細說明。

// Listing 2-6  Drawing to a bitmap graphics context
    CGRect myBoundingBox;// 1
 
    myBoundingBox = CGRectMake (0, 0, myWidth, myHeight);// 2
    myBitmapContext = MyCreateBitmapContext (400, 300);// 3
    // ********** Your drawing code here ********** // 4
    CGContextSetRGBFillColor (myBitmapContext, 1, 0, 0, 1);
    CGContextFillRect (myBitmapContext, CGRectMake (0, 0, 200, 100 ));
    CGContextSetRGBFillColor (myBitmapContext, 0, 0, 1, .5);
    CGContextFillRect (myBitmapContext, CGRectMake (0, 0, 100, 200 ));
    myImage = CGBitmapContextCreateImage (myBitmapContext);// 5
    CGContextDrawImage(myContext, myBoundingBox, myImage);// 6
    char *bitmapData = CGBitmapContextGetData(myBitmapContext); // 7
    CGContextRelease (myBitmapContext);// 8
    if (bitmapData) free(bitmapData); // 9
    CGImageRelease(myImage);// 10

這是代碼的作用:

  • 1)聲明一個變量來存儲邊界框的原點和尺寸,Quartz將在其中繪制從位圖圖形上下文創建的圖像。
  • 2)將邊界框的原點設置為(0,0),將寬度和高度設置為先前聲明的變量,但其聲明未在此代碼中顯示。
  • 3)調用應用程序提供的函數MyCreateBitmapContext(參見Listing 2-5)以創建400像素寬和300像素高的位圖上下文。您可以使用適合您的應用程序的任何維度創建位圖圖形上下文。
  • 4)調用Quartz 2D函數繪制到位圖圖形上下文中。您可以使用適合您應用程序的繪圖代碼替換此代碼和接下來的四行代碼。
  • 5)從位圖圖形上下文創建Quartz 2D圖像(CGImageRef)
  • 6)將圖像繪制到由邊界框指定的窗口圖形上下文中的位置。邊界框指定用戶空間中繪制圖像的位置和尺寸。此示例未顯示窗口圖形上下文的創建。有關如何創建窗口圖形上下文的信息,請參閱Creating a Window Graphics Context in Mac OS X
  • 7)獲取與位圖圖形上下文關聯的位圖數據。
  • 8)在不再需要時釋放位圖圖形上下文。
  • 9)釋放位圖數據(如果存在)。
  • 10)不再需要時釋放圖像。
Figure 2-3 An image created from a bitmap graphics context and drawn to a window graphics context

1. Supported Pixel Formats - 支持像素格式

表2-1總結了位圖圖形上下文支持的像素格式,關聯的色彩空間(cs)以及格式首次可用的Mac OS X版本。 像素格式被指定為每像素位數(bpp)和每個分量位數(bpc)。 該表還包括與該像素格式相關聯的位圖信息常量。 有關每個位圖信息格式常量所代表的內容的詳細信息,請參閱 CGImage Reference

Table 2-1 Pixel formats supported for bitmap graphics contexts

2. Anti-Aliasing - 抗鋸齒

位圖圖形上下文支持抗鋸齒,這是人工校正在繪制文本或形狀時有時在位圖圖像中看到的鋸齒(或鋸齒)邊緣的過程。當位圖的分辨率明顯低于眼睛的分辨率時,會出現這些鋸齒狀邊緣。為了使對象在位圖中顯得平滑,Quartz對圍繞形狀輪廓的像素使用不同的顏色。通過以這種方式混合顏色,形狀顯得平滑。您可以在圖2-4中看到使用抗鋸齒的效果。您可以通過調用CGContextSetShouldAntialias函數來關閉特定位圖圖形上下文的消除鋸齒。抗鋸齒設置是圖形狀態的一部分。

您可以使用CGContextSetAllowsAntialiasing函數控制是否允許特定圖形上下文的抗鋸齒。傳遞給此函數true以允許消除鋸齒;傳遞false不允許它。此設置不是圖形狀態的一部分。當上下文和圖形狀態設置被設置為true時,Quartz會執行消除鋸齒。

Figure 2-4 A comparison of aliased and anti-aliasing drawing

Obtaining a Graphics Context for Printing - 獲取用于打印的圖形上下文

Mac OS X中的Cocoa應用程序通過自定義NSView子類實現打印。 通過調用print:方法告訴視圖進行打印。 然后,視圖創建一個以打印機為目標的圖形上下文,并調用其drawRect:方法。 您的應用程序使用與用于繪制到屏幕相同的繪圖代碼繪制到打印機。 它還可以自定義drawRect:調用打印機的圖像,該圖像與發送到屏幕的圖像不同。

有關在Cocoa中打印的詳細討論,請參閱Printing Programming Guide for Mac

后記

本篇主要講述了圖形上下文,感興趣的給個贊或者關注~~~

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

推薦閱讀更多精彩內容