Quartz 2D编程指南 (十三) —— 位图图像和图像蒙版(一)

版本记录

版本号 时间
V1.0 2018.09.06

前言

Quartz 2D框架相信大家都知道,也都一直在使用。Quartz 2D的API是纯C语言的,它是一个二维绘图引擎,同时支持iOS和Mac系统。Quartz 2D的API来自于Core Graphics框架,数据类型和函数基本都以CG作为前缀,接下来几篇我们就一起来看一下这个框架。感兴趣可以看上面几篇文章。
1. Quartz 2D编程指南 (一) —— 简介(一)
2. Quartz 2D编程指南 (二) —— Quartz 2D概览(二)
3. Quartz 2D编程指南 (三) —— 图形上下文(三)
4. Quartz 2D编程指南 (四) —— Paths路径(一)
5. Quartz 2D编程指南 (五) —— Paths路径(二)
6. Quartz 2D编程指南 (六) —— 颜色和颜色空间(一)
7. Quartz 2D编程指南 (七) —— 变换(一)
8. Quartz 2D编程指南 (八) —— Patterns图案样式(一)
9. Quartz 2D编程指南 (九) —— 阴影(一)
10. Quartz 2D编程指南 (十) —— 渐变(一)
11. Quartz 2D编程指南 (十一) —— 透明层(一)
12. Quartz 2D编程指南 (十二) —— Quartz 2D中的数据管理(一)

Bitmap Images and Image Masks - 位图图像和图像蒙版

位图图像和图像蒙版就像Quartz中的任何绘图基元一样。 Quartz中的图像和图像蒙版都由CGImageRef数据类型表示。正如您将在本章后面看到的,您可以使用各种功能来创建图像。其中一些需要数据提供者或图像源来提供位图数据。其他函数通过复制图像或对图像应用操作从现有图像创建图像。无论您如何在Quartz中创建位图图像,您都可以将图像绘制到任何形式的图形上下文中。请记住,位图图像是特定分辨率的位数组。如果将位图图像绘制为与分辨率无关的图形上下文(例如PDF图形上下文),则位图会受到创建它的分辨率的限制。

有一种方法可以通过调用函数CGImageMaskCreate来创建Quartz图像蒙版。您将看到如何在 Creating an Image Mask中创建一个。应用图像蒙版不是蒙层绘制的唯一方法。Masking an Image with ColorMasking an Image with an Image Mask以及Masking an Image by Clipping the Context的部分讨论了Quartz中可用的所有蒙层方法。


About Bitmap Images and Image Masks - 关于位图图像和图像蒙版

位图图像(或采样图像)是像素(或样本)的阵列。 每个像素代表图像中的单个点。 JPEG,TIFF和PNG图形文件是位图图像的示例。 应用程序图标是位图图像。 位图图像仅限于矩形。 但是通过使用alpha组件,它们可以呈现各种形状,可以旋转和剪裁,如图11-1所示。

Figure 11-1 Bitmap images

位图中的每个样本都包含指定颜色空间中的一个或多个颜色分量,以及一个指定alpha值以指示透明度的附加组件。 每个组件可以从1到多达32位。 在Mac OS X中,Quartz还提供对浮点组件的支持。 Mac OS X和iOS中支持的格式在“Pixel formats supported for bitmap graphics contexts”中描述。 ColorSync为位图图像提供色彩空间支持。

Quartz还支持图像蒙版image masks。 图像蒙版是一个位图,用于指定要绘制的区域,但不指定颜色。 实际上,图像蒙版充当模板以指定在页面上放置颜色的位置。 Quartz使用当前填充颜色来绘制图像蒙版。 图像蒙版可以具有1到8位的深度。


Bitmap Image Information - 位图图像信息

Quartz支持各种图像格式,并具有几种流行格式的内置知识。 在iOS中,格式包括JPEG,GIF,PNG,TIF,ICO,GMP,XBM和CUR。 其他位图图像格式或专有格式要求您向Quartz指定有关图像格式的详细信息,以确保正确解释图像。 您提供给函数CGImageCreate的图像数据必须基于每个像素而不是每个扫描行进行交错。 Quartz不支持平面数据。

