/* write image file */
int BIWriteFile(
	const char			*fileName,
	BIFileType			fileType,
	const BIImageInfo	*imageInfo,
	const unsigned char *bitmap)
{
	int						ourRtn = 0;
	CGImageAlphaInfo		alpha;
	CGBitmapInfo			bitmapInfo = 0;
	CGContextRef			bitmapContextRef = NULL;
	CGImageRef				imageRef = NULL;
	CFURLRef				fileURL = NULL;
	CGImageDestinationRef	imageDestRef = NULL;
	CGColorSpaceRef			rgbColorSpaceRef = NULL;
	CFStringRef				uti = NULL;
	CFDictionaryRef			propDict = NULL;
	
	if(imageInfo->bitsPerPixel == 8) {
		/* grayscale image */
		rgbColorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
		alpha = kCGImageAlphaNone;
		bitmapInfo = 0;
	}
	else {
		/* RGB no alpha */
        rgbColorSpaceRef = CGColorSpaceCreateDeviceRGB();
		alpha = kCGImageAlphaNoneSkipLast;
		bitmapInfo = kCGBitmapByteOrder32Big | alpha;
	}
	if(rgbColorSpaceRef == NULL) {
		fprintf(stderr, "***BIWriteFile: Error on CGColorSpaceCreateWithName\n");
		ourRtn = 1;
		goto errOut;
	}
	
	/* A bitmap-oriented CGContextRef based on bitmap data */
	bitmapContextRef = CGBitmapContextCreate((void *)bitmap, 
		imageInfo->imageWidth, imageInfo->imageHeight, 
		imageInfo->bitsPerComponent, imageInfo->bytesPerRow, 
		rgbColorSpaceRef, 
		bitmapInfo);
	if(bitmapContextRef == NULL) {
		fprintf(stderr, "***BIWriteFile: Error creating CGBitmapContext\n");
		ourRtn = 1;
		goto errOut;
	}
	
	/* CGContextRef --> CGImageRef */
    imageRef = CGBitmapContextCreateImage(bitmapContextRef);

	fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, 
		(unsigned char*)fileName, strlen(fileName), FALSE);
	if(fileURL == NULL) {
		fprintf(stderr, "***BIWriteFile: Error on CFURLCreateFromFileSystemRepresentation\n");
		ourRtn = 1;
		goto errOut;
	}

	uti = BIGetUTI(fileURL, fileType);
	if(uti == NULL) {
		ourRtn = 1;
		goto errOut;
	}
	imageDestRef = CGImageDestinationCreateWithURL(fileURL, 
		uti, 
		1, NULL );
	if(imageDestRef == NULL) {
		fprintf(stderr, "***BIWriteFile: Error on CGImageDestinationCreateWithURL\n");
		ourRtn = 1;
		goto errOut;
	}
	
	/* Some BIFileTypes require the specification of a "Lossless" property */
	switch(fileType) {
		case BI_FT_JPEG2000_Lossless:
		case BI_FT_JPEG_Lossless:
		{
			CFStringRef key = kCGImageDestinationLossyCompressionQuality;
			float valf = 1.0;
			CFNumberRef val = CFNumberCreate(NULL, kCFNumberFloatType, &valf);
			propDict = CFDictionaryCreate(NULL, (const void **)&key, (const void **)&val, 1, 
				&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
			/* 
			 * The docs say we should be able to set these properties like this,
			 * but that has no effect. We need to pass it as the 'properties' argument
			 * to CGImageDestinationAddImage(), below. 
			 * See <rdar://problem/5670614> 
			 */
			//CGImageDestinationSetProperties(imageDestRef, propDict);
			CFRelease(val);
			break;
		}
		default:
			break;
	}
	
	CGImageDestinationAddImage(imageDestRef, imageRef, propDict);
	
	/* Write the image to disk */
	if(!CGImageDestinationFinalize(imageDestRef)) {
		fprintf(stderr, "***BIWriteFile: Error on CGImageDestinationFinalize\n");
		ourRtn = 1;
	}
	if(propDict != NULL) {
		CFRelease(propDict);
	}
errOut:
	CFRELEASE(bitmapContextRef);
	CFRELEASE(imageRef);
	CFRELEASE(fileURL);
	CFRELEASE(imageDestRef);
	CFRELEASE(rgbColorSpaceRef);
	return ourRtn;
}
Exemple #2
0
/***********************************************************************
 *              create_cgimage_from_icon_bitmaps
 */
