iOS開發(fā)之循環(huán)引用常見場景

#頭文件

/*

File: LargeImageDownsizingViewController.h

Abstract: The primary view controller for this project.

Version: 1.1

Disclaimer: IMPORTANT:? This Apple software is supplied to you by Apple

Inc. ("Apple") in consideration of your agreement to the following

terms, and your use, installation, modification or redistribution of

this Apple software constitutes acceptance of these terms.? If you do

not agree with these terms, please do not use, install, modify or

redistribute this Apple software.

In consideration of your agreement to abide by the following terms, and

subject to these terms, Apple grants you a personal, non-exclusive

license, under Apple's copyrights in this original Apple software (the

"Apple Software"), to use, reproduce, modify and redistribute the Apple

Software, with or without modifications, in source and/or binary forms;

provided that if you redistribute the Apple Software in its entirety and

without modifications, you must retain this notice and the following

text and disclaimers in all such redistributions of the Apple Software.

Neither the name, trademarks, service marks or logos of Apple Inc. may

be used to endorse or promote products derived from the Apple Software

without specific prior written permission from Apple.? Except as

expressly stated in this notice, no other rights or licenses, express or

implied, are granted by Apple herein, including but not limited to any

patent rights that may be infringed by your derivative works or by other

works in which the Apple Software may be incorporated.

The Apple Software is provided by Apple on an "AS IS" basis.? APPLE

MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION

THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS

FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND

OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.

IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL

OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,

MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED

AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),

STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

Copyright (C) 2014 Apple Inc. All Rights Reserved.

*/

#import

@classImageScrollView;

@interfaceLargeImageDownsizingViewController :UIViewController{

// The input image file

UIImage* sourceImage;

// output image file

UIImage* destImage;

// sub rect of the input image bounds that represents the

// maximum amount of pixel data to load into mem at one time.

CGRectsourceTile;

// sub rect of the output image that is proportionate to the

// size of the sourceTile.

CGRectdestTile;

// the ratio of the size of the input image to the output image.

floatimageScale;

// source image width and height

CGSizesourceResolution;

// total number of pixels in the source image

floatsourceTotalPixels;

// total number of megabytes of uncompressed pixel data in the source image.

floatsourceTotalMB;

// output image width and height

CGSizedestResolution;

// the temporary container used to hold the resulting output image pixel

// data, as it is being assembled.

CGContextRefdestContext;

// the number of pixels to overlap tiles as they are assembled.

floatsourceSeemOverlap;

// an image view to visualize the image as it is being pieced together

UIImageView* progressView;

// a scroll view to display the resulting downsized image

ImageScrollView* scrollView;

}

// destImage property is specifically thread safe (i.e. no 'nonatomic' attribute)

// because it is accessed off the main thread.

@property(retain)UIImage* destImage;

-(void)downsize:(id)arg;

-(void)updateScrollView:(id)arg;

-(void)initializeScrollView:(id)arg;

-(void)createImageFromContext;

@end

源文件

/*

File: LargeImageDownsizingViewController.m

Abstract: The primary view controller for this project.

Version: 1.1

Disclaimer: IMPORTANT:? This Apple software is supplied to you by Apple

Inc. ("Apple") in consideration of your agreement to the following

terms, and your use, installation, modification or redistribution of

this Apple software constitutes acceptance of these terms.? If you do

not agree with these terms, please do not use, install, modify or

redistribute this Apple software.

In consideration of your agreement to abide by the following terms, and

subject to these terms, Apple grants you a personal, non-exclusive

license, under Apple's copyrights in this original Apple software (the

"Apple Software"), to use, reproduce, modify and redistribute the Apple

Software, with or without modifications, in source and/or binary forms;

provided that if you redistribute the Apple Software in its entirety and

without modifications, you must retain this notice and the following

text and disclaimers in all such redistributions of the Apple Software.

Neither the name, trademarks, service marks or logos of Apple Inc. may

be used to endorse or promote products derived from the Apple Software

without specific prior written permission from Apple.? Except as

expressly stated in this notice, no other rights or licenses, express or

implied, are granted by Apple herein, including but not limited to any

patent rights that may be infringed by your derivative works or by other

works in which the Apple Software may be incorporated.

The Apple Software is provided by Apple on an "AS IS" basis.? APPLE

MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION

THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS

FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND

OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.

IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL

OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,

MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED

AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),

STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

Copyright (C) 2014 Apple Inc. All Rights Reserved.

*/

#import"LargeImageDownsizingViewController.h"

#import

#import"ImageScrollView.h"