本节介绍与位图图像关联的信息。 当您创建和使用Quartz图像(使用CGImageRef数据类型)时,您会看到一些Quartz图像创建函数要求您指定所有这些信息,而其他函数需要此信息的子集。 您提供的内容取决于用于位图数据的编码,以及位图是表示图像还是图像蒙版。

注意:为了在处理原始图像数据时获得最佳性能,请使用vImage框架。 您可以使用vImageBuffer_InitWithCGImage函数从CGImageRef引用将图像数据导入vImage。 有关详细信息,请参阅Accelerate Release Notes

Quartz在创建位图图像(CGImageRef)时使用以下信息:

  • 1) 位图数据源,可以是Quartz数据提供程序或Quartz图像源。 Data Management in Quartz 2D描述了两者并讨论了提供位图数据源的函数。
  • 2) 可选的解码阵列(Decode Array)。
  • 3) 插值设置,是一个布尔值,指定Quartz在调整图像大小时是否应该应用插值算法。
  • 4) 一种渲染意图,指定如何映射位于图形上下文的目标颜色空间内的颜色。图像蒙版不需要此信息。有关更多信息,请参见Setting Rendering Intent
  • 5) 图像尺寸。
  • 6) 像素格式,包括每个分量的位数,每像素的位数和每行的字节数(Pixel Format)。
  • 7) 对于图像,颜色空间和位图布局(Color Spaces and Bitmap Layout)信息,用于描述alpha的位置以及位图是否使用浮点值。图像蒙版不需要此信息。

1. Decode Array

解码阵列将图像颜色值映射到其他颜色值,这对于去饱和图像或反转颜色等任务非常有用。 该数组包含每个颜色分量的一对数字。 当Quartz渲染图像时,它应用线性变换将原始组件值映射到适合目标颜色空间的指定范围内的相对数字。 例如,RGB颜色空间中的图像的解码阵列包含六个条目,每个红色,绿色和蓝色分量一对。

2. Pixel Format - 像素格式

像素格式包含以下信息:

  • 1)每个组件的位数,即像素中每个单独颜色分量中的位数。 对于图像掩码,该值是源像素中的重要掩蔽位的数量。 例如,如果源图像是8位掩码,则为每个组件指定8位。
  • 2)每像素位数,即源像素中的总位数。 该值必须至少为每个组件的位数乘以每个像素的组件数。
  • 3)每行字节数。 图像中每个水平行的字节数。

3. Color Spaces and Bitmap Layout - 颜色空间和位图布局

为确保Quartz正确解释每个像素的位,您必须指定:

  • 位图是否包含Alpha通道。 Quartz支持RGB,CMYK和灰色空间。它还支持alpha或透明度,但alpha信息并非在所有位图图像格式中都可用。当它可用时,alpha分量可以位于像素的最高有效位或最低有效位。
  • 对于具有alpha分量的位图,颜色分量是否已经乘以alpha值。预乘alpha(Premultiplied alpha)描述了一种源颜色,其组件已经乘以alpha值。预乘通过消除每个颜色分量的额外乘法运算来加速图像的渲染。例如,在RGB颜色空间中,渲染具有预乘alpha的图像消除了图像中每个像素的三个乘法运算(红色乘以alpha,绿色乘以alpha和蓝色乘以alpha)。
  • 采样的数据格式 - 整数或浮点值。

使用CGImageCreate函数创建图像时,提供CGImageBitmapInfo类型的bitmapInfo参数以指定位图布局信息。以下常量指定alpha分量的位置以及颜色分量是否预乘:

  • kCGImageAlphaLast - alpha分量存储在每个像素的最低有效位中,例如RGBA。
  • kCGImageAlphaFirst - alpha分量存储在每个像素的最高有效位中,例如ARGB。
  • kCGImageAlphaPremultipliedLast - alpha分量存储在每个像素的最低有效位中,颜色分量已经乘以此alpha值。
  • kCGImageAlphaPremultipliedFirst - alpha分量存储在每个像素的最高有效位中,颜色分量已经乘以此alpha值。
  • kCGImageAlphaNoneSkipLast - 没有alpha分量。如果像素的总大小大于颜色空间中的颜色分量的数量所需的空间,则忽略最低有效位。
  • kCGImageAlphaNoneSkipFirst - 没有alpha组件。如果像素的总大小大于颜色空间中颜色分量的数量所需的空间,则忽略最高有效位。
  • kCGImageAlphaNone - 相当于kCGImageAlphaNoneSkipLast