CGImageRef create_cgimage_from_icon_bitmaps(HDC hdc, HANDLE icon, HBITMAP hbmColor,
                                            unsigned char *color_bits, int color_size, HBITMAP hbmMask,
                                            unsigned char *mask_bits, int mask_size, int width,
                                            int height, int istep)
{
    int i, has_alpha = FALSE;
    DWORD *ptr;
    CGBitmapInfo alpha_format;
    CGColorSpaceRef colorspace;
    CFDataRef data;
    CGDataProviderRef provider;
    CGImageRef cgimage;

    /* draw the cursor frame to a temporary buffer then create a CGImage from that */
    memset(color_bits, 0x00, color_size);
    SelectObject(hdc, hbmColor);
    if (!DrawIconEx(hdc, 0, 0, icon, width, height, istep, NULL, DI_NORMAL))
    {
        WARN("Could not draw frame %d (walk past end of frames).\n", istep);
        return NULL;
    }

    /* check if the cursor frame was drawn with an alpha channel */
    for (i = 0, ptr = (DWORD*)color_bits; i < width * height; i++, ptr++)
        if ((has_alpha = (*ptr & 0xff000000) != 0)) break;

    if (has_alpha)
        alpha_format = kCGImageAlphaFirst;
    else
        alpha_format = kCGImageAlphaNoneSkipFirst;

    colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    if (!colorspace)
    {
        WARN("failed to create colorspace\n");
        return NULL;
    }

    data = CFDataCreate(NULL, (UInt8*)color_bits, color_size);
    if (!data)
    {
        WARN("failed to create data\n");
        CGColorSpaceRelease(colorspace);
        return NULL;
    }

    provider = CGDataProviderCreateWithCFData(data);
    CFRelease(data);
    if (!provider)
    {
        WARN("failed to create data provider\n");
        CGColorSpaceRelease(colorspace);
        return NULL;
    }

    cgimage = CGImageCreate(width, height, 8, 32, width * 4, colorspace,
                            alpha_format | kCGBitmapByteOrder32Little,
                            provider, NULL, FALSE, kCGRenderingIntentDefault);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorspace);
    if (!cgimage)
    {
        WARN("failed to create image\n");
        return NULL;
    }

    /* if no alpha channel was drawn then generate it from the mask */
    if (!has_alpha)
    {
        unsigned int width_bytes = (width + 31) / 32 * 4;
        CGImageRef cgmask, temp;

        /* draw the cursor mask to a temporary buffer */
        memset(mask_bits, 0xFF, mask_size);
        SelectObject(hdc, hbmMask);
        if (!DrawIconEx(hdc, 0, 0, icon, width, height, istep, NULL, DI_MASK))
        {
            WARN("Failed to draw frame mask %d.\n", istep);
            CGImageRelease(cgimage);
            return NULL;
        }

        data = CFDataCreate(NULL, (UInt8*)mask_bits, mask_size);
        if (!data)
        {
            WARN("failed to create data\n");
            CGImageRelease(cgimage);
            return NULL;
        }

        provider = CGDataProviderCreateWithCFData(data);
        CFRelease(data);
        if (!provider)
        {
            WARN("failed to create data provider\n");
            CGImageRelease(cgimage);
            return NULL;
        }

        cgmask = CGImageMaskCreate(width, height, 1, 1, width_bytes, provider, NULL, FALSE);
        CGDataProviderRelease(provider);
        if (!cgmask)
        {
            WARN("failed to create mask\n");
            CGImageRelease(cgimage);
            return NULL;
        }

        temp = CGImageCreateWithMask(cgimage, cgmask);
        CGImageRelease(cgmask);
        CGImageRelease(cgimage);
        if (!temp)
        {
            WARN("failed to create masked image\n");
            return NULL;
        }
        cgimage = temp;
    }

    return cgimage;
}
Exemple #3
0
static bool osx_prepare_text(const void *p_text, uindex_t p_length, const MCGFont &p_font)
{
    OSStatus t_err;
	t_err = noErr;
    
	if (t_err == noErr)
		if (s_layout == NULL)
			t_err = ATSUCreateTextLayout(&s_layout);
	
	if (t_err == noErr)
		if (s_style == NULL)
			t_err = ATSUCreateStyle(&s_style);
    
    if (t_err == noErr)
        if (s_colour_space == NULL)
            s_colour_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
    
    if (t_err == noErr)
        if (s_colour == NULL)
        {
            // Components are grey and alpha
            const float t_colour_components[] = {1.0, 1.0};
            s_colour = CGColorCreate(s_colour_space, t_colour_components);
        }
	
	ATSUFontID t_font_id;
	Fixed t_font_size;
	Boolean t_font_is_italic;
	ATSUTextMeasurement t_imposed_width;
    if (t_err == noErr)
    {
        t_font_size = p_font . size << 16;
		
		// MM-2013-09-16: [[ Bug 11283 ]] It appears that ATSUI doesn't like italic being passed as a style parameter to ATSUFONDtoFontID.
		//   Instead, set italic as an attribute tag.
		uint8_t t_style;
		t_style = p_font . style & ~italic;
		t_font_is_italic = p_font . style & italic;
		
		// MW-2013-12-05: [[ Bug 11535 ]] Set the imposed width to the fixed advance width
		//   if non-zero. Otherwise use the glyph advance.
		if (p_font . fixed_advance != 0)
			t_imposed_width = p_font . fixed_advance << 16;
		else
			t_imposed_width = kATSUseGlyphAdvance;
			
		// if the specified font can't be found, just use the default
		// MM-2013-09-16: [[ Bug 11283 ]] Do the same for font styles - if the font/style paring cannot be found, try font with no style.
		t_err = ATSUFONDtoFontID((short)(intptr_t)p_font . fid, t_style, &t_font_id);
		if (t_err != noErr)
			t_err = ATSUFONDtoFontID((short)(intptr_t)p_font . fid, 0, &t_font_id);
		if (t_err != noErr)
			t_err = ATSUFONDtoFontID(0, t_style, &t_font_id);
		if (t_err != noErr)
			t_err = ATSUFONDtoFontID(0, 0, &t_font_id);
    }
	ATSUAttributeTag t_tags[] =
	{
		kATSUFontTag,
		kATSUSizeTag,
		kATSUQDItalicTag,
		kATSUImposeWidthTag,
	};
	ByteCount t_sizes[] =
	{
		sizeof(ATSUFontID),
		sizeof(Fixed),
		sizeof(Boolean),
		sizeof(ATSUTextMeasurement),
	};
	ATSUAttributeValuePtr t_attrs[] =
	{
		&t_font_id,
		&t_font_size,
		&t_font_is_italic,
		&t_imposed_width,
	};
	if (t_err == noErr)
		t_err = ATSUSetAttributes(s_style, sizeof(t_tags) / sizeof(ATSUAttributeTag), t_tags, t_sizes, t_attrs);
	if (t_err == noErr)
		t_err = ATSUSetTextPointerLocation(s_layout, (const UniChar *) p_text, 0, p_length / 2, p_length / 2);
	if (t_err == noErr)
		t_err = ATSUSetRunStyle(s_layout, s_style, 0, p_length / 2);
	if (t_err == noErr)
		t_err = ATSUSetTransientFontMatching(s_layout, true);
	
	return t_err == noErr;
}
/* read image file */
int BIReadFile(
	const char			*fileName,
	BIFileType			fileType,
	BIPadMode			padMode,
	unsigned			padSize,
	BIImageInfo			*imageInfo,		/* RETURNED */
	unsigned char		**bitmap)		/* mallocd and RETURNED; caller must free */
{
	CFURLRef fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, 
		(unsigned char*)fileName, strlen(fileName), FALSE);
	if(fileURL == NULL) {
		fprintf(stderr, "***BIReadFile: Error on CFURLCreateFromFileSystemRepresentation\n");
		return -1;
	}

	CFStringRef keys[1] = {kCGImageSourceTypeIdentifierHint};
	CFStringRef values[1] = {BIGetUTI(fileURL, fileType)};
	
	if(values[0] == NULL) {
		return -1;
	}
	
	CFDictionaryRef		optionsDict = NULL;
	CGImageSourceRef	imageSourceRef = NULL;
	CGImageRef			imageRef = NULL;
	CGColorSpaceRef		rgbColorSpaceRef = NULL;
	CGContextRef		bitmapContextRef = NULL;
	CGBitmapInfo		bitmapInfo = 0;
	CGImageAlphaInfo	alpha;
	unsigned			bytesPerPixel = 4;
	
	optionsDict = CFDictionaryCreate( kCFAllocatorDefault, 
		(const void **)keys, (const void **)values, 1,  
		&kCFTypeDictionaryKeyCallBacks,  &kCFTypeDictionaryValueCallBacks );
	/* subsequent errors to errOut: */
	
	int ourRtn = 0;
	
	/* source file --> CGImageRef */
	imageSourceRef = CGImageSourceCreateWithURL(fileURL, optionsDict);
	if(imageSourceRef == NULL) {
		fprintf(stderr, "***BIReadFile: Error on CGImageSourceCreateWithURL\n");
		ourRtn = 1;
		goto errOut;
	}
	CFRELEASE(fileURL);
	imageRef = CGImageSourceCreateImageAtIndex(imageSourceRef, 0, optionsDict );
	if(imageRef == NULL) {
		fprintf(stderr, "***BIReadFile: Error on CGImageSourceCreateImageAtIndex\n");
		ourRtn = 1;
		goto errOut;
	}
	
	imageInfo->imageWidth			= CGImageGetWidth(imageRef);
	imageInfo->imageHeight			= CGImageGetHeight(imageRef);
	imageInfo->bitsPerComponent		= CGImageGetBitsPerComponent(imageRef);
	imageInfo->bitsPerPixel			= CGImageGetBitsPerPixel(imageRef);
	
	if(imageInfo->bitsPerPixel == 8) {
		/* the image is gray */
		rgbColorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
		imageInfo->bytesPerRow = imageInfo->imageWidth; 
		alpha = kCGImageAlphaNone;
		bitmapInfo = CGImageGetBitmapInfo(imageRef);
		bytesPerPixel = 1;
	}
	else {
        rgbColorSpaceRef = CGColorSpaceCreateDeviceRGB();
		imageInfo->bytesPerRow = imageInfo->imageWidth * 4;
		alpha = kCGImageAlphaPremultipliedLast;
		bitmapInfo = kCGBitmapByteOrder32Big | alpha;
	}
	if(rgbColorSpaceRef == NULL) {
		fprintf(stderr, "***BIReadFile: Error on CGColorSpaceCreateWithName\n");
		ourRtn = 1;
		goto errOut;
	}
	
	/* optionally pad */
	imageInfo->effectHeight = imageInfo->imageHeight;
	if(padMode != PM_None) {
		if(padSize == 0) {
			fprintf(stderr, "***Pad size of 0 invalid\n");
			ourRtn = 1;
			goto errOut;
		}
		unsigned padSizeBytes = padSize;
		if(padMode == PM_Pixels) {
			padSizeBytes *= bytesPerPixel;
		}
		imageInfo->bytesPerRow = ROUND_TO(imageInfo->bytesPerRow, padSizeBytes);
		/* also round up row count */
		imageInfo->effectHeight = ROUND_TO(imageInfo->imageHeight, padSize);
	}

	*bitmap = (unsigned char *)malloc(imageInfo->bytesPerRow * imageInfo->effectHeight);
	
	bitmapContextRef = CGBitmapContextCreate(*bitmap, 
		imageInfo->imageWidth, imageInfo->imageHeight, 
		imageInfo->bitsPerComponent, imageInfo->bytesPerRow, 
		rgbColorSpaceRef, 
		bitmapInfo);
	if(bitmapContextRef == NULL) {
		fprintf(stderr, "***BIReadFile: Error creating CGBitmapContext\n");
		ourRtn = 1;
		goto errOut;
	}

	/* enable high quality interpolation */
	CGContextSetInterpolationQuality(bitmapContextRef, kCGInterpolationHigh);

	/* Draw into the context */
	CGContextDrawImage(bitmapContextRef, CGRectMake(0, 0, imageInfo->imageWidth, imageInfo->imageHeight), 
		imageRef);

