create a new image with only masked part (without transparent area) with new size - objective-c

I have a mask and an image on which mask is applied to get a portion of that image.
The problem is when I apply that mask on the image ,the resultant image from masking is of same size as the original image .Though the unmasked part is transparent. What I need is an image which only has the masked part of the original image ,I dont want transparent part to be in the image. so that the resultant image will be of smaller size an contain only the masked part.
Thanks

You can:
Draw the image to a new CGBitmapContext at actual size, providing a buffer for the bitmap. CGBitmapContextCreate
Read alpha values from the bitmap to determine the transparent boundaries. You will have to determine how to read this based on the pixel data you have specified.
Create a new CGBitmapContext providing the external buffer, using some variation or combination of: a) a pixel offset, b) offset bytes per row, or c) manually move the bitmap's data (in place to reduce memory usage, if possible). CGBitmapContextCreate
Create a CGImage from the second bitmap context. CGBitmapContextCreateImage

Related

Accessing pixel values from destination image of CopyMakeBorder function in Emgu CV

A little bit new to EmguCV here
Just want to ask quick question, about CopyMakeBorder function
Are the pixel values of the destination image accessible?
I want to process further the destination image, but when I tried to access pixel values from the image, it only returns me 0 (even in the location that are not supposed to be 0, for example the central pixel). When I used Imshow, it shows that the image borders are perfectly processed, but problem only persist when I try to access the pixel values, only getting 0 wherever the pixel location is.
This is not a problem when I tried to use destination images from other EmguCV functions, such as Threshold Function
Can anyone clarify? Thanks A lot!!
I am using VB.net, here is the code (I am away from my workstation for the weekend so I am just gonna try to remember the code, probably some capital letters here and there are mistyped, but I hope you get the gist.)
First I initialize the source images and destination image
Dim img As Image(Of Gray,Byte) = New Image (Of Gray, Byte)("myimage.jpg")
Dim img1 As Image(Of Gray,Byte) = New Image (Of Gray, Byte)(img.size)
CopyMakeBorder Function, extend 1 pixel to top, bottom, left and right. Border type constant 0 values
Cvinvoke.CopyMakeBorder(img,img1,1,1,1,1,BorderType.Constant, New MCvscalar(0))
Accessing pixel values from destination image, take example pixel in x = 100, y = 100, and channel 0 (as it is a grayscale image)
Console.writeline(img1.data(100,100,0))
This will make debug output to 0, and no matter where I try to take the pixel values, it is still 0, even though when I try to show the image that specific pixel should not be 0 (it is not black)
Cvinvoke.Imshow("test",img1)
You are trying to access the data through Image.Data, however, this doesn't include the added border(s); just the original bitmap.
The added border is in the Mat property, however. Through it the individual pixels can be accessed
' returns data from original bitmap
Console.WriteLine(img1.Data(100, 100, 0))
' returns data from modified bitmap
Console.WriteLine(img1.Mat.GetData(100, 100)(0))

TCPDF - Cropping polygons

I'm using TCPDF::Polygon() to render coastline (land) coordinates from a text file on top of a blue TCPDF::Rect(). The text file contains coastlines for the entire world, however by specifying a center latitude and longitude in the map projection, together with some multiplication to get a 'zooming' effect, I manage to display the desired area within the A4 page.
Problem:
As you can see by the image the coastlines are drawn all the way to the edge of the document (and beyond). Although most of the coastline coordinates from the text file are 'outside' the document's visible area they are still taking up some hundred kilobytes in the output file.
Is there a nice way to 'crop' the coastline-polygon, so that the coastlines fit nicely inside the blue area and the excess vertecies are completely excluded from the document (not taking up file space)?
Solution:
The 'cropping' I was looking for is done using clipping, as suggested by #Rad Lexus:
// Start clipping
$pdf->StartTransform();
// Draw clipping rectangle
$pdf->Rect($DOC_MARG, $DOC_MARG, $MAP_W, $MAP_H, 'CNZ');
// -- Draw all polygons here (land areas) --
// Stop clipping
$pdf->StopTransform();
Source: https://stackoverflow.com/a/9400490/2667737
To save space in the output file I check every pixel in each polygon (land area) and render only the polygons that has one or more pixels within the bounds of the page - also suggested by #Rad. In the example view in my first post, the size was halved using this method.
Thanks for the help!