使用常量kCGBitmapFloatComponents指示使用浮点值的位图格式。 对于浮点格式,您可以使用上一个列表中的相应常量对此常量进行逻辑OR运算。 例如,对于使用预乘alpha的128位/像素浮点格式,alpha位于每个像素的最低有效位,您可以向Quartz提供以下信息:

kCGImageAlphaPremultipliedLast| kCGBitmapFloatComponents

图11-2直观地描述了在使用16位或32位整数格式的CMYK和RGB颜色空间中如何表示像素。 32位整数像素格式每个组件使用8位。 16位整数格式每个组件使用5位。 Quartz 2D还支持128位浮点像素格式,每个组件使用32位。 128位格式未在图中显示。

Figure 11-2 32-bit and 16-bit pixel formats for CMYK and RGB color spaces in Quartz 2D

Creating Images - 创建图像

表11-1列出了Quartz提供的用于创建CGImage对象的函数。图像创建函数的选择取决于图像数据的来源。最灵活的函数是CGImageCreate。它从任何类型的位图数据创建图像。但是,它是最复杂的函数,因为您必须指定所有位图信息。要使用此函数,您需要熟悉Bitmap Image Information中讨论的主题。

如果要从使用标准图像格式(如PNG或JPEG)的图像文件创建CGImage对象,最简单的解决方案是调用函数CGImageSourceCreateWithURL来创建图像源,然后调用函数CGImageSourceCreateImageAtIndex从图像源中特定索引处的图像数据来创建图像。如果原始图像文件仅包含一个图像,则提供0作为索引。如果图像文件格式支持包含多个图像的文件,则需要将索引提供给适当的图像,同时请记住索引值从0开始。

如果您已将内容绘制到位图图形上下文并想要将该绘图捕获到CGImage对象,请调用函数CGBitmapContextCreateImage

有几个函数是对现有图像进行操作的实用程序,可以进行复制,创建缩略图,也可以从较大图像的一部分创建图像。无论您如何创建CGImage对象,都可以使用CGContextDrawImage函数将图像绘制到图形上下文中。请记住,CGImage对象是不可变的。当您不再需要CGImage对象时,通过调用函数CGImageRelease释放它。

Table 11-1 Functions for creating images

以下部分讨论如何创建:

  • 来自现有图像的子图像
  • 来自位图图形上下文的图像

您可以查阅这些来源以获取更多信息:

1. Creating an Image From Part of a Larger Image - 从较大图像的一部分创建图像

函数CGImageCreateWithImageInRect允许您从现有的Quartz图像创建子图像。 图11-3说明了通过提供指定字母“A”位置的矩形从较大的图像中提取包含字母“A”的图像。

Figure 11-3 A subimage created from a larger image

函数CGImageCreateWithImageInRect返回的图像保留对原始图像的引用,这意味着您可以在调用此函数后释放原始图像。

Figure 11-4显示了提取图像的一部分以创建另一个图像的另一个示例。在这种情况下,从较大的图像中提取公鸡的头部,然后绘制到比子图像大的矩形,有效地放大图像。

Listing 11-1显示了创建然后绘制子图像的代码。函数CGContextDrawImage绘制公鸡头部的矩形的尺寸是提取的子图像尺寸的两倍。列表是一个代码片段。您需要声明适当的变量,创建公鸡图像,并处理公鸡图像和公鸡头子图像。因为代码是片段,所以它没有显示如何创建绘制图像的图形上下文。您可以使用任何您喜欢的图形上下文。有关如何创建图形上下文的示例,请参阅Graphics Contexts

Figure 11-4 An image, a subimage taken from it and drawn so it’s enlarged
// Listing 11-1  Code that creates a subimage and draws it enlarged