errOut:
	CFRELEASE(optionsDict);
	CFRELEASE(imageSourceRef);
	CFRELEASE(imageRef);
	CFRELEASE(rgbColorSpaceRef);
	CFRELEASE(bitmapContextRef);
	if(ourRtn) {
		if(*bitmap) {
			free(*bitmap);
			*bitmap = NULL;
		}
	}
	return ourRtn;
}
Exemple #5
0
void process_1_image (args cli_flags, char *files) {
	
	char *out_file_name = get_out_filename (files, cli_flags);
	
	if (file_exists (out_file_name)) {
		printf ("| Output file %s already exists. skipping... ", out_file_name);
		return;
	}
	
	// Origional Image Properties struct
	img_prop o = (img_prop) malloc (sizeof (image_properties));
	
	// set all the vales in the imapg properties struct to -1
	null_ip (o);
	
	// Create a data provider
	CGDataProviderRef source_image_provider = CGDataProviderCreateWithFilename (files);
	
	// Check for a null returned value
	if (source_image_provider == NULL) {
		
		// something went wrong 
		printf ("error: Couldn't create CGDataProvider from URL.\n"); 
		exit (0);
	}
	
	// get the information from the image exif here
	o->image_rot = get_exif_rot (source_image_provider);
	

	// Create the image in memory from the JPEG data
	CGImageRef source_image = CGImageCreateWithJPEGDataProvider (source_image_provider, NULL, no, kCGRenderingIntentDefault);
	
  /********************************************/
  /* Getting the colour space **/
  
  o->colorSpace = CGImageGetColorSpace(source_image);
  
  /********************************************/
  
	// populate the image info struct
	pop_img_props (source_image, o);
	
	// create a data provider from the decoded JPEG data
	CGDataProviderRef image_data_provider = CGImageGetDataProvider (source_image);
	
	// Create a pointer to the data section of the image in memory
	CFDataRef source_data_ptr = CGDataProviderCopyData (image_data_provider);

	// The vImage_Buffers we will use
	vImage_Buffer *vImage_source = (vImage_Buffer*) malloc (sizeof (vImage_Buffer));
	
	// Check for NULL
	if (NULL == vImage_source) {
		printf ("Cannot malloc vImage_source buffer\n");
		exit (0);
	}
	
	if (o->bits_ppixel == 24) {
		
		// convert from 24bit to 32bit by adding the alpha channel.
		source_data_ptr = convert24_32bit (source_data_ptr, o);
		
	}
	
	// Setup the vImage Buffer for the image
	setupBuffer (vImage_source, o->image_h, o->image_w, o->bytes_row);

	// Assign the data to the vImage Buffer for the source
	vImage_source->data = (void *) CFDataGetBytePtr (source_data_ptr);
	
	// Check for NULL
	if (vImage_source->data == NULL) 
		printf ("Unable to get the vimage.data pointer\n");

	if (o->image_rot != 1 && o->image_rot != 4 && o->image_rot != 2) // rotate the image
		rotate_image (vImage_source, o, NULL);
	
	// flip the image
	if (o->image_rot == 2  || o->image_rot == 4 || o->image_rot == 7 || o->image_rot == 5)
		flip_image (vImage_source, o, NULL);
	
  
	// Resize the images
	resize_image (vImage_source, o, cli_flags);

    // Create a colour space to be compared against
    CGColorSpaceRef rgb = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
    if (NULL == rgb) {
        fprintf(stderr, "Unable to create the reference colourspace.\n");
        exit(0);
    }
    
    // Convert the colourspace to RGB
    if (!CFEqual(rgb, o->colorSpace) && !cli_flags->disableCC) {
        vImage_source->data = convert_space(vImage_source->data, o->image_w, o->image_h);
        if (NULL == vImage_source->data) exit(0);
    }
    
    // release the reference colour space
    CGColorSpaceRelease(rgb);
    
	// save the image
	save_image (vImage_source, o, cli_flags->quality, out_file_name);
	
	// Release the source provider
	CGDataProviderRelease (source_image_provider);
	source_image_provider = NULL;
	
	// Release the source image
	CGImageRelease (source_image);
	source_image = NULL;
	
	free(source_data_ptr);
    
	// Free the filename created by get_out_filename ()
	free (out_file_name);
	out_file_name = NULL;
	
	// free the image properties
	free (o);
	o = NULL;
	
	// if there is info in the buffer
	if (vImage_source->data != NULL) {
		free (vImage_source->data);
		vImage_source->data = NULL;
	}
	
	// free the buffer
	free (vImage_source);
	vImage_source = NULL;

} // Process 1 image
Exemple #6
0
/*
 * Given a display ID and a rectangle on that display, generate a CGImageRef
 * containing the display contents.
 *
 * srcRect is display-origin relative.
 *
 * This function uses a full screen OpenGL read-only context.
 * By using OpenGL, we can read the screen using a DMA transfer
 * when it's in millions of colors mode, and we can correctly read
 * a microtiled full screen OpenGL context, such as a game or full
 * screen video display.
 *
 * Returns a CGImageRef. When you are done with the CGImageRef, release it
 * using CFRelease().
 * Returns NULL on an error.
 */
