How can I increase the bit depth of an image while keeping it transparent? - swift

I am using UIGraphicsBeginImageContext(canvasRect.size) to export images, but because UIGraphicsBeginImageContext uses only 8-bit context, the exported image has the original image's The color representation was dropped, resulting in a blurry appearance.
Therefore, we changed the code to UIGraphicsBeginImageContextWithOptions(canvasRect.size, true, 1.0).
The original image was successfully exported as a clean image with no loss of color representation, but transparency is no longer represented because opaque was set to true.
Please let me know if you know how to increase the bit rate while keeping the transparency of the image.
Please let me know if there is any other method other than UIGraphicsBeginImageContextWithOptions that can be used to export an image while preserving the color representation of the image.

Related

Can a PNG image that is entirely opaque contain an alpha channel?

Is it possible to construct a png image, that is entirely opaque (that means every pixel in the image is opaque) but the image data itself has an alpha channel ?
Why is it that some PNG images don't have an alpha channel ?
Yes. Just like an RGB image may contain only data in the Red channel and not in Green and Blue; "unused" channels are not a problem. Alpha is a separate channel of its own, and in particular, its values should be independent of the associated pixel colors: "PNG does not use premultiplied alpha" (6.2 Alpha representation).
Also see 12.4 Alpha channel creation in the official specifications for some additional details:
The alpha channel can be regarded either as a mask that temporarily hides transparent parts of the image, or as a means for constructing a non-rectangular image. In the first case, the colour values of fully transparent pixels should be preserved for future use. In the second case, the transparent pixels carry no useful data and are simply there to fill out the rectangular image area required by PNG. In this case, fully transparent pixels should all be assigned the same colour value for best compression.
Because they don't need to, per that same specification:
... PNG provides a patent-free replacement for GIF and can also replace many common uses of TIFF. Indexed-color, grayscale, and truecolor images are supported, plus an optional alpha channel. (my emphasis)

How to convert a black and white photo that was originally colored, back to its original color?

I've converted a colored photo to black and white, and bolded the edges. Now i need to convert it back to its original color with the bolded edges. Is there any function in matlab which allows me to do so?
Once you remove the colour from an image, there is no possible way to automatically put it back. You're basically reducing a set of 16,777,216 colours to a set of 256 - on average each shade of grey has 65,536 equivalent colours, and without the original image there's no way to guess which it could be.
Now, if you were to take the bolded lines from your black-and-white image and paint them on top of the original coloured image, that might end up producing what you're looking for.
If what you are trying to do is to use some filter over the B/W image and then use that with the original color. I suggest you convert your image to a color space with Lightness channel that suits your needs (for example L*a*b* if you need the ligtness to be uniformly distributed regarding human recognition of differences) and apply your filter only over the Lightness channel.

Transparency with JPEGs

JPEGs are smaller in size than PNGs. So, I thought that if I can make a specific region in a JPEG-file transparent, with some code, maybe I can save some bytes.
So does anyone know how to achieve this with for example PHP or JavaScript?
No. You can't do this. JPGs do not support alpha channels and have no capacity to designate certain colors as transparent either (GIF-style).
There's several issues with this, all of them have to do with that JPEG is a lossy compression format. The JPEG format is optimized for natural images and sharp edges will get blurred. If you intend that a specific pixel should have the value #d67fff there's no guarantee that after color conversion, FDCT, quantization, IDCT and color conversion, the pixel still will have that value. There's also a strong possibility that that pixel value will occur in areas that you don't want.
No. JPEG does not support transparency and is not likely to do so any time
soon. http://www.faqs.org/faqs/jpeg-faq/part1/section-12.html
You cannot do that, the client renders the image and doesn't know that you want it to treat that color as transparent (plus various compression methods on jpeg wouldn't work well with transparencies anyway).
I believe you can go with an 8-bit custom-pallet png, should save you a lot of space. Otherwise 24-bit PNG is your only high color option.
You can convert your image to SVG containing a color information as JPEG and an alpha channel as grayscale mask. Here is a tool I wrote to do it https://github.com/igrmk/transpeg

What's the difference between an CGImageRef that is a mask, and one that is not a mask?

