objective c - How do I access and manipulate JPEG image pixels? -
i have jpg file. need convert pixel data , change color of pixel. this:
nsstring *string = [[nsbundle mainbundle] pathforresource:@"pic" oftype:@"jpg"]; nsdata *data = [nsdata datawithcontentsoffile:string]; unsigned char *bytesarray = datai.bytes; nsuinteger byteslenght = data.length; //--------pixel array nsmutablearray *array = [[nsmutablearray alloc] initwithcapacity:byteslenght]; (int = 0; i<byteslenght; i++) { [array addobject:[nsnumber numberwithunsignedchar:bytesarray[i]]]; }
here try change color of pixels since 95 till 154.
nsnumber *number = [nsnumber numberwithint:200]; (int i=95; i<155; i++) { [array replaceobjectatindex:i withobject:number]; }
but when convert array image got blurred picture. don't understand why don't have influence on pixels , why have influence on picture in total?
the process of accessing pixel-level data little more complicated question might suggest, because, martin pointed out, jpeg can compressed image format. apple discusses approved technique getting pixel data in technical q&a qa1509.
bottom line, uncompressed pixel data uiimage
, would:
get
cgimage
uiimage
.get data provider
cgimageref
viacgimagegetdataprovider
.get binary data associated data provider via
cgdataprovidercopydata
.extract of information image, know how interpret buffer.
thus:
uiimage *image = ... cgimageref imageref = image.cgimage; // cgimageref nsassert(imageref, @"unable cgimageref"); cgdataproviderref provider = cgimagegetdataprovider(imageref); // data provider nsassert(provider, @"unable provider"); nsdata *data = cfbridgingrelease(cgdataprovidercopydata(provider)); // copy of data nsassert(data, @"unable copy image data"); nsinteger bitspercomponent = cgimagegetbitspercomponent(imageref); // other interesting details image nsinteger bitspercomponent = cgimagegetbitspercomponent(imageref); nsinteger bitsperpixel = cgimagegetbitsperpixel(imageref); cgbitmapinfo bitmapinfo = cgimagegetbitmapinfo(imageref); nsinteger bytesperrow = cgimagegetbytesperrow(imageref); nsinteger width = cgimagegetwidth(imageref); nsinteger height = cgimagegetheight(imageref); cgcolorspaceref colorspace = cgimagegetcolorspace(imageref);
given want manipulate this, presumably want mutable pixel buffer. easiest approach make mutablecopy
of nsdata
object , manipulate there, in these cases, tend fall c, creating void *outputbuffer
, copy original pixels , manipulate using traditional c array techniques.
to create buffer:
void *outputbuffer = malloc(width * height * bitsperpixel / 8); nsassert(outputbuffer, @"unable allocate buffer");
for precise details on how manipulate it, have @ bitmapinfo
(which tell whether it's rgba or argb; whether it's floating point or integer) , bitspercomponent
(which tell whether it's 8 or 16 bits per component, etc.). example, common jpeg format 8 bits per component, 4 components, rgba (i.e. red, green, blue, , alpha, in order). need check various properties extracted cgimageref
make sure. see discussion in quartz 2d programming guide - bitmap images , image masks more information. find "figure 11-2" illuminating.
the next logical question when you're done manipulating pixel data, how create uiimage
that. in short, you'd reverse above process, e.g. create data provider, create cgimageref
, , create uiimage
:
cgdataproviderref outputprovider = cgdataprovidercreatewithdata(null, outputbuffer, sizeof(outputbuffer), releasedata); cgimageref outputimageref = cgimagecreate(width, height, bitspercomponent, bitsperpixel, bytesperrow, colorspace, bitmapinfo, outputprovider, null, no, kcgrenderingintentdefault); uiimage *outputimage = [uiimage imagewithcgimage:outputimageref]; cgimagerelease(outputimageref); cgdataproviderrelease(outputprovider);
where releasedata
c function calls free
pixel buffer associated data provider:
void releasedata(void *info, const void *data, size_t size) { free((void *)data); }
Comments
Post a Comment