/* Image Constants: for images, we define the resulting image

size and tile size in megabytes. This translates to an amount

of pixels. Keep in mind this is almost always significantly different

from the size of a file on disk for compressed formats such as png, or jpeg.

For an image to be displayed in iOS, it must first be uncompressed (decoded) from

disk. The approximate region of pixel data that is decoded from disk is defined by both,

the clipping rect set onto the current graphics context, and the content/image

offset relative to the current context.

To get the uncompressed file size of an image, use: Width x Height / pixelsPerMB, where

pixelsPerMB = 262144 pixels in a 32bit colospace (which iOS is optimized for).

Supported formats are: PNG, TIFF, JPEG. Unsupported formats: GIF, BMP, interlaced images.

*/

#define kImageFilename @"large_leaves_70mp.jpg"http:// 7033x10110 image, 271 MB uncompressed

/* The arguments to the downsizing routine are the resulting image size, and

"tile" size. And they are defined in terms of megabytes to simplify the correlation

between images and memory footprint available to your application.

The "tile" is the maximum amount of pixel data to load from the input image into

memory at one time. The size of the tile defines the number of iterations

required to piece together the resulting image.

Choose a resulting size for your image given both: the hardware profile of your

target devices, and the amount of memory taken by the rest of your application.

Maximizing the source image tile size will minimize the time required to complete

the downsize routine. Thus, performance must be balanced with resulting image quality.

Choosing appropriate resulting image size and tile size can be done, but is left as

an exercise to the developer. Note that the device type/version string

(e.g. "iPhone2,1" can be determined at runtime through use of the sysctlbyname function:

size_t size;

sysctlbyname("hw.machine", NULL, &size, NULL, 0);

char *machine = malloc(size);

sysctlbyname("hw.machine", machine, &size, NULL, 0);

NSString* _platform = [NSString stringWithCString:machine encoding:NSASCIIStringEncoding];

free(machine);

These constants are suggested initial values for iPad1, and iPhone 3GS */

#define IPAD1_IPHONE3GS

#ifdef IPAD1_IPHONE3GS

#? define kDestImageSizeMB60.0f// The resulting image will be (x)MB of uncompressed image data.

#? define kSourceImageTileSizeMB20.0f// The tile size will be (x)MB of uncompressed image data.

#endif

/* These constants are suggested initial values for iPad2, and iPhone 4 */

//#define IPAD2_IPHONE4

#ifdef IPAD2_IPHONE4

#? define kDestImageSizeMB120.0f// The resulting image will be (x)MB of uncompressed image data.

#? define kSourceImageTileSizeMB40.0f// The tile size will be (x)MB of uncompressed image data.

#endif

/* These constants are suggested initial values for iPhone3G, iPod2 and earlier devices */

//#define IPHONE3G_IPOD2_AND_EARLIER

#ifdef IPHONE3G_IPOD2_AND_EARLIER

#? define kDestImageSizeMB30.0f// The resulting image will be (x)MB of uncompressed image data.

#? define kSourceImageTileSizeMB10.0f// The tile size will be (x)MB of uncompressed image data.

#endif

/* Constants for all other iOS devices are left to be defined by the developer.

The purpose of this sample is to illustrate that device specific constants can

and should be created by you the developer, versus iterating a complete list. */

#define bytesPerMB1048576.0f

#define bytesPerPixel4.0f

#define pixelsPerMB ( bytesPerMB / bytesPerPixel )// 262144 pixels, for 4 bytes per pixel.

#define destTotalPixels kDestImageSizeMB * pixelsPerMB

#define tileTotalPixels kSourceImageTileSizeMB * pixelsPerMB

#define destSeemOverlap2.0f// the numbers of pixels to overlap the seems where tiles meet.

@implementationLargeImageDownsizingViewController

@synthesizedestImage;

// release ownership

- (void)dealloc {

[destImagerelease];

[scrollViewrelease];

//--

[superdealloc];

}

- (void)didReceiveMemoryWarning {

// Releases the view if it doesn't have a superview.

[superdidReceiveMemoryWarning];

// Release any cached data, images, etc that aren't in use.

}

#pragma mark - View lifecycle

/*

-(void)loadView {

}*/

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad {

[superviewDidLoad];

//--

progressView= [[UIImageViewalloc]initWithFrame:self.view.bounds];

[self.viewaddSubview:progressView];

[progressViewrelease];

[NSThreaddetachNewThreadSelector:@selector(downsize:)toTarget:selfwithObject:nil];

}

- (void)viewDidUnload {

[superviewDidUnload];

// Release any retained subviews of the main view.

// e.g. self.myOutlet = nil;

}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

// Return YES for supported orientations

return(interfaceOrientation ==UIInterfaceOrientationPortrait);

}

-(void)downsize:(id)arg {

// create an autorelease pool to catch calls to -autorelease.

NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc]init];

// create an image from the image filename constant. Note this

// doesn't actually read any pixel information from disk, as that

// is actually done at draw time.

sourceImage= [[UIImagealloc]initWithContentsOfFile:[[NSBundlemainBundle]pathForResource:kImageFilenameofType:nil]];