how can a 512x512 bmp image have 1MB of size

my code to save bmp format:
ImgResult.Save(dlgSavePicture.FileName, System.Drawing.Imaging.ImageFormat.Bmp)
I have tried the code and the output is a 512x512 bmp image with 1 megabyte size
if i use ms paint to create a 515x512 bmp image, the size is 768kb
i have tried to open the image and resave as bmp and the size still 1MB
can a 512x512 bmp image size upto 1mb in 512x512? or there are something wrong with my code?
BMP is a very simple image file format. Just a little header that describes the image (size, pixel format, resolution, color table), followed by a blob of pixel data. Technically it can be compressed with RLE but encoders don't bother anymore. The pixel data depends on the pixel format, ancient ones are 1bpp, 4bpp and 8bpp, they require a color table. 16bpp can happen, unusual, normal ones are 24bpp (RGB) and 32bpp (ARGB). In other words, 3 or 4 bytes per pixel.
So yes, 512 x 512 x 4 ~= 1 megabyte. MSPaint is pretty explicit about the pixel format it uses. It is a very simple painting program without support for alpha blending effects. So uses 24bpp (no alpha), 512 x 512 x 3 ~= 786 kilobytes. You could use Paint.NET to create 32bpp BMPs.
Which one you get in your own program depends on how you created the Bitmap object. The simple version uses the same pixel format as the video adapter. On all modern machines that's 32bpp. 16bpp can happen, it is very unusual. If you want another format then you have to use the Bitmap constructor that takes a PixelFormat argument.
There's otherwise a pretty good reason to do this, the default pixel format is not usually the most optimal one. The best one by a factor of 10 is the format that matches the pixel format of the video adapter exactly. Choice is between 32bppArgb and 32bppPArgb. The P means "pre-multiplied", the alpha value is applied to the RGB values up front. Argb is most efficient if you do a lot of drawing into the bitmap yourself with Graphics.FromImage(). PArgb is most efficient for painting, the pixel data can be blitted to the video frame buffer directly without having to be converted. Ten times faster. You usually care about painting speed, the most visible artifact of a program.
If you care about image file size then there is no better choice than PNG. It compresses the pixel data with LZW compression, typical compression rates are 50% or better. JPEG is a decent choice as well, much higher compression rates, but it is lossy. It achieves high rates by throwing away image details. Suitable for photos, in general images without text or line art, that don't otherwise have to be compressed multiple times.
i have tried this code
Public Function ConvertTo24bpp(img As Image) As Bitmap
Dim bmp = New Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb)
Using gr = Graphics.FromImage(bmp)
gr.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height))
End Using
Return bmp
End Function
ImgResult = New Bitmap(Original)
For j = 0 To Original.Height - 1
For i = 0 To Original.Width - 1
ImgResult.SetPixel(i, j, Color.FromArgb(resultArray2(j, i, 0), originalArray(j, i, 1), resultArray2(j, i, 2)))
Next
Next
Dim clone As Bitmap
clone = ConvertTo24bpp(ImgResult)
clone.Save(dlgSavePicture.FileName)
the output is 24bit 512x512 bmp image but it size is ~640 KB not ~678 KB
i think the output is png format with bmp extension
is my code gone wrong?

Creating Image from pixel data with CGBitmapContextCreate

