im struggeling for a long while now. Im trying to change the alpha channel on a specific pixel of a image. I want to convert an image to a 2D array with only alpha channels. I got this working in Android, but don't know how in UWP.
Android version
short[][] dotMapArray;
short[][] heatMapArray;
int[] scolorGradiant;
void init() {
Bitmap dotBitmap = loadImageFromResources(DOT);
Bitmap gradiantBitmap = loadImageFromResources(SPECTRUMPIC);
// initializing the 'dot' for the points on the heatmap
dotMapArray = new short[dotBitmap.getWidth()][dotBitmap.getHeight()];
print(true, "Converting Dot image to black image");
for (int x = 0; x < dotBitmap.getWidth(); x++) {
for (int y = 0; y < dotBitmap.getHeight(); y++) {
dotMapArray[x][y] = (short) (Color.alpha(dotBitmap.getPixel(x, y)));
if (dotMapArray[x][y] > 255)
dotMapArray[x][y] = 255;
}
}
// initializing the color gradiant
scolorGradiant = new int[gradiantBitmap.getHeight()];
int gradiant, pixelColor;
for (int y = 0; y < scolorGradiant.length; y++) {
gradiant = gradiantBitmap.getPixel(0, y); // color
pixelColor = Color.argb(90, Color.red(gradiant), Color.green(gradiant), Color.blue(gradiant));
scolorGradiant[y] = pixelColor;
}
}
How do I do this in UWP?
Can anybody help me?
Here's a loop that checks 1st channel (BGRA) if blue = 255 then all channels go to 0
var pixels = yourWriteableBitmap.PixelBuffer.ToArray();
for (int i = 0; i < pixels.Length; i += 4)
{
if (pixels[i] == 255)
{
pixels[i] = 0;
pixels[i + 1] = 0;
pixels[i + 2] = 0;
pixels[i + 3] = 0;
}
}
using (var stream = yourWriteableBitmap.PixelBuffer.AsStream())
{
await stream.WriteAsync(pixels, 0, pixels.Length);
}
Related
There is a comment on here, on a stackflow post that answers the question of how to achieve super fast median calculation on opencv. The question is here:
super fast median of matrix in opencv (as fast as matlab)
The problem is that the code is on C/C++ and I can't find a way to convert this to opencv for java or C#, since I'm trying to port this to OpenCV for Xamarin.Forms
Anyone knows how to conver this?
double medianMat(cv::Mat Input, int nVals) {
// COMPUTE HISTOGRAM OF SINGLE CHANNEL MATRIX
float range[] = {
0,
nVals
};
const float * histRange = {
range
};
bool uniform = true;
bool accumulate = false;
cv::Mat hist;
calcHist( & Input, 1, 0, cv::Mat(), hist, 1, & nVals, & histRange, uniform, accumulate);
// COMPUTE CUMULATIVE DISTRIBUTION FUNCTION (CDF)
cv::Mat cdf;
hist.copyTo(cdf);
for (int i = 1; i <= nVals - 1; i++) {
cdf.at < float > (i) += cdf.at < float > (i - 1);
}
cdf /= Input.total();
// COMPUTE MEDIAN
double medianVal;
for (int i = 0; i <= nVals - 1; i++) {
if (cdf.at < float > (i) >= 0.5) {
medianVal = i;
break;
}
}
return medianVal / nVals;
}
UPDATE:
As an example, this is my tried method on c# to calculate the mediam of a grey scale Mat. It fails, can you see what I did wrong?
private static int Median2(Mat Input)
{
// COMPUTE HISTOGRAM OF SINGLE CHANNEL MATRIX
MatOfInt mHistSize = new MatOfInt(256);
MatOfFloat mRanges = new MatOfFloat(0f, 256f);
MatOfInt channel = new MatOfInt(0); // only 1 channel for grey
Mat temp = new Mat();
Mat hist = new Mat();
Imgproc.CalcHist(Java.Util.Arrays.AsList(Input).Cast<Mat>().ToList(), channel, temp, hist, mHistSize, mRanges);
float[] cdf = new float[(int)hist.Total()];
hist.Get(0, 0, cdf);
for (int i = 1; i < 256; i++)
{
cdf[i] += cdf[i - 1];
cdf[i - 1] = cdf[i - 1] / Input.Total();
}
// COMPUTE CUMULATIVE DISTRIBUTION FUNCTION (CDF)
float total = (float)Input.Total();
// COMPUTE MEDIAN
double medianVal=0;
for (int i = 0; i < 256; i++)
{
if (cdf[i] >= 0.5) {
medianVal = i;
break;
}
}
return (int)(medianVal / 256);
}
I have problem where i need to add a button on center of transparent area in image.
Example:
according to above image i have hundreds of photo frame and each frame there is a transparent area and i need to add a button on center of this transparent area.
Now i want a solution in which i can get coordinates of "x" programatically.
Please help.
public static PointF getTransparentCenter(Bitmap bitmap, Point viewSize) {
List<Point> transparentPoints = new ArrayList<>();
for (int i = 0; i < bitmap.getWidth(); i++) {
for (int j = 0; j < bitmap.getHeight(); j++) {
int pixel = bitmap.getPixel(i, j);
if ((pixel & 0xff000000) == 0) {
//the point color is transparent
transparentPoints.add(new Point(i, j));
}
}
}
int totalX = 0;
int totalY = 0;
for (Point transparentPoint : transparentPoints) {
totalX += transparentPoint.x;
totalY += transparentPoint.y;
}
float centerX = (float) totalX / transparentPoints.size();
float centerY = (float) totalY / transparentPoints.size();
float x = viewSize.x * centerX / bitmap.getWidth();
float y = viewSize.y * centerY / bitmap.getHeight();
return new PointF(x, y);
}
I think this is stupid, but I think there's no other way.
I'm designing a puzzle game in android eclipse. I have a picture in resources drawable file named "puzzle_image01". i want to divide this image to 9 parts and put it to some variables. then using them for the puzzle pieces. Now, how can i divide the image to 9 parts?
thank you for your advice.
for(int i = 0; i < 9; ++i) {
int indexY = 0;
if(i < 3) {
imageStartY = 0;
imageFinishY = sourceBitmap.height() / 3;
}
else if(i < 6) {
imageStartY = sourceBitmap.height() / 3;
imageFinishY = (sourceBitmap-height() / 3) * 2;
}
else if(i < 9) {
imageStartY = (sourceBitmap.height() / 3) * 2;
imageFinishY = sourceBitmap.height();
}
Bitmap resizedbitmap = Bitmap.createBitmap(sourceBitmap
, ((sourceBitmap.width()) / 3) * i
, imageStartY
,((sourceBitmap.width()) / 3) * i + sourceBitmap.width()
, imageFinishY)
}
Interesting challenge. Didn't test this, but it should work for any row/column combination where the image's dimensions divided by their respective value is greater than zero:
private Bitmap[][] split(Bitmap bitmap, int rows, int columns){
int[] dimens = new int[]{ bitmap.getWidth() / rows, bitmap.getHeight() / columns };
Bitmap[][] splitMap = new Bitmap[rows][columns];
for(int i = 0; i < rows; i++){
for(int j = 0; j < columns; j++){
splitMap[i][j] = Bitmap.createBitmap(bitmap, i * dimens[0], j * dimens[1], dimens[0], dimens[1]);
}
}
return splitMap;
}
i am trying to create gradient of two colors like Photoshop.
r,g,b of two colors is input and result will be the Mat of gradient. I tried it like for 5 hours at least and i could not find exact effect as of the Photoshop.
I tried to create my own formula (as i could not find any on the web), by changing RGB to HSV and then adding the difference of hue, with respect to the total number of rows, to each row of Mat with and also decreasing intensity to the center of image and then increasing it again. The code is self explanatory.
Additionally if anyone can tell me the exact formula for creating a gradient it will be really helpful.
here is how Photoshop gradient looks like
and this is what i get from my code
int r1, g1, b1, r2, g2, b2;
r1 = 255;
g1 = 0;
b1 = 0;
r2 = 0;
g2 = 255;
b2 = 0;
Mat input = imread("img.jpg");
Mat color1(input.size(), input.type());
Mat color2(input.size(), input.type());
vector<Mat> bgr1;
vector<Mat> bgr2;
split(color1, bgr1);
bgr1[0] = b1;
bgr1[1] = g1;
bgr1[2] = r1;
merge(bgr1, color1);
split(color2, bgr2);
bgr2[0] = b2;
bgr2[1] = g2;
bgr2[2] = r2;
merge(bgr2, color2);
vector<Mat> hls1;
vector<Mat> hls2;
cvtColor(color1, color1, CV_BGRA2BGR);
cvtColor(color1, color1, CV_BGR2HSV);
split(color1, hls1);
cvtColor(color2, color2, CV_BGRA2BGR);
cvtColor(color2, color2, CV_BGR2HSV);
split(color2, hls2);
double h1 = hls1[0].at<uchar>(0, 0);
double h2 = hls2[0].at<uchar>(0, 0);
double dif = (h2 - h1) / input.rows;
double h = h1;
double halfL = 255 / 2;
double halfR = input.rows / 2;
double ldif = halfL / halfR;
double l = 255;
bool isHalf = false;
for (int i = 0; i < input.rows; i++)
{
for (int j = 0; j < input.cols; j++)
{
hls1[0].at<uchar>(i, j) = h;
hls1[2].at<uchar>(i, j) = l;
}
if (isHalf == false){
l -= ldif;
}
else{
l += ldif;
}
if (i < input.rows * 0.40)
{
h += dif * 0.40;
}
else if (i < input.rows * 0.60)
{
h += dif * 3;
}
else
{
h += dif * 0.40;
}
if (i >= input.rows / 2)
{
isHalf = true;
}
}
merge(hls1, color1);
merge(hls2, color2);
cvtColor(color1, color1, CV_HSV2BGR);
cvtColor(color1, color1, CV_BGR2BGRA);
cvtColor(color2, color2, CV_HSV2BGR);
cvtColor(color2, color2, CV_BGR2BGRA);
namedWindow("Color1", cv::WINDOW_NORMAL);
resizeWindow("Color1", color1.size().width / 2, color1.size().height / 2);
imshow("Color1", color1);
waitKey(0);
destroyAllWindows();
system("pause");
I corrected my first code
It seems to be a really complex code for something that should be easier.
I would do something like that.
int taille = 500;
Mat image(taille,taille,CV_8UC3);
for(int y = 0; y < taille; y++){
Vec3b val;
val[0] = 0; val[1] = (y*255)/taille; val[2] = (taille-y)*255/taille;
for(int x = 0; x < taille; x++)
image.at<Vec3b>(y,x) = val;
}
On Micka's advice, I add a picture of the result with taille = 400;
I have the following routine in a subclass of view:
It calculates an array of points that make up a line, then erases the previous lines, then draws the new lines (impact refers to the width in pixels drawn with multiple lines). The line is your basic bell curve, squeezed or stretched by variance and x-factor.
Unfortunately, nothing shows on the screen. A previous version with drawPoint() and no array worked, and I've verified the array contents are being loaded correctly, and I can see that my onDraw() is being triggered.
Any ideas why it might not be drawn? Thanks in advance!
protected void drawNewLine( int maxx, int maxy, Canvas canvas, int impact, double variance, double xFactor, int color) {
// impact = 2 to 8; xFactor between 4 and 20; variance between 0.2 and 5
double x = 0;
double y = 0;
int cx = maxx / 2;
int cy = maxy / 2;
int mu = cx;
int index = 0;
points[maxx<<1][1] = points[maxx<<1][0];
for (x = 0; x < maxx; x++) {
points[index][1] = points[index][0];
points[index][0] = (float) x;
Log.i(DEBUG_TAG, "x: " + x);
index++;
double root = 1.0 / (Math.sqrt(2 * Math.PI * variance));
double exponent = -1.0 * (Math.pow(((x - mu)/maxx*xFactor), 2) / (2 * variance));
double ePow = Math.exp(exponent);
y = Math.round(cy * root * ePow);
points[index][1] = points[index][0];
points[index][0] = (float) (maxy - y - OFFSET);
index++;
}
points[maxx<<1][0] = (float) impact;
for (int line = 0; line < points[maxx<<1][1]; line++) {
for (int pt = 0; pt < (maxx<<1); pt++) {
pointsToPaint[pt] = points[pt][1];
}
for (int skip = 1; skip < (maxx<<1); skip = skip + 2)
pointsToPaint[skip] = pointsToPaint[skip] + line;
myLinePaint.setColor(Color.BLACK);
canvas.drawLines(pointsToPaint, bLinePaint); // draw over old lines w/blk
}
for (int line = 0; line < points[maxx<<1][0]; line++) {
for (int pt = 0; pt < maxx<<1; pt++) {
pointsToPaint[pt] = points[pt][0];
}
for (int skip = 1; skip < maxx<<1; skip = skip + 2)
pointsToPaint[skip] = pointsToPaint[skip] + line;
myLinePaint.setColor(color);
canvas.drawLines(pointsToPaint, myLinePaint); / new color
}
}
update: Replaced the drawLines() with drawPoint() in loop, still no joy
for (int p = 0; p<pointsToPaint.length; p = p + 2) {
Log.i(DEBUG_TAG, "x " + pointsToPaint[p] + " y " + pointsToPaint[p+1]);
canvas.drawPoint(pointsToPaint[p], pointsToPaint[p+1], myLinePaint);
}
/// canvas.drawLines(pointsToPaint, myLinePaint);
I was attempting to write from within onCreate() and onStart(). The View and its Canvas are never actually rendered for the first time until the end of onStart().
aren't you suppose to call invalidate (like a mapview) to force the view to reload?
YourView.invalidate() (or maybe postInvalidate(), depending where you are : main sthread or not)
here is the detail