if(sourceImage==nil)NSLog(@"input image not found!");

// get the width and height of the input image using

// core graphics image helper functions.

sourceResolution.width=CGImageGetWidth(sourceImage.CGImage);

sourceResolution.height=CGImageGetHeight(sourceImage.CGImage);

// use the width and height to calculate the total number of pixels

// in the input image.

sourceTotalPixels=sourceResolution.width*sourceResolution.height;

// calculate the number of MB that would be required to store

// this image uncompressed in memory.

sourceTotalMB=sourceTotalPixels/pixelsPerMB;

// determine the scale ratio to apply to the input image

// that results in an output image of the defined size.

// see kDestImageSizeMB, and how it relates to destTotalPixels.

imageScale=destTotalPixels/sourceTotalPixels;

// use the image scale to calcualte the output image width, height

destResolution.width= (int)(sourceResolution.width*imageScale);

destResolution.height= (int)(sourceResolution.height*imageScale);

// create an offscreen bitmap context that will hold the output image

// pixel data, as it becomes available by the downscaling routine.

// use the RGB colorspace as this is the colorspace iOS GPU is optimized for.

CGColorSpaceRefcolorSpace =CGColorSpaceCreateDeviceRGB();

intbytesPerRow =bytesPerPixel*destResolution.width;

// allocate enough pixel data to hold the output image.

void* destBitmapData =malloc( bytesPerRow *destResolution.height);

if( destBitmapData ==NULL)NSLog(@"failed to allocate space for the output image!");

// create the output bitmap context

destContext=CGBitmapContextCreate( destBitmapData,destResolution.width,destResolution.height, 8, bytesPerRow, colorSpace,kCGImageAlphaPremultipliedLast);

// remember CFTypes assign/check for NULL. NSObjects assign/check for nil.

if(destContext==NULL) {

free( destBitmapData );

NSLog(@"failed to create the output bitmap context!");

}

// release the color space object as its job is done

CGColorSpaceRelease( colorSpace );

// flip the output graphics context so that it aligns with the

// cocoa style orientation of the input document. this is needed

// because we used cocoa's UIImage -imageNamed to open the input file.

CGContextTranslateCTM(destContext, 0.0f,destResolution.height);

CGContextScaleCTM(destContext, 1.0f, -1.0f );

// now define the size of the rectangle to be used for the

// incremental blits from the input image to the output image.

// we use a source tile width equal to the width of the source

// image due to the way that iOS retrieves image data from disk.

// iOS must decode an image from disk in full width 'bands', even

// if current graphics context is clipped to a subrect within that

// band. Therefore we fully utilize all of the pixel data that results

// from a decoding opertion by achnoring our tile size to the full

// width of the input image.

sourceTile.size.width=sourceResolution.width;

// the source tile height is dynamic. Since we specified the size

// of the source tile in MB, see how many rows of pixels high it

// can be given the input image width.

sourceTile.size.height= (int)(tileTotalPixels/sourceTile.size.width);

NSLog(@"source tile size: %f x %f",sourceTile.size.width,sourceTile.size.height);

sourceTile.origin.x= 0.0f;

// the output tile is the same proportions as the input tile, but

// scaled to image scale.

destTile.size.width=destResolution.width;

destTile.size.height=sourceTile.size.height*imageScale;

destTile.origin.x= 0.0f;

NSLog(@"dest tile size: %f x %f",destTile.size.width,destTile.size.height);

// the source seem overlap is proportionate to the destination seem overlap.

// this is the amount of pixels to overlap each tile as we assemble the ouput image.

sourceSeemOverlap= (int)( (destSeemOverlap/destResolution.height) *sourceResolution.height);

NSLog(@"dest seem overlap: %f, source seem overlap: %f",destSeemOverlap,sourceSeemOverlap);

CGImageRefsourceTileImageRef;

// calculate the number of read/write opertions required to assemble the

// output image.

intiterations = (int)(sourceResolution.height/sourceTile.size.height);

// if tile height doesn't divide the image height evenly, add another iteration

// to account for the remaining pixels.

intremainder = (int)sourceResolution.height% (int)sourceTile.size.height;

if( remainder ) iterations++;

// add seem overlaps to the tiles, but save the original tile height for y coordinate calculations.

floatsourceTileHeightMinusOverlap =sourceTile.size.height;

sourceTile.size.height+=sourceSeemOverlap;

destTile.size.height+=destSeemOverlap;

NSLog(@"beginning downsize. iterations: %d, tile height: %f, remainder height: %d", iterations,sourceTile.size.height,remainder );