I discovered that CGBitmapContextCreateImage() creates an image, which is not neccessarily always a mask compatible with CGContextClipToMask(). But when using CGImageMaskCreate(), the CGImageRef is always a mask that works with CGContextClipToMask(). Now, what is so special about the mask VS. the "normal" image?
My guess is that the mask is grayscale only, where as an CGImageRef created with CGBitmapContextCreateImage() may have RGBA values which irritate CGContextClipToMask(). I couldn't find the spot in the documentation where the exact difference between masks and CG images is explained.
But it seems that an Core Graphics image != a mask, while a mask == a Core Graphics Image
Every value in an image, be it RGB, CMYK or Greyscale, represents a position in a particular colorspace. It is meaningful to ask "What would this value be in colour-space 'x'?" - and the result would, if possible, be the same colour, but could be a different numerical value.
eg (simplistically). A pixel with value (255,255,255) is White in an RGB colorspace but Black in a (hypothetical) CMY colour-space. Converting the White RGB pixel to the CMY colorspace would give the value (0,0,0). In other words an Image must have a colorspace, it only makes sense given a colorspace.
On the contrary, an 8bit mask represents absolute values between 0-255. There is no colorspace and it makes no sense to think of a mask in a particular colorspace.
In that way images and masks are fundamentally different, even though we often think of masks as greyscale images.
An image mask in Core Graphics is a special kind of image. From the CGImageMaskCreate reference:
A Quartz bitmap image mask is used the same way an artist uses a silkscreen, or a sign painter uses a stencil. The bitmap represents a mask through which a color is transferred. The bitmap itself does not have a color. It gets its color from the fill color currently set in the graphics state.
When you draw into a context with a bitmap image mask, Quartz uses the mask to determine where and how the current fill color is applied to the image rectangle. Each sample value in the mask specifies how much of the current fill color is masked out at a specific location. Effectively, the sample value specifies the opacity of the mask. Larger values represent greater opacity and hence less color applied to the page.
See more here: http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CGImage/Reference/reference.html

Writing a masked image to disk as a PNG file

Basically I'm downloading images off of a webserver and then caching them to the disk, but before I do so I want to mask them.
I'm using the masking code everyone seems to point at which can be found here:
http://iosdevelopertips.com/cocoa/how-to-mask-an-image.html
What happens though, is that the image displays fine, but the version that gets written to the disk with
UIImage *img = [self maskImage:[UIImage imageWithData:data] withMask:self.imageMask];
[UIImagePNGRepresentation(img) writeToFile:cachePath atomically:NO];
has it's alpha channel inverted when compared to the one displayed later on (using the same UIImage instance here).
Any ideas? I do need the cached version to be masked, otherwise displaying the images in a table view get's awfully slow if I have to mask them every time.
Edit: So yeah, UIImagePNGRepresentation(img) seems to invert the alpha channel, doesn't have anything to do with the code that writes to disk, which is rather obvious but I checked anyway.
How about drawing into a new image, and then save that?
UIGraphicsBeginImageContext(img.size);
[img drawAtPoint:CGPointZero];
UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[UIImagePNGRepresentation(newImg) writeToFile:cachePath atomically:NO];
(untested)
See the description in CGImageCreateWithMask in CGImage Reference:
The resulting image depends on whether the mask parameter is an image mask or an image. If the mask parameter is an image mask, then the source samples of the image mask act as an inverse alpha value. That is, if the value of a source sample in the image mask is S, then the corresponding region in image is blended with the destination using an alpha value of (1-S). For example, if S is 1, then the region is not painted, while if S is 0, the region is fully painted.
If the mask parameter is an image, then it serves as an alpha mask for blending the image onto the destination. The source samples of mask' act as an alpha value. If the value of the source sample in mask is S, then the corresponding region in image is blended with the destination with an alpha of S. For example, if S is 0, then the region is not painted, while if S is 1, the region is fully painted.
It seems for some reason the image mask is treated as a mask image to mask with while saving. According to:
UIImagePNGRepresentation and masked images
http://lists.apple.com/archives/quartz-dev/2010/Sep/msg00038.html
to correctly save with UIImagePNGRepresentation, there are several choices:
Use inverse version of the image mask.
Use "mask image" instead of "image mask".
Render to a bitmap context and then save it, like epatel mentioned.