I am trying to write code that can crop an existing image down to some specified size/region. I am working with DICOM images, and the API I am using allows me to get pixel values directly. I've placed pixel values of the area of interest within the image into an array of floats (dstImage, below).
Where I'm encountering trouble is with the actual construction/creation of the new, cropped image file using this pixel data. The source image is grayscale, however all of the examples I have found online (like this one) have been for RGB images. I tried to follow the example in that link, adjusting for grayscale and trying numerous different values, but I continue to get errors on the CGBitmapContextCreate line of code and still do not clearly understand what those values are supposed to be.
My intensity values for the source image go above 255, so my impression is that this is not 8-bit Grayscale, but 16-bit Grayscale.
Here is my code:
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context;
context = CGBitmapContextCreate(dstImage, // pixel data from the region of interest
dstWidth, // width of the region of interest
dstHeight, // height of the region of interest
16, // bits per component
2 * dstWidth, // bytes per row
colorSpace,
kCGImageAlphaNoneSkipLast);
CFRelease(colorSpace);
CGImageRef cgImage = CGBitmapContextCreateImage(context);
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
CFSTR("test.png"),
kCFURLPOSIXPathStyle,
false);
CFStringRef type = kUTTypePNG;
CGImageDestinationRef dest = CGImageDestinationCreateWithURL(url,
type,
1,
0);
CGImageDestinationAddImage(dest,
cgImage,
0);
CFRelease(cgImage);
CFRelease(context);
CGImageDestinationFinalize(dest);
free(dstImage);
The error I keep receiving is:
CGBitmapContextCreate: unsupported parameter combination: 16 integer bits/component; 32 bits/pixel; 1-component color space; kCGImageAlphaNoneSkipLast; 42 bytes/row.
The ultimate goal is to create an image file from the pixel data in dstImage and save it to the hard drive. Help on this would be greatly appreciated as would insight into how to determine what values I should be using in the CGBitmapContextCreate call.
Thank you
First, you should familiarize yourself with the "Supported Pixel Formats" section of Quartz 2D Programming Guide: Graphics Contexts.
If your image data is in an array of float values, then it's 32-bits-per-component, not 16. Therefore, you have to use kCGImageAlphaNone | kCGBitmapFloatComponents.
However, I believe that Core Graphics will interpret floating-point components as being between 0.0 and 1.0. If your values are outside of that, you may need to convert them using something like (value - minimumValue) / (maximumValue - minimumValue). An alternative may be to use CGColorSpaceCreateCalibratedGray() or to create a CGImage using CGImageCreate() and specifying an appropriate decode parameter and then create a bitmap context from that using CGBitmapContextCreateImage().
In fact, if you're not drawing into your bitmap context, you should just be creating a CGImage instead, anyway.

convert grayIplImage to color iplimage in opencv [duplicate]

I want to composite a number of images into a single window in openCV. I had found i could create a ROI in one image and copy another colour image into this area without any problems.
Switching the source image to an image i had carried out some processing on didn't work though.
Eventually i found out that i'd converted the src image to greyscale and that when using the copyTo method that it didn't copy anything over.
I've answered this question with my basic solution that only caters for greyscale to colour. If you use other Mat image types then you'd have to carry out the additional tests and conversions.
I realised my problem was i was trying to copy a greyscale image into a colour image. As such i had to convert it into the appropriate type first.
drawIntoArea(Mat &src, Mat &dst, int x, int y, int width, int height)
{
Mat scaledSrc;
// Destination image for the converted src image.
Mat convertedSrc(src.rows,src.cols,CV_8UC3, Scalar(0,0,255));
// Convert the src image into the correct destination image type
// Could also use MixChannels here.
// Expand to support range of image source types.
if (src.type() != dst.type())
{
cvtColor(src, convertedSrc, CV_GRAY2RGB);
}else{
src.copyTo(convertedSrc);
}
// Resize the converted source image to the desired target width.
resize(convertedSrc, scaledSrc,Size(width,height),1,1,INTER_AREA);
// create a region of interest in the destination image to copy the newly sized and converted source image into.
Mat ROI = dst(Rect(x, y, scaledSrc.cols, scaledSrc.rows));
scaledSrc.copyTo(ROI);
}
Took me a while to realise the image source types were different, i'd forgotten i'd converted the images to grey scale for some other processing steps.