for(inty = 0; y < iterations; ++y ) {

// create an autorelease pool to catch calls to -autorelease made within the downsize loop.

NSAutoreleasePool* pool2 = [[NSAutoreleasePoolalloc]init];

NSLog(@"iteration %d of %d",y+1,iterations);

sourceTile.origin.y= y * sourceTileHeightMinusOverlap +sourceSeemOverlap;

destTile.origin.y= (destResolution.height) - ( ( y + 1 ) * sourceTileHeightMinusOverlap *imageScale+destSeemOverlap);

// create a reference to the source image with its context clipped to the argument rect.

sourceTileImageRef =CGImageCreateWithImageInRect(sourceImage.CGImage,sourceTile);

// if this is the last tile, it's size may be smaller than the source tile height.

// adjust the dest tile size to account for that difference.

if( y == iterations - 1 && remainder ) {

floatdify =destTile.size.height;

destTile.size.height=CGImageGetHeight( sourceTileImageRef ) *imageScale;

dify -=destTile.size.height;

destTile.origin.y+= dify;

}

// read and write a tile sized portion of pixels from the input image to the output image.

CGContextDrawImage(destContext,destTile, sourceTileImageRef );

/* release the source tile portion pixel data. note,

releasing the sourceTileImageRef doesn't actually release the tile portion pixel

data that we just drew, but the call afterward does. */

CGImageRelease( sourceTileImageRef );

/* while CGImageCreateWithImageInRect lazily loads just the image data defined by the argument rect,

that data is finally decoded from disk to mem when CGContextDrawImage is called. sourceTileImageRef

maintains internally a reference to the original image, and that original image both, houses and

caches that portion of decoded mem. Thus the following call to release the source image. */

[sourceImagerelease];

// free all objects that were sent -autorelease within the scope of this loop.

[pool2drain];

// we reallocate the source image after the pool is drained since UIImage -imageNamed

// returns us an autoreleased object.

if( y < iterations - 1 ) {

sourceImage= [[UIImagealloc]initWithContentsOfFile:[[NSBundlemainBundle]pathForResource:kImageFilenameofType:nil]];

[selfperformSelectorOnMainThread:@selector(updateScrollView:)withObject:nilwaitUntilDone:YES];

}

}

NSLog(@"downsize complete.");

[selfperformSelectorOnMainThread:@selector(initializeScrollView:)withObject:nilwaitUntilDone:YES];

// free the context since its job is done. destImageRef retains the pixel data now.

CGContextRelease(destContext);

[pooldrain];

}

-(void)createImageFromContext {

// create a CGImage from the offscreen image context

CGImageRefdestImageRef =CGBitmapContextCreateImage(destContext);

if( destImageRef ==NULL)NSLog(@"destImageRef is null.");

// wrap a UIImage around the CGImage

self.destImage= [UIImageimageWithCGImage:destImageRefscale:1.0forientation:UIImageOrientationDownMirrored];

// release ownership of the CGImage, since destImage retains ownership of the object now.

CGImageRelease( destImageRef );

if(destImage==nil)NSLog(@"destImage is nil.");

}

-(void)updateScrollView:(id)arg {

[selfcreateImageFromContext];

// display the output image on the screen.

progressView.image=destImage;

}

-(void)initializeScrollView:(id)arg {

[progressViewremoveFromSuperview];

[selfcreateImageFromContext];

// create a scroll view to display the resulting image.

scrollView= [[ImageScrollViewalloc]initWithFrame:self.view.boundsimage:self.destImage];

[self.viewaddSubview:scrollView];

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末当叭,一起剝皮案震驚了整個濱河市姐直,隨后出現(xiàn)的幾起案子躏率,更是在濱河造成了極大的恐慌聪全,老刑警劉巖呻纹,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異站欺,居然都是意外死亡迎瞧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門吴旋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來损肛,“玉大人,你說我怎么就攤上這事荣瑟≈文茫” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵笆焰,是天一觀的道長劫谅。 經(jīng)常有香客問我,道長嚷掠,這世上最難降的妖魔是什么捏检? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮不皆,結(jié)果婚禮上贯城,老公的妹妹穿的比我還像新娘。我一直安慰自己霹娄,他們只是感情好能犯,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著犬耻,像睡著了一般踩晶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枕磁,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天渡蜻,我揣著相機(jī)與錄音,去河邊找鬼透典。 笑死晴楔,一個胖子當(dāng)著我的面吹牛顿苇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播税弃,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼纪岁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了则果?” 一聲冷哼從身側(cè)響起幔翰,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎西壮,沒想到半個月后遗增,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡款青,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年做修,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抡草。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡饰及,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出康震,到底是詐尸還是另有隱情燎含,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布腿短,位于F島的核電站屏箍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏橘忱。R本人自食惡果不足惜赴魁,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鹦付。 院中可真熱鬧尚粘,春花似錦、人聲如沸敲长。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祈噪。三九已至泽铛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辑鲤,已是汗流浹背盔腔。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人弛随。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓瓢喉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舀透。 傳聞我的和親對象是個殘疾皇子栓票,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

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