myImageArea = CGRectMake (rooster_head_x_origin, rooster_head_y_origin,
                            myWidth, myHeight);
mySubimage = CGImageCreateWithImageInRect (myRoosterImage, myImageArea);
myRect = CGRectMake(0, 0, myWidth*2, myHeight*2);
CGContextDrawImage(context, myRect, mySubimage);

2. Creating an Image from a Bitmap Graphics Context - 从位图图形上下文创建图像

要从现有位图图形上下文创建图像,请按如下方式调用函数CGBitmapContextCreateImage

CGImageRef myImage;
myImage = CGBitmapContextCreateImage(myBitmapContext);

函数返回的CGImage对象由复制操作创建。 因此,您对位图图形上下文所做的任何后续更改都不会影响返回的CGImage对象的内容。 在某些情况下,复制操作实际上遵循写时复制语义,因此只有在位图图形上下文中的基础数据被修改时才会发生位的实际物理复制。 在对位图图形上下文执行其他绘制之前,您可能希望使用生成的图像并将其释放,以便您可以避免数据的实际物理副本。

有关如何创建位图图形上下文的示例,请参阅Creating a Bitmap Graphics Context


Creating an Image Mask - 创建图像蒙版

Quartz位图图像蒙版的使用方式与艺术家使用丝网印刷的方式相同。位图图像蒙版确定如何传输颜色,而不是使用哪种颜色。图像蒙版中的每个样本值指定在特定位置屏蔽当前填充颜色的量。样本值指定蒙版的不透明度。较大的值表示较大的不透明度,并指定Quartz绘制较少颜色的位置。您可以将样本值视为反alpha值。值1是透明的,0是不透明的。

图像掩码是每个组件1,2,4或8位。对于1位掩码,样本值1指定阻止当前填充颜色的掩码部分。样本值0指定蒙版的各个部分,这些部分显示绘制蒙版时图形状态的当前填充颜色。您可以将1位掩码视为黑白,采样要么完全阻挡绘制,要么完全允许绘制。

每个组件具有2,4或8位的图像掩码表示灰度值。使用以下公式将每个组件映射到0到1的范围:

例如,4位掩码的值范围为0到1,增量为1/15。 0或1的组件值表示极端 - 完全阻挡绘制和完全允许绘制。 介于0和1之间的值允许使用公式1 - MaskSampleValue进行部分绘制。 例如,如果8位掩码的样本值缩放为0.7,则将颜色绘制为具有alpha值(1 - 0.7)的0.3,即0.3。

函数CGImageMaskCreate根据您提供的位图图像信息创建Quartz图像蒙版,这在Bitmap Image Information中进行了讨论。 您提供的用于创建图像蒙版的信息与您创建图像时提供的信息相同,只是您不提供颜色空间信息,位图信息常量或渲染意图,您可以通过查看函数看到Listing 11-2中的原型。

// Listing 11-2  The prototype for the function CGImageMaskCreate

CGImageRef CGImageMaskCreate (
        size_t width,
        size_t height,
        size_t bitsPerComponent,
        size_t bitsPerPixel,
        size_t bytesPerRow,
        CGDataProviderRef provider,
        const CGFloat decode[],
        bool shouldInterpolate
);

Masking Images - 蒙层图像

蒙层技术可以通过控制图像的哪些部分被绘制来产生许多有趣的效果。 您可以:

  • 1) 将图像蒙版应用于图像。 您还可以使用图像作为蒙版来实现与应用图像蒙版相反的效果。
  • 2) 使用颜色屏蔽图像的某些部分,其中包括称为色度键屏蔽的技术(chroma key masking)
  • 3) 将图形上下文剪辑到图像或图像蒙版,当Quartz将内容绘制到剪切的上下文时,它有效地屏蔽图像(或任何类型的图形)。

1. Masking an Image with an Image Mask - 使用图像蒙版屏蔽图像

