CGColorSpaceRef colorSpaceFromPDFArray(CGPDFArrayRef colorSpaceArray){ CGColorSpaceRef cgColorSpace = NULL, alternateColorSpace = NULL; CGPDFStreamRef stream; const char *colorSpaceName = NULL, *alternateColorSpaceName = NULL; CGPDFInteger numberOfComponents; CGPDFDictionaryRef dict; bool retrieved; CGFloat *range; CGPDFArrayRef rangeArray; if (CGPDFArrayGetName(colorSpaceArray, 0, &colorSpaceName)) { if (strcmp(colorSpaceName, "ICCBased") == 0) { if (CGPDFArrayGetStream(colorSpaceArray, 1, &stream)) { dict = CGPDFStreamGetDictionary(stream); // First obtain the alternate color space if present if (CGPDFDictionaryGetName(dict, "Alternate", &alternateColorSpaceName)) { if (strcmp(alternateColorSpaceName, "DeviceRGB") == 0) { alternateColorSpace = CGColorSpaceCreateDeviceRGB(); } else if (strcmp(alternateColorSpaceName, "DeviceGray") == 0) { alternateColorSpace = CGColorSpaceCreateDeviceGray(); } else if (strcmp(alternateColorSpaceName, "DeviceCMYK") == 0) { alternateColorSpace = CGColorSpaceCreateDeviceCMYK(); } } // Obtain the preferential color space CGPDFDataFormat dataFormat; CFDataRef colorSpaceDataPtr = CGPDFStreamCopyData(stream, &dataFormat); if (dataFormat == CGPDFDataFormatRaw) { CGDataProviderRef profile = CGDataProviderCreateWithCFData(colorSpaceDataPtr); retrieved = CGPDFDictionaryGetInteger(dict, "N", &numberOfComponents); // Deduce an alternate color space if we don't have one //already if (alternateColorSpace == NULL) { switch (numberOfComponents) { case 1: alternateColorSpace = CGColorSpaceCreateDeviceGray(); break; case 3: alternateColorSpace = CGColorSpaceCreateDeviceRGB(); break; case 4: alternateColorSpace = CGColorSpaceCreateDeviceCMYK(); break; default: break; } } range = malloc(numberOfComponents * 2 * sizeof(CGFloat)); if (!CGPDFDictionaryGetArray(dict, "Range", &rangeArray)) { int i = 0; for (; i < numberOfComponents * 2; i += 2) { range[i] = (i % 2 == 0) ? 0.0 : 1.0; } } else { size_t count = CGPDFArrayGetCount(rangeArray); int i = 0; for (; i < count; i++) { (void)CGPDFArrayGetNumber(rangeArray, i, &range[i]); } } cgColorSpace = CGColorSpaceCreateICCBased(numberOfComponents, range, profile, alternateColorSpace); CGDataProviderRelease(profile); free(range); if (cgColorSpace) { // Since we have a preferential color space, we no //longer need the hang on to the alternate color space CGColorSpaceRelease(alternateColorSpace); } else { cgColorSpace = alternateColorSpace; } } else if (dataFormat == CGPDFDataFormatJPEGEncoded) { // } else if (dataFormat == CGPDFDataFormatJPEG2000) { // } } } else if (strcmp(colorSpaceName, "Indexed") == 0) { CGColorSpaceRef baseSpace; CGPDFArrayRef base = NULL; CGPDFInteger highValue = 0; CGPDFStreamRef stream = NULL; CGPDFStringRef string; const unsigned char *chars; const char *namedColorSpaceName; if (CGPDFArrayGetArray(colorSpaceArray, 1, &base)) { baseSpace = colorSpaceFromPDFArray(base); } else if (CGPDFArrayGetName(colorSpaceArray, 1, &namedColorSpaceName)) { if (strcmp(namedColorSpaceName, "DeviceRGB") == 0) { baseSpace = CGColorSpaceCreateDeviceRGB(); } else if (strcmp(namedColorSpaceName, "DeviceGray") == 0) { baseSpace = CGColorSpaceCreateDeviceGray(); } else if (strcmp(namedColorSpaceName, "DeviceCMYK") == 0) { baseSpace = CGColorSpaceCreateDeviceCMYK(); } } retrieved = CGPDFArrayGetInteger(colorSpaceArray, 2, &highValue); if (CGPDFArrayGetStream(colorSpaceArray, 3, &stream)) { chars = CFDataGetBytePtr(CGPDFStreamCopyData(stream, NULL)); } else if (CGPDFArrayGetString(colorSpaceArray, 3, &string)) { chars = CGPDFStringGetBytePtr(string); } else { // TODO: Raise some error state? } cgColorSpace = CGColorSpaceCreateIndexed(baseSpace, highValue, chars); } } return (CGColorSpaceRef)CFMakeCollectable(cgColorSpace); }
void myOperator_Do(CGPDFScannerRef s, void *info) { // Check to see if this is an image or not. const char *name; CGPDFObjectRef xobject; CGPDFDictionaryRef dict; CGPDFStreamRef stream; CGPDFContentStreamRef cs = CGPDFScannerGetContentStream(s); // The Do operator takes a name. Pop the name off the // stack. If this fails then the argument to the // Do operator is not a name and is therefore invalid! if(!CGPDFScannerPopName(s, &name)){ fprintf(stderr, "Couldn't pop name off stack!\n"); return; } // Get the resource with type "XObject" and the name // obtained from the stack. xobject = CGPDFContentStreamGetResource(cs, "XObject", name); if(!xobject){ fprintf(stderr, "Couldn't get XObject with name %s\n", name); return; } // An XObject must be a stream so obtain the value from the xobject // as if it were a stream. If this fails, the PDF is malformed. if (!CGPDFObjectGetValue(xobject, kCGPDFObjectTypeStream, &stream)){ fprintf(stderr, "XObject '%s' is not a stream!\n", name); return; } // Streams consist of a dictionary and the data associated // with the stream. This code only cares about the dictionary. dict = CGPDFStreamGetDictionary(stream); if(!dict){ fprintf(stderr, "Couldn't obtain dictionary from stream %s!\n", name); return; } // An XObject dict has a Subtype that indicates what kind it is. if(!CGPDFDictionaryGetName(dict, "Subtype", &name)){ fprintf(stderr, "Couldn't get SubType of dictionary object!\n"); return; } // This code is interested in the "Image" Subtype of an XObject. // Check whether this object has Subtype of "Image". printf("%s\n",name); if(strcmp(name, "Image") != 0){ // The Subtype is not "Image" so this must be a form // or other type of XObject. return; } else { CGPDFArrayRef colorSpaceArray; CGPDFDictionaryGetArray(dict,"ColorSpace" ,&colorSpaceArray); CGColorSpaceRef colorSpace=NULL; colorSpace=colorSpaceFromPDFArray(colorSpaceArray); CGPDFDataFormat format; const char *name = NULL, *colorSpaceName = NULL,*renderingIntentName = NULL;; CFDataRef data=CGPDFStreamCopyData(stream,&format); if (format == CGPDFDataFormatRaw){ CGColorSpaceRef cgColorSpace; CGPDFInteger width, height, bps, spp; CGColorRenderingIntent renderingIntent; CGPDFBoolean interpolation = 0; CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(data); if (!CGPDFDictionaryGetInteger(dict, "Width", &width)) return ; if (!CGPDFDictionaryGetInteger(dict, "Height", &height)) return ; if (!CGPDFDictionaryGetInteger(dict, "BitsPerComponent", &bps)) return ; if (!CGPDFDictionaryGetBoolean(dict, "Interpolate", &interpolation)) interpolation = 0; if (!CGPDFDictionaryGetName(dict, "Intent", &renderingIntentName)) renderingIntent = kCGRenderingIntentDefault; else{ renderingIntent = kCGRenderingIntentDefault; // renderingIntent = renderingIntentFromName(renderingIntentName); } if (CGPDFDictionaryGetArray(dict, "ColorSpace", &colorSpaceArray)) { cgColorSpace = CGColorSpaceCreateDeviceRGB(); // cgColorSpace = colorSpaceFromPDFArray(colorSpaceArray); spp = CGColorSpaceGetNumberOfComponents(cgColorSpace); } else if (CGPDFDictionaryGetName(dict, "ColorSpace", &colorSpaceName)) { if (strcmp(colorSpaceName, "DeviceRGB") == 0) { cgColorSpace = CGColorSpaceCreateDeviceRGB(); // CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); spp = 3; } else if (strcmp(colorSpaceName, "DeviceCMYK") == 0) { cgColorSpace = CGColorSpaceCreateDeviceCMYK(); // CGColorSpaceCreateWithName(kCGColorSpaceGenericCMYK); spp = 4; } else if (strcmp(colorSpaceName, "DeviceGray") == 0) { cgColorSpace = CGColorSpaceCreateDeviceGray(); // CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); spp = 1; } else if (bps == 1) { // if there's no colorspace entry, there's still one we can infer from bps cgColorSpace = CGColorSpaceCreateDeviceGray(); // colorSpace = NSDeviceBlackColorSpace; spp = 1; } } CGFloat *decodeValues = NULL; decodeValues = decodeValuesFromImageDictionary(dict, cgColorSpace, bps); int rowBits = bps * spp * width; int rowBytes = rowBits / 8; // pdf image row lengths are padded to byte-alignment if (rowBits % 8 != 0) ++rowBytes; CGImageRef sourceImage = CGImageCreate(width, height, bps, bps * spp, rowBytes, cgColorSpace, 0, dataProvider, decodeValues, interpolation, renderingIntent); CGDataProviderRelease(dataProvider); CGDataProviderRef dataProvider2 = CGImageGetDataProvider(sourceImage); CFDataRef data = CGDataProviderCopyData(dataProvider2); int fd; findex; char file[256]; memset(file,0,sizeof(file)); sprintf(file,"%d.jpg",findex); fd=open(file, O_RDWR|O_CREAT); write(fd, CFDataGetBytePtr(data), CFDataGetLength(data)); findex++; close(fd); //[[NSImage alloc] initWithCGImage:sourceImage size:NSMakeSize(0, 0)]; }else { int fd; findex; char file[256]; memset(file,0,sizeof(file)); sprintf(file,"%d.jpg",findex); fd=open(file, O_RDWR|O_CREAT); write(fd, CFDataGetBytePtr(data), CFDataGetLength(data)); findex++; close(fd); } } // This is an Image so figure out what variety of image it is. checkImageType(dict, (MyDataScan *)info); }
FX_BOOL CFX_QuartzDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, FX_ARGB argb, const FX_RECT* srcRect, int dest_left, int dest_top, int blendType, int alphaFlag , void* iccTransform ) { SaveState(); CGFloat src_left, src_top, src_width, src_height; if (srcRect) { src_left = srcRect->left; src_top = srcRect->top; src_width = srcRect->Width(); src_height = srcRect->Height(); } else { src_left = src_top = 0; src_width = pBitmap->GetWidth(); src_height = pBitmap->GetHeight(); } CGAffineTransform ctm = CGContextGetCTM(_context); CGFloat scale_x = FXSYS_fabs(ctm.a); CGFloat scale_y = FXSYS_fabs(ctm.d); src_left /= scale_x; src_top /= scale_y; src_width /= scale_x; src_height /= scale_y; CGRect rect_fx = CGRectMake(dest_left, dest_top, src_width, src_height); CGRect rect_usr = CGRectApplyAffineTransform(rect_fx, _foxitDevice2User); CGContextBeginPath(_context); CGContextAddRect(_context, rect_usr); CGContextClip(_context); rect_usr.size = CGSizeMake(pBitmap->GetWidth() / scale_x, pBitmap->GetHeight() / scale_y); rect_usr = CGRectOffset(rect_usr, -src_left, -src_top); CG_SetImageTransform(dest_left, dest_top, src_width, src_height, &rect_usr); CFX_DIBitmap* pBitmap1 = NULL; if (pBitmap->IsAlphaMask()) { if (pBitmap->GetBuffer()) { pBitmap1 = (CFX_DIBitmap*)pBitmap; } else { pBitmap1 = pBitmap->Clone(); } if (NULL == pBitmap1) { RestoreState(FALSE); return FALSE; } CGDataProviderRef pBitmapProvider = CGDataProviderCreateWithData(NULL, pBitmap1->GetBuffer(), pBitmap1->GetPitch() * pBitmap1->GetHeight(), NULL); CGColorSpaceRef pColorSpace = CGColorSpaceCreateDeviceGray(); CGBitmapInfo bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault; CGImageRef pImage = CGImageCreate(pBitmap1->GetWidth(), pBitmap1->GetHeight(), pBitmap1->GetBPP(), pBitmap1->GetBPP(), pBitmap1->GetPitch(), pColorSpace, bitmapInfo, pBitmapProvider, NULL, true, kCGRenderingIntentDefault); CGContextClipToMask(_context, rect_usr, pImage); CGContextSetRGBFillColor(_context, FXARGB_R(argb) / 255.f, FXARGB_G(argb) / 255.f, FXARGB_B(argb) / 255.f, FXARGB_A(argb) / 255.f); CGContextFillRect(_context, rect_usr); CGImageRelease(pImage); CGColorSpaceRelease(pColorSpace); CGDataProviderRelease(pBitmapProvider); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(FALSE); return TRUE; } if (pBitmap->GetBPP() < 32) { pBitmap1 = pBitmap->CloneConvert(FXDIB_Rgb32); } else { if (pBitmap->GetBuffer()) { pBitmap1 = (CFX_DIBitmap*)pBitmap; } else { pBitmap1 = pBitmap->Clone(); } } if (NULL == pBitmap1) { RestoreState(FALSE); return FALSE; } if (pBitmap1->HasAlpha()) { if (pBitmap1 == pBitmap) { pBitmap1 = pBitmap->Clone(); if (!pBitmap1) { RestoreState(FALSE); return FALSE; } } for (int row = 0; row < pBitmap1->GetHeight(); row ++) { FX_LPBYTE pScanline = (FX_LPBYTE)pBitmap1->GetScanline(row); for (int col = 0; col < pBitmap1->GetWidth(); col ++) { pScanline[0] = (FX_BYTE)(pScanline[0] * pScanline[3] / 255.f + .5f); pScanline[1] = (FX_BYTE)(pScanline[1] * pScanline[3] / 255.f + .5f); pScanline[2] = (FX_BYTE)(pScanline[2] * pScanline[3] / 255.f + .5f); pScanline += 4; } } } CGContextRef ctx = createContextWithBitmap(pBitmap1); CGImageRef image = CGBitmapContextCreateImage(ctx); int blend_mode = blendType; if (FXDIB_BLEND_HARDLIGHT == blendType) { blend_mode = kCGBlendModeSoftLight; } else if (FXDIB_BLEND_SOFTLIGHT == blendType) { blend_mode = kCGBlendModeHardLight; } else if (blendType >= FXDIB_BLEND_NONSEPARABLE && blendType <= FXDIB_BLEND_LUMINOSITY) { blend_mode = blendType - 9; } else if (blendType > FXDIB_BLEND_LUMINOSITY || blendType < 0) { blend_mode = kCGBlendModeNormal; } CGContextSetBlendMode(_context, (CGBlendMode)blend_mode); CGContextDrawImage(_context, rect_usr, image); CGImageRelease(image); CGContextRelease(ctx); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(FALSE); return TRUE; }
FX_BOOL CFX_QuartzDeviceDriver::StretchDIBits(const CFX_DIBSource* pBitmap, FX_ARGB argb, int dest_left, int dest_top, int dest_width, int dest_height, const FX_RECT* clipRect, FX_DWORD flags, int alphaFlag , void* iccTransform , int blend_type) { SaveState(); if (clipRect) { CGContextBeginPath(_context); CGRect rect_clip = CGRectMake(clipRect->left, clipRect->top, clipRect->Width(), clipRect->Height()); rect_clip = CGRectApplyAffineTransform(rect_clip, _foxitDevice2User); CGContextAddRect(_context, rect_clip); CGContextClip(_context); } CGRect rect = CGRectMake(dest_left, dest_top, dest_width, dest_height); rect = CGRectApplyAffineTransform(rect, _foxitDevice2User); if (FXDIB_BICUBIC_INTERPOL == flags) { CGContextSetInterpolationQuality(_context, kCGInterpolationHigh); } else if (FXDIB_DOWNSAMPLE == flags) { CGContextSetInterpolationQuality(_context, kCGInterpolationNone); } else { CGContextSetInterpolationQuality(_context, kCGInterpolationMedium); } CG_SetImageTransform(dest_left, dest_top, dest_width, dest_height); CFX_DIBitmap* pBitmap1 = NULL; if (pBitmap->IsAlphaMask()) { if (pBitmap->GetBuffer()) { pBitmap1 = (CFX_DIBitmap*)pBitmap; } else { pBitmap1 = pBitmap->Clone(); } if (NULL == pBitmap1) { RestoreState(FALSE); return FALSE; } CGDataProviderRef pBitmapProvider = CGDataProviderCreateWithData(NULL, pBitmap1->GetBuffer(), pBitmap1->GetPitch() * pBitmap1->GetHeight(), NULL); CGColorSpaceRef pColorSpace = CGColorSpaceCreateDeviceGray(); CGBitmapInfo bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault; CGImageRef pImage = CGImageCreate(pBitmap1->GetWidth(), pBitmap1->GetHeight(), pBitmap1->GetBPP(), pBitmap1->GetBPP(), pBitmap1->GetPitch(), pColorSpace, bitmapInfo, pBitmapProvider, NULL, true, kCGRenderingIntentDefault); CGContextClipToMask(_context, rect, pImage); CGContextSetRGBFillColor(_context, FXARGB_R(argb) / 255.f, FXARGB_G(argb) / 255.f, FXARGB_B(argb) / 255.f, FXARGB_A(argb) / 255.f); CGContextFillRect(_context, rect); CGImageRelease(pImage); CGColorSpaceRelease(pColorSpace); CGDataProviderRelease(pBitmapProvider); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(FALSE); return TRUE; } if (pBitmap->GetBPP() < 32) { pBitmap1 = pBitmap->CloneConvert(FXDIB_Rgb32); } else { if (pBitmap->GetBuffer()) { pBitmap1 = (CFX_DIBitmap*)pBitmap; } else { pBitmap1 = pBitmap->Clone(); } } if (NULL == pBitmap1) { RestoreState(FALSE); return FALSE; } if (pBitmap1->HasAlpha()) { if (pBitmap1 == pBitmap) { pBitmap1 = pBitmap->Clone(); if (!pBitmap1) { RestoreState(FALSE); return FALSE; } } for (int row = 0; row < pBitmap1->GetHeight(); row ++) { FX_LPBYTE pScanline = (FX_LPBYTE)pBitmap1->GetScanline(row); for (int col = 0; col < pBitmap1->GetWidth(); col ++) { pScanline[0] = (FX_BYTE)(pScanline[0] * pScanline[3] / 255.f + .5f); pScanline[1] = (FX_BYTE)(pScanline[1] * pScanline[3] / 255.f + .5f); pScanline[2] = (FX_BYTE)(pScanline[2] * pScanline[3] / 255.f + .5f); pScanline += 4; } } } CGContextRef ctx = createContextWithBitmap(pBitmap1); CGImageRef image = CGBitmapContextCreateImage(ctx); CGContextDrawImage(_context, rect, image); CGImageRelease(image); CGContextRelease(ctx); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(FALSE); return TRUE; }
FX_BOOL CFX_AggDeviceDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS * pCharPos, CFX_Font * pFont, CFX_FontCache * pCache, const CFX_AffineMatrix * pObject2Device, FX_FLOAT font_size, FX_DWORD argb, int alpha_flag, void* pIccTransform) { if (!pFont) { return FALSE; } FX_BOOL bBold = pFont->IsBold(); if (!bBold && pFont->GetSubstFont() && pFont->GetSubstFont()->m_Weight >= 500 && pFont->GetSubstFont()->m_Weight <= 600) { return FALSE; } for (int i = 0; i < nChars; i ++) { if (pCharPos[i].m_bGlyphAdjust) { return FALSE; } } CGContextRef ctx = CGContextRef(m_pPlatformGraphics); if (NULL == ctx) { return FALSE; } CGContextSaveGState(ctx); CGContextSetTextDrawingMode(ctx, kCGTextFillClip); CGRect rect_cg; CGImageRef pImageCG = NULL; if (m_pClipRgn) { rect_cg = CGRectMake(m_pClipRgn->GetBox().left, m_pClipRgn->GetBox().top, m_pClipRgn->GetBox().Width(), m_pClipRgn->GetBox().Height()); const CFX_DIBitmap* pClipMask = m_pClipRgn->GetMask(); if (pClipMask) { CGDataProviderRef pClipMaskDataProvider = CGDataProviderCreateWithData(NULL, pClipMask->GetBuffer(), pClipMask->GetPitch() * pClipMask->GetHeight(), _DoNothing); CGFloat decode_f[2] = {255.f, 0.f}; pImageCG = CGImageMaskCreate(pClipMask->GetWidth(), pClipMask->GetHeight(), 8, 8, pClipMask->GetPitch(), pClipMaskDataProvider, decode_f, FALSE); CGDataProviderRelease(pClipMaskDataProvider); } } else { rect_cg = CGRectMake(0, 0, m_pBitmap->GetWidth(), m_pBitmap->GetHeight()); } rect_cg = CGContextConvertRectToDeviceSpace(ctx, rect_cg); if (pImageCG) { CGContextClipToMask(ctx, rect_cg, pImageCG); } else { CGContextClipToRect(ctx, rect_cg); } FX_BOOL ret = _CGDrawGlyphRun(ctx, nChars, pCharPos, pFont, pCache, pObject2Device, font_size, argb, alpha_flag, pIccTransform); if (pImageCG) { CGImageRelease(pImageCG); } CGContextRestoreGState(ctx); return ret; }
static mblk_t *jpeg2yuv(uint8_t *jpgbuf, int bufsize, MSVideoSize *reqsize){ #ifndef NO_FFMPEG AVCodecContext av_context; int got_picture=0; mblk_t *ret; struct SwsContext *sws_ctx; AVPacket pkt; MSPicture dest; AVCodec *codec=avcodec_find_decoder(CODEC_ID_MJPEG); AVFrame* orig = av_frame_alloc(); if (codec==NULL){ ms_error("Could not find MJPEG decoder in ffmpeg."); return NULL; } avcodec_get_context_defaults3(&av_context,NULL); if (avcodec_open2(&av_context,codec,NULL)<0){ ms_error("jpeg2yuv: avcodec_open failed"); return NULL; } av_init_packet(&pkt); pkt.data=jpgbuf; pkt.size=bufsize; if (avcodec_decode_video2(&av_context,orig,&got_picture,&pkt) < 0) { ms_error("jpeg2yuv: avcodec_decode_video failed"); avcodec_close(&av_context); return NULL; } ret=ms_yuv_buf_alloc(&dest, reqsize->width,reqsize->height); /* not using SWS_FAST_BILINEAR because it doesn't play well with * av_context.pix_fmt set to PIX_FMT_YUVJ420P by jpeg decoder */ sws_ctx=sws_getContext(av_context.width,av_context.height,av_context.pix_fmt, reqsize->width,reqsize->height,PIX_FMT_YUV420P,SWS_BILINEAR, NULL, NULL, NULL); if (sws_ctx==NULL) { ms_error("jpeg2yuv: ms_sws_getContext() failed."); avcodec_close(&av_context); freemsg(ret); return NULL; } #if LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(0,9,0) if (sws_scale(sws_ctx,(const uint8_t* const *)orig->data,orig->linesize,0,av_context.height,dest.planes,dest.strides)<0){ #else if (sws_scale(sws_ctx,(uint8_t**)orig->data,orig->linesize,0,av_context.height,dest.planes,dest.strides)<0){ #endif ms_error("jpeg2yuv: ms_sws_scale() failed."); sws_freeContext(sws_ctx); avcodec_close(&av_context); freemsg(ret); return NULL; } sws_freeContext(sws_ctx); av_frame_free(&orig); avcodec_close(&av_context); return ret; #elif TARGET_OS_IPHONE MSPicture dest; CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, jpgbuf, bufsize, NULL); // use the data provider to get a CGImage; release the data provider CGImageRef image = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, FALSE, kCGRenderingIntentDefault); CGDataProviderRelease(dataProvider); reqsize->width = CGImageGetWidth(image); reqsize->height = CGImageGetHeight(image); uint8_t* tmp = (uint8_t*) malloc(reqsize->width * reqsize->height * 4); mblk_t* ret=ms_yuv_buf_alloc(&dest, reqsize->width, reqsize->height); CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef imageContext = CGBitmapContextCreate(tmp, reqsize->width, reqsize->height, 8, reqsize->width*4, colourSpace, kCGImageAlphaNoneSkipLast); CGColorSpaceRelease(colourSpace); // draw the image to the context, release it CGContextDrawImage(imageContext, CGRectMake(0, 0, reqsize->width, reqsize->height), image); CGImageRelease(image); /* convert tmp/RGB -> ret/YUV */ for(int y=0; y<reqsize->height; y++) { for(int x=0; x<reqsize->width; x++) { uint8_t r = tmp[y * reqsize->width * 4 + x * 4 + 0]; uint8_t g = tmp[y * reqsize->width * 4 + x * 4 + 1]; uint8_t b = tmp[y * reqsize->width * 4 + x * 4 + 2]; // Y *dest.planes[0]++ = (uint8_t)((0.257 * r) + (0.504 * g) + (0.098 * b) + 16); // U/V subsampling if ((y % 2==0) && (x%2==0)) { uint32_t r32=0, g32=0, b32=0; for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { r32 += tmp[(y+i) * reqsize->width * 4 + (x+j) * 4 + 0]; g32 += tmp[(y+i) * reqsize->width * 4 + (x+j) * 4 + 1]; b32 += tmp[(y+i) * reqsize->width * 4 + (x+j) * 4 + 2]; } } r32 = (uint32_t)(r32 * 0.25f); g32 = (uint32_t)(g32 * 0.25f); b32 = (uint32_t) (b32 * 0.25f); // U *dest.planes[1]++ = (uint8_t)(-(0.148 * r32) - (0.291 * g32) + (0.439 * b32) + 128); // V *dest.planes[2]++ = (uint8_t)((0.439 * r32) - (0.368 * g32) - (0.071 * b32) + 128); } } } free(tmp); return ret; #else return NULL; #endif } mblk_t *ms_load_jpeg_as_yuv(const char *jpgpath, MSVideoSize *reqsize){ #if defined(WIN32) mblk_t *m=NULL; DWORD st_sizel; DWORD st_sizeh; uint8_t *jpgbuf; DWORD err; HANDLE fd; #ifdef UNICODE WCHAR wUnicode[1024]; MultiByteToWideChar(CP_UTF8, 0, jpgpath, -1, wUnicode, 1024); fd = CreateFile(wUnicode, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); #else fd = CreateFile(jpgpath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); #endif if (fd==INVALID_HANDLE_VALUE){ ms_error("Failed to open %s",jpgpath); return NULL; } st_sizel=0; st_sizeh=0; st_sizel = GetFileSize(fd, &st_sizeh); if (st_sizeh>0 || st_sizel<=0) { CloseHandle(fd); ms_error("Can't load file %s",jpgpath); return NULL; } jpgbuf=(uint8_t*)ms_malloc0(st_sizel); if (jpgbuf==NULL) { CloseHandle(fd); ms_error("Cannot allocate buffer for %s",jpgpath); return NULL; } err=0; ReadFile(fd, jpgbuf, st_sizel, &err, NULL) ; if (err!=st_sizel){ ms_error("Could not read as much as wanted !"); } m=jpeg2yuv(jpgbuf,st_sizel,reqsize); ms_free(jpgbuf); if (m==NULL) { CloseHandle(fd); ms_error("Cannot load image from buffer for %s",jpgpath); return NULL; } CloseHandle(fd); return m; #else mblk_t *m=NULL; struct stat statbuf; uint8_t *jpgbuf; int err; int fd=open(jpgpath,O_RDONLY); if (fd!=-1){ fstat(fd,&statbuf); if (statbuf.st_size<=0) { close(fd); ms_error("Cannot load %s",jpgpath); return NULL; } jpgbuf=(uint8_t*)ms_malloc0(statbuf.st_size + FF_INPUT_BUFFER_PADDING_SIZE); if (jpgbuf==NULL) { close(fd); ms_error("Cannot allocate buffer for %s",jpgpath); return NULL; } err=read(fd,jpgbuf,statbuf.st_size); if (err!=statbuf.st_size){ ms_error("Could not read as much as wanted: %i<>%li !",err,(long)statbuf.st_size); } m=jpeg2yuv(jpgbuf,statbuf.st_size,reqsize); ms_free(jpgbuf); if (m==NULL) { close(fd); ms_error("Cannot load image from buffer for %s",jpgpath); return NULL; } }else{ ms_error("Cannot load %s",jpgpath); return NULL; } close(fd); return m; #endif }
CGImageRef CreateCGImage(void *aInfo, const void *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) { //XXX: we should avoid creating this colorspace everytime CGColorSpaceRef colorSpace = nullptr; CGBitmapInfo bitinfo = 0; int bitsPerComponent = 0; int bitsPerPixel = 0; switch (aFormat) { case SurfaceFormat::B8G8R8A8: colorSpace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; bitsPerComponent = 8; bitsPerPixel = 32; break; case SurfaceFormat::B8G8R8X8: colorSpace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; bitsPerComponent = 8; bitsPerPixel = 32; break; case SurfaceFormat::A8: // XXX: why don't we set a colorspace here? bitsPerComponent = 8; bitsPerPixel = 8; break; default: MOZ_CRASH(); } size_t bufLen = BufferSizeFromStrideAndHeight(aStride, aSize.height); if (bufLen == 0) { return nullptr; } CGDataProviderRef dataProvider = CGDataProviderCreateWithData(aInfo, aData, bufLen, releaseCallback); CGImageRef image; if (aFormat == SurfaceFormat::A8) { CGFloat decode[] = {1.0, 0.0}; image = CGImageMaskCreate (aSize.width, aSize.height, bitsPerComponent, bitsPerPixel, aStride, dataProvider, decode, true); } else { image = CGImageCreate (aSize.width, aSize.height, bitsPerComponent, bitsPerPixel, aStride, colorSpace, bitinfo, dataProvider, nullptr, true, kCGRenderingIntentDefault); } CGDataProviderRelease(dataProvider); CGColorSpaceRelease(colorSpace); return image; }
OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize) { CGFloat minCartDrawSize = 64; CGFloat size = fmin(maxSize.width, maxSize.height); CGContextRef qlContext = NULL; if (size < minCartDrawSize) { size = 32; qlContext = QLThumbnailRequestCreateContext(thumbnail, CGSizeMake(size,size), true, NULL); } else { qlContext = QLThumbnailRequestCreateContext(thumbnail, CGSizeMake(size,size), false, NULL); } if (qlContext) { NDSHeader header; NDSIcon icon; int pathlen = 2047; UInt8 path[pathlen+1]; if (CFURLGetFileSystemRepresentation(url, true, path, pathlen)) { if (size < minCartDrawSize) { // at smaller sizes we only draw the game icon at native size and let QL do the scaling parseNDSInfo(path, &header, &icon); CGImageRef image = CGImageCreateWithNDSIcon(&icon); if (image) { CGContextDrawImage(qlContext, CGRectMake(0, 0, size, size), image); CGImageRelease(image); } } else { CGContextClearRect(qlContext, CGRectMake(0,0,size,size)); // draw cartridge background CFURLRef bgURL = CFBundleCopyResourceURL(CFBundleGetBundleWithIdentifier( CFSTR("net.mironer.nds.quicklookgenerator")), CFSTR("background"), CFSTR("png"), NULL); if (bgURL) { CGDataProviderRef bgPNG = CGDataProviderCreateWithURL(bgURL); if (bgPNG) { CGImageRef bg = CGImageCreateWithPNGDataProvider(bgPNG, NULL, true, kCGRenderingIntentDefault); if (bg) { CGContextDrawImage(qlContext, CGRectMake(0, 0, size, size), bg); CGImageRelease(bg); } CGDataProviderRelease(bgPNG); } CFRelease(bgURL); } // draw game icon parseNDSInfo(path, &header, &icon); CGImageRef image = CGImageCreateWithNDSIcon(&icon); if (image) { CGContextDrawImage(qlContext, CGRectMake(size / 5, size / 5, size * 3 / 5, size * 3 / 5), image); CGImageRelease(image); } // draw cartridge overlay CFURLRef ovrURL = CFBundleCopyResourceURL( CFBundleGetBundleWithIdentifier( CFSTR("net.mironer.nds.quicklookgenerator")), CFSTR("overlay"), CFSTR("png"), NULL); if (ovrURL) { CGDataProviderRef ovrPNG = CGDataProviderCreateWithURL(ovrURL); if (ovrPNG) { CGImageRef ovr = CGImageCreateWithPNGDataProvider(ovrPNG, NULL, true, kCGRenderingIntentDefault); if (ovr) { CGContextDrawImage(qlContext, CGRectMake(0, 0, size, size), ovr); CGImageRelease(ovr); } CGDataProviderRelease(ovrPNG); } CFRelease(ovrURL); } // draw serial number CFStringRef serial = CFStringCreateWithSerialNumber(&header); CFAttributedStringRef aString = CFAttributedStringCreate(kCFAllocatorDefault, serial, NULL); CFMutableAttributedStringRef attrStr = CFAttributedStringCreateMutableCopy(kCFAllocatorDefault, 128, aString); CFIndex len = CFAttributedStringGetLength(attrStr); CTFontRef font = CTFontCreateWithName(CFSTR("Lucida Sans"), size / 16, NULL); CFAttributedStringSetAttribute(attrStr, CFRangeMake(0, len), kCTFontAttributeName, font); CTTextAlignment rightAlign = kCTRightTextAlignment; CTParagraphStyleSetting styleSettings[] = { {kCTParagraphStyleSpecifierAlignment, sizeof(rightAlign), &rightAlign} }; CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(styleSettings, 1); CFAttributedStringSetAttribute(attrStr, CFRangeMake(0, len), kCTParagraphStyleAttributeName, paragraphStyle); CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrStr); CFRelease(attrStr); CFRelease(aString); CFRelease(serial); CFRelease(font); CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, CGRectMake(-size * 1.55 / 8, -size * 6.1 / 8, size, size)); CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); CTFrameDraw(frame, qlContext); CFRelease(frame); CFRelease(framesetter); CFRelease(paragraphStyle); CFRelease(path); } } QLThumbnailRequestFlushContext(thumbnail, qlContext); CFRelease(qlContext); } return noErr; }
static CGImageSourceRef SkStreamToCGImageSource(SkStream* stream) { CGDataProviderRef data = SkStreamToDataProvider(stream); CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(data, 0); CGDataProviderRelease(data); return imageSrc; }
// ----------------------------------------------------------------------------- // CreateCGImageWithQTFromFile // ----------------------------------------------------------------------------- // OSStatus CreateCGImageWithQTFromFile( FSRef* inFSRef, CGImageRef* outImage ) { OSStatus err; GraphicsImportComponent importer; FSSpec fileSpec; GWorldPtr gWorld = NULL; Rect bounds; CGDataProviderRef provider; CGColorSpaceRef colorspace; long width; long height; long rowbytes; Ptr dataPtr; // Make an FSRef into an FSSpec err = FSGetCatalogInfo( inFSRef, kFSCatInfoNone, NULL, NULL, &fileSpec, NULL ); require_noerr( err, CantMakeFSSpec ); err = GetGraphicsImporterForFile( &fileSpec, &importer ); require_noerr( err, CantGetImporter ); err = GraphicsImportGetNaturalBounds( importer, &bounds ); require_noerr( err, CantGetBounds ); // Allocate the buffer width = RECT_WIDTH( bounds ); height = RECT_HEIGHT( bounds ); rowbytes = width * 4; dataPtr = NewPtr( height * rowbytes ); require_action( dataPtr != NULL, CantAllocBuffer, err = memFullErr ); err = NewGWorldFromPtr( &gWorld, 32, &bounds, NULL, NULL, NULL, dataPtr, rowbytes ); require_noerr( err, CantCreateGWorld ); err = GraphicsImportSetGWorld( importer, gWorld, GetGWorldDevice( gWorld) ); require_noerr( err, CantSetGWorld ); err = GraphicsImportDraw( importer ); require_noerr( err, CantDraw ); provider = CGDataProviderCreateWithData( NULL, dataPtr, height * rowbytes, GWorldImageBufferRelease ); require_action( provider != NULL, CantCreateProvider, err = memFullErr ); colorspace = CGColorSpaceCreateDeviceRGB(); require_action( colorspace != NULL, CantCreateColorSpace, err = memFullErr ); *outImage = CGImageCreate( width, height, 8, 32, rowbytes, colorspace, kCGImageAlphaPremultipliedFirst, provider, NULL, false, kCGRenderingIntentDefault ); require_action( *outImage != NULL, CantCreateImage, err = memFullErr ); CantCreateImage: CGColorSpaceRelease( colorspace ); CantCreateColorSpace: CGDataProviderRelease( provider ); CantCreateProvider: CantDraw: CantSetGWorld: if ( gWorld != NULL ) DisposeGWorld( gWorld ); CantCreateGWorld: CantAllocBuffer: CantGetBounds: CantGetImporter: CantMakeFSSpec: return err; }
bool SourceSurfaceCG::InitFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) { //XXX: we should avoid creating this colorspace everytime CGColorSpaceRef colorSpace = NULL; CGBitmapInfo bitinfo = 0; CGDataProviderRef dataProvider = NULL; int bitsPerComponent = 0; int bitsPerPixel = 0; switch (aFormat) { case B8G8R8A8: colorSpace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; bitsPerComponent = 8; bitsPerPixel = 32; break; case B8G8R8X8: colorSpace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; bitsPerComponent = 8; bitsPerPixel = 32; break; case A8: // XXX: why don't we set a colorspace here? bitsPerComponent = 8; bitsPerPixel = 8; }; void *data = malloc(aStride * aSize.height); memcpy(aData, data, aStride * aSize.height); mFormat = aFormat; dataProvider = CGDataProviderCreateWithData (data, data, aSize.height * aStride, releaseCallback); if (aFormat == A8) { CGFloat decode[] = {1.0, 0.0}; mImage = CGImageMaskCreate (aSize.width, aSize.height, bitsPerComponent, bitsPerPixel, aStride, dataProvider, decode, true); } else { mImage = CGImageCreate (aSize.width, aSize.height, bitsPerComponent, bitsPerPixel, aStride, colorSpace, bitinfo, dataProvider, NULL, true, kCGRenderingIntentDefault); } CGDataProviderRelease(dataProvider); CGColorSpaceRelease (colorSpace); if (mImage) { return false; } return true; }