CGImageRef grabViaOpenGL(CGDirectDisplayID display, CGRect srcRect)
{
    CGContextRef bitmap;
    CGImageRef image;
    void * data;
    long bytewidth;
    GLint width, height;
    long bytes;
    CGColorSpaceRef cSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
    
    CGLContextObj    glContextObj;
    CGLPixelFormatObj pixelFormatObj ;
    long numPixelFormats ;
    CGLPixelFormatAttribute attribs[] =
    {
        kCGLPFAFullScreen,
        kCGLPFADisplayMask,
        0,    /* Display mask bit goes here */
        0
    } ;
    
    
    if ( display == kCGNullDirectDisplay )
        display = CGMainDisplayID();
    attribs[2] = CGDisplayIDToOpenGLDisplayMask(display);
    
    
    /* Build a full-screen GL context */
    CGLChoosePixelFormat( attribs, &pixelFormatObj, (GLint *)&numPixelFormats );
    if ( pixelFormatObj == NULL )    // No full screen context support
        return NULL;
    CGLCreateContext( pixelFormatObj, NULL, &glContextObj ) ;
    CGLDestroyPixelFormat( pixelFormatObj ) ;
    if ( glContextObj == NULL )
        return NULL;
    
    
    CGLSetCurrentContext( glContextObj ) ;
    CGLSetFullScreen( glContextObj ) ;
    
    
    glReadBuffer(GL_FRONT);
    
    
    width = srcRect.size.width;
    height = srcRect.size.height;
    
    
    bytewidth = width * 4; // Assume 4 bytes/pixel for now
    bytewidth = (bytewidth + 3) & ~3; // Align to 4 bytes
    bytes = bytewidth * height; // width * height
    
    /* Build bitmap context */
    data = malloc(height * bytewidth);
    if ( data == NULL )
    {
        CGLSetCurrentContext( NULL );
        CGLClearDrawable( glContextObj ); // disassociate from full screen
        CGLDestroyContext( glContextObj ); // and destroy the context
        return NULL;
    }
    bitmap = CGBitmapContextCreate(data, width, height, 8, bytewidth,
                                   cSpace, kCGImageAlphaNoneSkipFirst /* XRGB */);
    CFRelease(cSpace);
    
    
    /* Read framebuffer into our bitmap */
    glFinish(); /* Finish all OpenGL commands */
    glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */
    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
    
    /*
     * Fetch the data in XRGB format, matching the bitmap context.
     */
    glReadPixels((GLint)srcRect.origin.x, (GLint)srcRect.origin.y, width, height,
                 GL_BGRA,
#ifdef __BIG_ENDIAN__
                 GL_UNSIGNED_INT_8_8_8_8_REV, // for PPC
#else
                 GL_UNSIGNED_INT_8_8_8_8, // for Intel! http://lists.apple.com/archives/quartz-dev/2006/May/msg00100.html
#endif
                 data);
    /*
     * glReadPixels generates a quadrant I raster, with origin in the lower left
     * This isn't a problem for signal processing routines such as compressors,
     * as they can simply use a negative 'advance' to move between scanlines.
     * CGImageRef and CGBitmapContext assume a quadrant III raster, though, so we need to
     * invert it. Pixel reformatting can also be done here.
     */
    swizzleBitmap(data, bytewidth, height);
    
    
    /* Make an image out of our bitmap; does a cheap vm_copy of the bitmap */
    image = CGBitmapContextCreateImage(bitmap);
    
    /* Get rid of bitmap */
    CFRelease(bitmap);
    free(data);
    
    
    /* Get rid of GL context */
    CGLSetCurrentContext( NULL );
    CGLClearDrawable( glContextObj ); // disassociate from full screen
    CGLDestroyContext( glContextObj ); // and destroy the context
    
    /* Returned image has a reference count of 1 */
    return image;
}
Exemple #7
0
void nuiSoftwarePainter::Display(nglWindow* pWindow, const nuiRect& rRect)
{
  if (!pWindow)
    return;
  const nglWindow::OSInfo* pInfo = pWindow->GetOSInfo();
  
  NGL_ASSERT(pInfo);

  if (!pInfo)
    return;

  //TestAgg((char*)&mBuffer[0], mWidth, mHeight);
  
  int32 x, y, w, h;
  x = ToBelow(rRect.Left());
  y = ToBelow(rRect.Top());
  w = ToBelow(rRect.GetWidth());
  h = ToBelow(rRect.GetHeight());
  int32 offset = (x + mWidth * y);
  
#ifdef _WIN32_
  HDC hdc = GetDC(pInfo->GLWindowHandle);

  BITMAPV5HEADER bminfo;

  // BITMAPV5HEADER
  bminfo.bV5Size = sizeof(BITMAPV5HEADER);
  bminfo.bV5Width = (LONG)mWidth;
  bminfo.bV5Height = -(LONG)mHeight;
  bminfo.bV5Planes = 1;
  bminfo.bV5BitCount = 32;
  bminfo.bV5Compression = BI_RGB;
  bminfo.bV5SizeImage = 0;
  bminfo.bV5XPelsPerMeter = 0;
  bminfo.bV5YPelsPerMeter = 0;
  bminfo.bV5ClrUsed = 0;
  bminfo.bV5ClrImportant =0;

  bminfo.bV5RedMask = 0;
  bminfo.bV5GreenMask = 0;
  bminfo.bV5BlueMask = 0;
  bminfo.bV5AlphaMask = 0;

  bminfo.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
  bminfo.bV5Endpoints.ciexyzRed.ciexyzX = 0;
  bminfo.bV5Endpoints.ciexyzRed.ciexyzY = 0;
  bminfo.bV5Endpoints.ciexyzRed.ciexyzZ = 0;
  bminfo.bV5Endpoints.ciexyzGreen.ciexyzX = 0;
  bminfo.bV5Endpoints.ciexyzGreen.ciexyzY = 0;
  bminfo.bV5Endpoints.ciexyzGreen.ciexyzZ = 0;
  bminfo.bV5Endpoints.ciexyzBlue.ciexyzX = 0;
  bminfo.bV5Endpoints.ciexyzBlue.ciexyzY = 0;
  bminfo.bV5Endpoints.ciexyzBlue.ciexyzZ = 0;
  bminfo.bV5GammaRed = 0;
  bminfo.bV5GammaGreen = 0;
  bminfo.bV5GammaBlue = 0;
  bminfo.bV5Intent = LCS_GM_IMAGES;
  bminfo.bV5ProfileData = 0;
  bminfo.bV5ProfileSize = 0;

  bminfo.bV5Reserved = 0;

  RECT r;
  GetClientRect(pInfo->GLWindowHandle, &r);

  r.right = (LONG)mWidth;
  r.bottom = (LONG)mHeight;

  uint32* pBuffer = mpRasterizer->GetBuffer();
/*
  for (uint32 i = 0; i < mWidth * mHeight; i++)
    pBuffer[i] = rand();
*/

  SetDIBitsToDevice(
    hdc,              // handle to DC
    x,                // x-coord of destination upper-left corner
    y,                // y-coord of destination upper-left corner
    w,          // width of destination rectangle
    h,         // height of destination rectangle
    x,                // x-coord of source upper-left corner
    mHeight - h - y,                // y-coord of source upper-left corner

    0,                // first scan line
    (LONG)mHeight,    // number of scan lines

    pBuffer,          // bitmap bits
    (const BITMAPINFO*)&bminfo,          // bitmap data
    DIB_RGB_COLORS    // usage options
    );

  ReleaseDC(pInfo->GLWindowHandle, hdc);

#elif (defined _CARBON_)

  WindowRef win = pInfo->WindowHandle;
  if (!win)
    win = pInfo->Parent;
  
  //CGContextRef myMemoryContext;
  CGColorSpaceRef cspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
  CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, mpRasterizer->GetBuffer() + offset, mWidth * h * 4, NULL);
  
  CGImageRef img = CGImageCreate(
                                 w,
                                 h,
                                 8,
                                 32,
                                 mWidth * 4,
                                 cspace,
                                 kCGBitmapByteOrder32Host | kCGImageAlphaNoneSkipFirst,
                                 provider,
                                 NULL,
                                 0,
                                 kCGRenderingIntentDefault
                                 );
  
  CGContextRef myContext;
  
  SetPortWindowPort (win);// 1
  QDBeginCGContext (GetWindowPort (win), &myContext);

  CGRect rect = CGRectMake(x, mHeight - h - y, w, h);
  CGContextDrawImage(myContext, rect, img);
  
  QDEndCGContext (GetWindowPort(win), &myContext);  
          