函数CGImageCreateWithMask返回通过将图像蒙版应用于图像而创建的图像。该函数有两个参数:

  • 要将蒙版应用到的图像。此图像不能是图像蒙版,也不能具有与其关联的蒙版颜色(请参见Masking an Image with Color)。
  • 通过调用函数CGImageMaskCreate创建的图像掩码。可以提供图像而不是图像蒙版,但这会产生截然不同的结果。请参阅Masking an Image with an Image

图像掩模的源样本用作反alpha值。图像掩码样本值(S):

  • 等于1阻止绘制相应的图像样本。
  • 等于0允许在完全覆盖范围内绘制相应的图像样本。
  • 大于0且小于1允许使用alpha值(1-S)绘制相应的图像样本。

图11-5显示了使用Quartz图像创建函数之一创建的图像,图11-6显示了使用CGImageMaskCreate函数创建的图像蒙版。图11-7显示了调用函数CGImageCreateWithMask将图像蒙版应用于图像所产生的图像。

Figure 11-5 The original image
Figure 11-6 An image mask

请注意,原始图像中与蒙版黑色区域对应的区域显示在结果图像中(图11-7)。 与蒙版中白色区域对应的区域未涂色。 与蒙版中的灰色区域对应的区域使用等于1减去图像掩模样本值的中间alpha值绘制。

Figure 11-7 The image that results from applying the image mask to the original image

2. Masking an Image with an Image - 用图像掩盖图像

您可以使用CGImageCreateWithMask函数用另一个图像来屏蔽图像,而不是使用图像蒙版。 您可以这样做以获得与使用图像蒙版遮罩图像时所获得的效果相反的效果。 您可以提供从其中一个Quartz图像创建函数创建的图像,而不是传递使用CGImageMaskCreate函数创建的图像蒙版。

用作掩模(但不是Quartz图像掩模)的图像的源样本作为alpha值运行。 图像样本值(S)

  • 等于1允许在完全覆盖范围内绘制相应的图像样本。
  • 等于0阻止绘制相应的图像样本。
  • 大于0且小于1允许使用alphaS绘制相应的图像样本。

Figure 11-8显示了调用函数CGImageCreateWithMaskFigure 11-6所示的图像应用于图11-5所示的图像所产生的图像。 在这种情况下,假设图11-6中所示的图像是使用Quartz图像创建函数之一创建的,例如CGImageCreate。 将图11-8与图11-7进行比较,了解相同的样本值在用作图像样本而不是图像蒙版样本时如何实现相反的效果。

原始图像中与图像黑色区域对应的区域未在结果图像中绘制(图11-8)。 对应于白色区域的区域被绘制。 与掩模中的灰色区域对应的区域使用等于掩蔽图像样本值的中间alpha值绘制。

Figure 11-8 The image that results from masking the original image with an image

3. Masking an Image with Color - 用颜色掩盖图像

函数CGImageCreateWithMaskingColors通过屏蔽提供给函数的图像中的一种颜色或一系列颜色来创建图像。 使用此功能,您可以执行类似于Figure 11-9所示的色度键屏蔽(chroma key masking),或者可以屏蔽一系列颜色,类似于Figure 11-11Figure 11-12Figure 11-13中所示。

函数CGImageCreateWithMaskingColors有两个参数:

  • 不是图像蒙版的图像,不是将图像蒙版或蒙版颜色应用于其他图像的结果。
  • 一组颜色组件,用于指定要在图像中屏蔽的函数的颜色或颜色范围。
Figure 11-9 Chroma key masking

颜色分量数组中的元素数必须等于图像颜色空间中颜色分量数的两倍。对于颜色空间中的每个颜色分量,提供指定要遮罩的颜色范围的最小值和最大值。要仅遮罩一种颜色,请将最小值设置为最大值。颜色组件数组中的值按以下顺序提供:

{min [1],max [1],... min [N],max [N]},其中N是分量数。

如果图像使用整数像素分量,则颜色分量数组中的每个值必须在[0 .. 2 ^ bitsPerComponent - 1]范围内。如果图像使用浮点像素分量,则每个值可以是作为有效颜色分量的任何浮点数。

如果图像样本的颜色值落在以下范围内,则不会绘制图像样本:

{c [1],... c [N]}

