When converting from PNG to JPG using the MagickWand API, how do I set the background to specified color for transparent pixels? I still get only white background which I don't want.
I know there is similar question, but without answer =
How to set background color for transparent pixels in MagickWand?
I've found it... I missed that MagickMergeImageLayers is returning new wand! So the code looks like:
if(current_wand && IsMagickWand(current_wand)){
status=MagickReadImage(current_wand, "test.png");
if (status == MagickFalse) {
ThrowWandException(current_wand);
}
PixelWand *color = NewPixelWand();
PixelSetColor(color, "red");
MagickSetImageBackgroundColor(current_wand, color);
MagickWand *newwand = MagickMergeImageLayers(current_wand, FlattenLayer);
MagickWriteImage(newwand, "test.jpg");
DestroyMagickWand(newwand);
}
Related
I would like to know what is the problem in below code, since it only appears only part of the Gray image as Binary image!
cv::Mat gry = cv::imread("image_gray.jpg");
cv::Mat bin(gry.size(), gry.type());
for (int i=0; i<gry.rows ;i++)
{
for (int j=0; j<gry.cols ;j++)
{
if (gry.at<uchar>(i,j)>=100)
bin.at<uchar>(i,j)=255;
else
bin.at<uchar>(i,j)=0;
}
}
cv::namedWindow("After", cv::WINDOW_AUTOSIZE);
cv::imshow("After",bin);
waitKey(0);
cvDestroyWindow( "After" );
imwrite("binary_image.bmp", bin);
Your problem is in cv::imread.
The function assumes it should load the image as a color image, if you want to load it as a garyscale image, you should call the function as follows:
cv::imread(fileName, CV_LOAD_IMAGE_GRAYSCALE)
By the way, the reason you only see part of the image, is because the image is simply bigger than a uchar for each pixel. (and you end up iterating only over part of it).
it would be easier if you use use the OpenCV function:
cv::threshold(image_src, image_dst, 200, 255, cv::THRESH_BINARY);
This piece of code set as black value (255) all those pixels which have as original value 200.
I'm creating an application of watermarking using opencv, I'm not able to set background of image as transparent.
I'm using this code Scalar colorScalar = new Scalar(255,255,255,0);
Can any body help me how to make background transparent. I'm using PNG format image.
targetMat = new Mat(targetSize, scaledImage.type(), colorScalar);
Mat waterSubmat = targetMat.submat((int)offsetY,scaledImage.height(), (int)offsetX, scaledImage.width());
scaledImage.copyTo(waterSubmat);
center = new org.opencv.core.Point(pivotX, pivotY);
Mat rotImage = Imgproc.getRotationMatrix2D(center, degreevaluechange, 1);
Mat resultMat = new Mat(2,3, CvType.CV_32FC1);
colorScalar = new Scalar(255,255,255,0);
Imgproc.warpAffine(targetMat, resultMat, rotImage, targetSize, Imgproc.INTER_AREA, Imgproc.BORDER_CONSTANT, colorScalar);
scaledImage = resultMat.clone();
If you want to load your PNG image with the alpha channel and therefore load your image with transparenty, you have to use this code:
imread("image.png",-1)
You can find more informations in the opencv documentation here:
http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imread#imread
As you see in the documentation provided by Maximus. You need to create a 4 channel Mat:
Mat* targetMat = new Mat(targetSize, CV_8UC4, colorScalar);
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compression_params.push_back(9);
try {
imwrite("alpha.png", targetMat, compression_params);
}
catch (runtime_error& ex) {
fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what());
return 1;
}
Then add the parameters and write. (This code is from the documentation)
I have successfully ported ImageMagick in my iPhone Application, everything seems to be working. I need to apply one filter for border color. I have written using Pixelwand, however its not been showing border color. Below is my code.
PixelWand *color = NewPixelWand();
PixelSetColor(color, "PixelGetMagenta");
status = MagickSetImageBorderColor(magick_wand, color);
What I am doing wrong?
PixelSetColor's second parameter is expecting color name, not a method name. Example "magenta", "#FF00FF", or "rgb(255,0,255)". The MagickBooleanType would return MagickFalse when calling PixelSetColor(color, "PixelGetMagenta");, as setting a color named "PixeGetMagenta" would fail. PixelGetMagenta is usally used with PixelGetMagentaQuantum when working directly with color packets.
MagickBooleanType status;
PixelWand *color = NewPixelWand();
status = PixelSetColor(color, "magenta");
// Error handle if status == MagickFalse
status = MagickSetImageBorderColor(magick_wand, color);
// Error handle if status == MagickFalse
status = MagickBorderImage(wand,color,10,10);
// Error handle if status == MagickFalse
I created a drawing application where I allow the user to draw and save the image to later reload to continue drawing. Essentially, I'm passing the drawing as a bitmap to the JNI layer to be saved and the same to load a previous drawing.
I'm using OpenCv to write and read to png file.
I'm noticing something weird in terms of the transparencies of the image. It almost seems as the transparency is being calculated against a black color on OpenCv? Take a look a the images attached, the contain lines that have transparencies.
Correct transparency by passing int array to native code, no color conversion needed:
Darkened transparency by passing Bitmap object to native code, color conversion needed:
What could potentially be happening?
Saving image using native Bitmap get pixel methods:
if ((error = AndroidBitmap_getInfo(pEnv, jbitmap, &info)) < 0) {
LOGE("AndroidBitmap_getInfo() failed! error:%d",error);
}
if (0 == error)
{
if ((error = AndroidBitmap_lockPixels(pEnv, jbitmap, &pixels)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", error);
}
}
if (0 == error)
{
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888)
{
LOGI("ANDROID_BITMAP_FORMAT_RGBA_8888");
}
else
{
LOGI("ANDROID_BITMAP_FORMAT %d",info.format);
}
Mat bgra(info.height, info.width, CV_8UC4, pixels);
Mat image;
//bgra.copyTo(image);
// fix pixel order RGBA -> BGRA
cvtColor(bgra, image, COLOR_RGBA2BGRA);
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compression_params.push_back(3);
// save image
if (!imwrite(filePath, image, compression_params))
{
LOGE("saveImage() -> Error saving image!");
error = -7;
}
// release locked pixels
AndroidBitmap_unlockPixels(pEnv, jbitmap);
}
Saving image using native int pixel array methods:
JNIEXPORT void JNICALL Java_com_vblast_smasher_Smasher_saveImageRaw
(JNIEnv *pEnv, jobject obj, jstring jFilePath, jintArray jbgra, jint options, jint compression)
{
jint* _bgra = pEnv->GetIntArrayElements(jbgra, 0);
const char *filePath = pEnv->GetStringUTFChars(jFilePath, 0);
if (NULL != filePath)
{
Mat image;
Mat bgra(outputHeight, outputWidth, CV_8UC4, (unsigned char *)_bgra);
bgra.copyTo(image);
if (0 == options)
{
// replace existing cache value
mpCache->insert(filePath, image);
}
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compression_params.push_back(compression);
// save image
if (!imwrite(filePath, image))
{
LOGE("saveImage() -> Error saving image!");
}
}
pEnv->ReleaseIntArrayElements(jbgra, _bgra, 0);
pEnv->ReleaseStringUTFChars(jFilePath, filePath);
}
Update 05/25/12:
After a little more research I'm finding out that this issue does not happen if I get the int array of pixels from the bitmap and pass that directly to the JNI as opposed to what I do currently which is pass the entire Bitmap to the JNI layer then get the pixels and use cvtColor to convert pixels properly. Am I using the right pixel conversion?
There are two ways representing alpha in an RGBA pixel, premultiplied or not. With premultiplication, the R, G, and B values are multiplied by the percentage of alpha: color = (color * alpha) / 255. This simplifies a lot of blending calculations and is often used internally in imaging libraries. Before saving out to a format that doesn't use premultiplied alpha, such as PNG, the color values must be "unmultiplied": color = (255 * color) / alpha. If it is not, the colors will look too dark; the more transparent the color, the darker it will be. That looks like the effect you're seeing here.
There is nothing called as transparent image in opencv. The foreground and the background images are mixed appropriately to give the illusion of transparency. Check this to see how its done.
When converting from PNG to JPG using the MagickWand API, how do I set the background to white for transparent pixels?
if(current_wand && IsMagickWand(current_wand)){
status=MagickReadImage(current_wand, "test.png");
if (status == MagickFalse) {
ThrowWandException(current_wand);
}
PixelWand *color = NewPixelWand();
PixelSetColor(color, "white");
MagickSetImageBackgroundColor(current_wand, color);
MagickWand *newwand = MagickMergeImageLayers(current_wand, FlattenLayer);
MagickWriteImage(newwand, "test.jpg");
DestroyMagickWand(newwand);
}
Use MagickMergeImageLayers