#endif
}
Exemple #8
0
int main(int argc, char* argv[])
{
	// check the correct BASS was loaded
	if (HIWORD(BASS_GetVersion())!=BASSVERSION) {
		Error("An incorrect version of BASS was loaded");
		return 0;
	}

	// initialize BASS
	if (!BASS_Init(-1,44100,0,win,NULL)) {
		Error("Can't initialize device");
		return 0;
	}
	if (!PlayFile()) { // start a file playing
		BASS_Free();
		return 0;
	}

	// create the window
	Rect wr;
	wr.left=200;
	wr.right=wr.left+SPECWIDTH;
	wr.top=200;
	wr.bottom=wr.top+SPECHEIGHT;
	CreateNewWindow(kMovableModalWindowClass,kWindowStandardHandlerAttribute,&wr,&win);
	SetWindowTitleWithCFString(win,CFSTR("BASS spectrum example (click to toggle mode)"));
	ChangeWindowAttributes(win,kWindowAsyncDragAttribute,kWindowNoAttributes);
	{
		EventTypeSpec etype={kEventClassWindow,kEventWindowDrawContent};
		InstallWindowEventHandler(win,NewEventHandlerUPP(EventWindowDrawContent),1,&etype,0,NULL);
		etype.eventKind=kEventWindowHandleContentClick;
		InstallWindowEventHandler(win,NewEventHandlerUPP(EventWindowClick),1,&etype,0,NULL);
	}

	// create the bitmap
	CGColorSpaceRef colorSpace=CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
	specdc=CGBitmapContextCreate(specbuf,SPECWIDTH,SPECHEIGHT,8,SPECWIDTH*4,colorSpace,kCGImageAlphaNoneSkipLast);
	CGColorSpaceRelease(colorSpace);

	{ // setup palette
		RGBQUAD *pal=(RGBQUAD*)palette;
		int a;
		memset(palette,0,sizeof(palette));
		for (a=1;a<128;a++) {
			pal[a].rgbGreen=256-2*a;
			pal[a].rgbRed=2*a;
		}
		for (a=0;a<32;a++) {
			pal[128+a].rgbBlue=8*a;
			pal[128+32+a].rgbBlue=255;
			pal[128+32+a].rgbRed=8*a;
			pal[128+64+a].rgbRed=255;
			pal[128+64+a].rgbBlue=8*(31-a);
			pal[128+64+a].rgbGreen=8*a;
			pal[128+96+a].rgbRed=255;
			pal[128+96+a].rgbGreen=255;
			pal[128+96+a].rgbBlue=8*a;
		}
	}

	ShowWindow(win);
	
	// setup update timer (40hz)
	EventLoopTimerRef timer;
	InstallEventLoopTimer(GetCurrentEventLoop(),kEventDurationNoWait,kEventDurationSecond/40,NewEventLoopTimerUPP(UpdateSpectrum),0,&timer);

	RunApplicationEventLoop();

    CGContextRelease(specdc);
	DisposeWindow(win);
	BASS_Free();
	return 0;	
}
Exemple #9
0
CGColorSpaceRef          CGColorSpaceCreateGenericRGB_wrap() { return CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); }
Exemple #10
0
CGColorSpaceRef          CGColorSpaceCreateGenericCMYK_wrap() { return CGColorSpaceCreateWithName(kCGColorSpaceGenericCMYK); }
Exemple #11
0
CGColorSpaceRef          CGColorSpaceCreateGenericGray_wrap() { return CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); }
Exemple #12
0
bool  ImageIODecoder::readData( Mat& img )
{
    uchar* data = img.data;
    int step = img.step;
    bool color = img.channels() > 1;
    int bpp; // Bytes per pixel
    int bit_depth = 8;

    // Get Height, Width, and color information
    if( !readHeader() )
        return false;

    CGContextRef     context = NULL; // The bitmap context
    CGColorSpaceRef  colorSpace = NULL;
    uchar*           bitmap = NULL;
    CGImageAlphaInfo alphaInfo;

    // CoreGraphics will take care of converting to grayscale and back as long as the
    // appropriate colorspace is set
    if( color == CV_LOAD_IMAGE_GRAYSCALE )
    {
        colorSpace = CGColorSpaceCreateDeviceGray();
        bpp = 1;
        alphaInfo = kCGImageAlphaNone;
    }
    else if( color == CV_LOAD_IMAGE_COLOR )
    {
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
        colorSpace = CGColorSpaceCreateDeviceRGB();
#else
        colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGBLinear );
#endif
        bpp = 4; /* CG only has 8 and 32 bit color spaces, so we waste a byte */
        alphaInfo = kCGImageAlphaNoneSkipLast;
    }
    if( !colorSpace )
        return false;

    bitmap = (uchar*)malloc( bpp * m_height * m_width );
    if( !bitmap )
    {
        CGColorSpaceRelease( colorSpace );
        return false;
    }

    context = CGBitmapContextCreate( (void *)bitmap,
                                     m_width,        /* width */
                                     m_height,       /* height */
                                     bit_depth,    /* bit depth */
                                     bpp * m_width,  /* bytes per row */
                                     colorSpace,     /* color space */
                                     alphaInfo);

    CGColorSpaceRelease( colorSpace );
    if( !context )
    {
        free( bitmap );
        return false;
    }

    // Copy the image data into the bitmap region
    CGRect rect = {{0,0},{m_width,m_height}};
    CGContextDrawImage( context, rect, imageRef );

    uchar* bitdata = (uchar*)CGBitmapContextGetData( context );
    if( !bitdata )
    {
        free( bitmap);
        CGContextRelease( context );
        return false;
    }

    // Move the bitmap (in RGB) into data (in BGR)
    int bitmapIndex = 0;

    if( color == CV_LOAD_IMAGE_COLOR )
    {
        uchar * base = data;

        for (int y = 0; y < m_height; y++)
        {
            uchar * line = base + y * step;

            for (int x = 0; x < m_width; x++)
            {
                // Blue channel
                line[0] = bitdata[bitmapIndex + 2];
                // Green channel
                line[1] = bitdata[bitmapIndex + 1];
                // Red channel
                line[2] = bitdata[bitmapIndex + 0];

                line        += 3;
                bitmapIndex += bpp;
            }
        }
    }
    else if( color == CV_LOAD_IMAGE_GRAYSCALE )
    {
        for (int y = 0; y < m_height; y++)
            memcpy (data + y * step, bitmap + y * m_width, m_width);
    }

    free( bitmap );
    CGContextRelease( context );
    return true;
}
Exemple #13
0
bool  ImageIOEncoder::write( const Mat& img, const vector<int>& params )
{
    int width = img.cols, height = img.rows;
    int _channels = img.channels();
    const uchar* data = img.data;
    int step = img.step;

    // Determine the appropriate UTI based on the filename extension
    CFStringRef imageUTI = FilenameToUTI( m_filename.c_str() );

    // Determine the Bytes Per Pixel
    int bpp = (_channels == 1) ? 1 : 4;

    // Write the data into a bitmap context
    CGContextRef context;
    CGColorSpaceRef colorSpace;
    uchar* bitmapData = NULL;

    if( bpp == 1 ) {
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
        colorSpace = CGColorSpaceCreateDeviceGray();
#else
        colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericGray );
#endif
    }
    else if( bpp == 4 ) {
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
        colorSpace = CGColorSpaceCreateDeviceRGB();
#else
        colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGBLinear );
#endif
    }
    if( !colorSpace )
        return false;

    bitmapData = (uchar*)malloc( bpp * height * width );
    if( !bitmapData )
    {
        CGColorSpaceRelease( colorSpace );
        return false;
    }

    context = CGBitmapContextCreate( bitmapData,
                                     width,
                                     height,
                                     8,
                                     bpp * width,
                                     colorSpace,
                                     (bpp == 1) ? kCGImageAlphaNone :
                                     kCGImageAlphaNoneSkipLast );
    CGColorSpaceRelease( colorSpace );
    if( !context )
    {
        free( bitmapData );
        return false;
    }

    // Copy pixel information from data into bitmapData
    if (bpp == 4)
    {
        int           bitmapIndex = 0;
        const uchar * base        = data;

        for (int y = 0; y < height; y++)
        {
            const uchar * line = base + y * step;

            for (int x = 0; x < width; x++)
            {
                // Blue channel
                bitmapData[bitmapIndex + 2] = line[0];
                // Green channel
                bitmapData[bitmapIndex + 1] = line[1];
                // Red channel
                bitmapData[bitmapIndex + 0] = line[2];

                line        += 3;
                bitmapIndex += bpp;
            }
        }
    }
    else if (bpp == 1)
    {
        for (int y = 0; y < height; y++)
            memcpy (bitmapData + y * width, data + y * step, width);
    }

    // Turn the bitmap context into an imageRef
    CGImageRef imageRef = CGBitmapContextCreateImage( context );
    CGContextRelease( context );
    if( !imageRef )
    {
        free( bitmapData );
        return false;
    }

    // Write the imageRef to a file based on the UTI
    CFURLRef imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL,
        (const UInt8*)m_filename.c_str(), m_filename.size(), false );
    if( !imageURLRef )
    {
        CGImageRelease( imageRef );
        free( bitmapData );
        return false;
    }

    CGImageDestinationRef destRef = CGImageDestinationCreateWithURL( imageURLRef,
                                                                     imageUTI,
                                                                     1,
                                                                     NULL);
    CFRelease( imageURLRef );
    if( !destRef )
    {
        CGImageRelease( imageRef );
        free( bitmapData );
        fprintf(stderr, "!destRef\n");
        return false;
    }

    CGImageDestinationAddImage(destRef, imageRef, NULL);
    if( !CGImageDestinationFinalize(destRef) )
    {
        fprintf(stderr, "Finalize failed\n");
        return false;
    }

    CFRelease( destRef );
    CGImageRelease( imageRef );
    free( bitmapData );

    return true;
}
Exemple #14
0
Memsubfont*
mksubfont(XFont *f, char *name, int lo, int hi, int size, int antialias)
{
	CFStringRef s;
	CGColorSpaceRef color;
	CGContextRef ctxt;
	CTFontRef font;
	CTFontDescriptorRef desc;
	CGRect bbox;
	Memimage *m, *mc, *m1;
	int x, y, y0;
	int i, height, ascent;
	Fontchar *fc, *fc0;
	Memsubfont *sf;
	CGFloat whitef[] = { 1.0, 1.0 };
	CGColorRef white;

	s = c2mac(name);
	desc = CTFontDescriptorCreateWithNameAndSize(s, size);
	CFRelease(s);
	if(desc == nil)
		return nil;
	font = CTFontCreateWithFontDescriptor(desc, 0, nil);
	CFRelease(desc);
	if(font == nil)
		return nil;
	
	
	bbox = CTFontGetBoundingBox(font);
	x = (int)(bbox.size.width*2 + 0.99999999);

	fontheight(f, size, &height, &ascent);
	y = height;
	y0 = height - ascent;

	m = allocmemimage(Rect(0, 0, x*(hi+1-lo)+1, y+1), GREY8);
	if(m == nil)
		return nil;
	mc = allocmemimage(Rect(0, 0, x+1, y+1), GREY8);
	if(mc == nil){
		freememimage(m);
		return nil;
	}
	memfillcolor(m, DBlack);
	memfillcolor(mc, DBlack);
	fc = malloc((hi+2 - lo) * sizeof fc[0]);
	sf = malloc(sizeof *sf);
	if(fc == nil || sf == nil) {
		freememimage(m);
		freememimage(mc);
		free(fc);
		free(sf);
		return nil;
	}
	fc0 = fc;

	color = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
	ctxt = CGBitmapContextCreate(byteaddr(mc, mc->r.min), Dx(mc->r), Dy(mc->r), 8,
		mc->width*sizeof(u32int), color, kCGImageAlphaNone);
	white = CGColorCreate(color, whitef);
	CGColorSpaceRelease(color);
	if(ctxt == nil) {
		freememimage(m);
		freememimage(mc);
		free(fc);
		free(sf);
		return nil;
	}

	CGContextSetAllowsAntialiasing(ctxt, antialias);
	CGContextSetTextPosition(ctxt, 0, 0);	// XXX
#if OSX_VERSION >= 101400
	CGContextSetAllowsFontSmoothing(ctxt, false);
#endif

	x = 0;
	for(i=lo; i<=hi; i++, fc++) {
		char buf[20];
		CFStringRef str;
		CFDictionaryRef attrs;
		CFAttributedStringRef attrString;
		CTLineRef line;
		CGRect r;
		CGPoint p1;
		CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName };
		CFTypeRef values[] = { font, white };

		sprint(buf, "%C", (Rune)mapUnicode(name, i));
 		str = c2mac(buf);
 		
 		// See https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/CoreText_Programming/LayoutOperations/LayoutOperations.html#//apple_ref/doc/uid/TP40005533-CH12-SW2
 		attrs = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys,
			(const void**)&values, sizeof(keys) / sizeof(keys[0]),
			&kCFTypeDictionaryKeyCallBacks,
			&kCFTypeDictionaryValueCallBacks);
		attrString = CFAttributedStringCreate(kCFAllocatorDefault, str, attrs);
		CFRelease(str);
		CFRelease(attrs);

		line = CTLineCreateWithAttributedString(attrString);
		CGContextSetTextPosition(ctxt, 0, y0);
		r = CTLineGetImageBounds(line, ctxt);
		memfillcolor(mc, DBlack);
		CTLineDraw(line, ctxt);		
		CFRelease(line);

		fc->x = x;
		fc->top = 0;
		fc->bottom = Dy(m->r);