其中min [i] <= c [i] <= max [i]为1 <= i <= N.

未绘制样品下面的任何东西,例如当前填充颜色或其他绘图,都会显示出来。

如图11-10所示,两只老虎的图像使用RGB颜色空间,每个分量有8位。要屏蔽此图像中的一系列颜色,请提供0到255范围内的最小和最大颜色分量值。

Figure 11-10 The original image

LIsting 11-3显示了一个代码片段,它设置了一个颜色组件数组,并将该数组提供给函数CGImageCreateWithMaskingColors,以实现如图11-11所示的结果。

// Listing 11-3  Masking light to mid-range brown colors in an image

CGImageRef myColorMaskedImage;
const CGFloat myMaskingColors[6] = {124, 255,  68, 222, 0, 165};
myColorMaskedImage = CGImageCreateWithMaskingColors (image,
                                        myMaskingColors);
CGContextDrawImage (context, myContextRect, myColorMaskedImage);
Figure 11-11 An image with light to midrange brown colors masked out

Listing 11-4显示了另一个代码片段,它对Figure 11-10所示的图像进行操作,得到如图11-12所示的结果。 此示例掩盖了较暗的颜色范围。

// Listing 11-4  Masking shades of brown to black

CGImageRef myMaskedImage;
const CGFloat myMaskingColors[6] = { 0, 124, 0, 68, 0, 0 };
myColorMaskedImage = CGImageCreateWithMaskingColors (image,
                                        myMaskingColors);
CGContextDrawImage (context, myContextRect, myColorMaskedImage);
Figure 11-12 A image after masking colors from dark brown to black

您可以屏蔽图像中的颜色以及设置填充颜色,以达到图11-13所示的效果,其中蒙版区域将替换为填充颜色。Listing 11-5显示了生成图11-13所示图像的代码片段。

// Listing 11-5  Masking a range of colors and setting a fill color and

CGImageRef myMaskedImage;
const CGFloat myMaskingColors[6] = { 0, 124, 0, 68, 0, 0 };
myColorMaskedImage = CGImageCreateWithMaskingColors (image,
                                        myMaskingColors);
CGContextSetRGBFillColor (myContext, 0.6373,0.6373, 0, 1);
CGContextFillRect(context, rect);
CGContextDrawImage(context, rect, myColorMaskedImage);
Figure 11-13 An image drawn after masking a range of colors and setting a fill colo

4. Masking an Image by Clipping the Context - 通过剪切上下文屏蔽图像

函数CGContextClipToMask将蒙版映射到矩形,并将其与图形上下文的当前剪切区域相交。您提供以下参数:

  • 要剪辑的图形上下文。
  • 要应用蒙版的矩形。
  • 通过调用函数CGImageMaskCreate创建的图像掩码。您可以提供图像而不是图像蒙版,以获得与提供图像蒙版所获得的效果相反的效果。必须使用Quartz图像创建函数创建图像,但不能将遮罩或遮罩颜色应用于其他图像。

生成的剪切区域取决于您是否向CGContextClipToMask函数提供图像蒙版或图像。如果提供图像蒙版,则会得到与Masking an Image with an Image Mask中描述的结果类似的结果,但图形上下文被剪裁除外。如果提供图像,则会截断图形上下文,类似于Masking an Image with an Image中所描述的内容。

看一下图11-14。假设它是通过调用函数CGImageMaskCreate创建的图像掩码,然后将掩码作为参数提供给函数CGContextClipToMask。生成的上下文允许绘制到黑色区域,不允许绘制到白色区域,并允许绘制到alpha值为1-S的灰色区域,其中S是图像蒙版的样本值。如果使用CGContextDrawImage函数将图像绘制到剪切的上下文中,您将得到类似于图11-15所示的结果。

Figure 11-14 A masking image
Figure 11-15 An image drawn to a context after clipping the content with an image mask

将屏蔽图像视为图像时,会得到相反的结果,如图11-16所示。

Figure 11-16 An image drawn to a context after clipping the content with an image

后记

本篇主要讲述了位图图像和图像蒙版,感兴趣的给个赞或者关注~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容