//		fprint(2, "printed %#x: %g %g\n", mapUnicode(i), p1.x, p1.y);
		p1 = CGContextGetTextPosition(ctxt);
		if(p1.x <= 0 || mapUnicode(name, i) == 0xfffd) {
			fc->width = 0;
			fc->left = 0;
			if(i == 0) {
				drawpjw(m, fc, x, (int)(bbox.size.width + 0.99999999), y, y - y0);
				x += fc->width;
			}	
			continue;
		}

		memimagedraw(m, Rect(x, 0, x + p1.x, y), mc, ZP, memopaque, ZP, S);
		fc->width = p1.x;
		fc->left = 0;
		x += p1.x;
	}
	fc->x = x;

	// round up to 32-bit boundary
	// so that in-memory data is same
	// layout as in-file data.
	if(x == 0)
		x = 1;
	if(y == 0)
		y = 1;
	if(antialias)
		x += -x & 3;
	else
		x += -x & 31;
	m1 = allocmemimage(Rect(0, 0, x, y), antialias ? GREY8 : GREY1);
	memimagedraw(m1, m1->r, m, m->r.min, memopaque, ZP, S);
	freememimage(m);
	freememimage(mc);

	sf->name = nil;
	sf->n = hi+1 - lo;
	sf->height = Dy(m1->r);
	sf->ascent = Dy(m1->r) - y0;
	sf->info = fc0;
	sf->bits = m1;
	
	return sf;
}
Exemple #15
0
static void
fontheight(XFont *f, int size, int *height, int *ascent)
{
	int i;
	CFStringRef s;
	CGRect bbox;
	CTFontRef font;
	CTFontDescriptorRef desc;
	CGContextRef ctxt;
	CGColorSpaceRef color;

	s = c2mac(f->name);
	desc = CTFontDescriptorCreateWithNameAndSize(s, size);
	CFRelease(s);
	if(desc == nil)
		return;
	font = CTFontCreateWithFontDescriptor(desc, 0, nil);
	CFRelease(desc);
	if(font == nil)
		return;

	color = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
	ctxt = CGBitmapContextCreate(nil, 1, 1, 8, 1, color, kCGImageAlphaNone);
	CGColorSpaceRelease(color);
	CGContextSetTextPosition(ctxt, 0, 0);

	for(i=0; i<nelem(lines); i++) {
		CFStringRef keys[] = { kCTFontAttributeName };
		CFTypeRef values[] = { font };
		CFStringRef str;
		CFDictionaryRef attrs;
		CFAttributedStringRef attrString;
		CGRect r;
		CTLineRef line;

 		str = c2mac(lines[i]);
 		
 		// See https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/CoreText_Programming/LayoutOperations/LayoutOperations.html#//apple_ref/doc/uid/TP40005533-CH12-SW2
 		attrs = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys,
			(const void**)&values, sizeof(keys) / sizeof(keys[0]),
			&kCFTypeDictionaryKeyCallBacks,
			&kCFTypeDictionaryValueCallBacks);
		attrString = CFAttributedStringCreate(kCFAllocatorDefault, str, attrs);
		CFRelease(str);
		CFRelease(attrs);

		line = CTLineCreateWithAttributedString(attrString);
		r = CTLineGetImageBounds(line, ctxt);
		r.size.width += r.origin.x;
		r.size.height += r.origin.y;
		CFRelease(line);
		
//	fprint(2, "%s: %g %g %g %g\n", lines[i], r.origin.x, r.origin.y, r.size.width, r.size.height);
		
		if(i == 0)
			bbox = r;
		if(bbox.origin.x > r.origin.x)
			bbox.origin.x = r.origin.x;	
		if(bbox.origin.y > r.origin.y)
			bbox.origin.y = r.origin.y;	
		if(bbox.size.width < r.size.width)
			bbox.size.width = r.size.width;
		if(bbox.size.height < r.size.height)
			bbox.size.height = r.size.height;
	}

	bbox.size.width -= bbox.origin.x;
	bbox.size.height -= bbox.origin.y;

	*height = bbox.size.height + 0.999999;
	*ascent = *height - (-bbox.origin.y + 0.999999);
		
	CGContextRelease(ctxt);
	CFRelease(font);
}