Weird output while processing images with Processing 3.3.7 - java

What I have:
I have 2 images with same size (500), one is a normal image and the other have a message with only black pixels (message) and white pixels (nothing).
What i do in encodeImage() is create messageEncoded with pixels of originalImage and incrementing it by 1 if the pixel of the messageImage isn't white.
This is how i'm hidding a image in another image, so decodeImage() should read the originalImage and messageEncoded to extract the messageImage, creating messageDecoded with white pixel when doens't change the pixel and black and it changes.
PImage originalImage;
PImage messageImage;
PImage messageEncoded;
PImage messageDecoded;
void setup() {
size(500, 500);
originalImage = loadImage("jap.jpg");
messageImage = loadImage("msg.jpg");
messageEncoded = createImage(originalImage.width, originalImage.height, RGB);
messageDecoded = createImage(originalImage.width, originalImage.height, RGB);
encodeImage();
}
void decodeImage() {
originalImage.loadPixels();
messageEncoded.loadPixels();
messageDecoded.loadPixels();
PImage msg = loadImage("messageEncoded.jpg");
msg.loadPixels();
for (int x = 0; x < originalImage.width; x++) {
for (int y = 0; y < originalImage.height; y++ ) {
int loc = x + y * originalImage.width;
if (messageEncoded.pixels[loc] == originalImage.pixels[loc]) {
messageDecoded.pixels[loc] = color(255);
} else {
messageDecoded.pixels[loc] = color(0);
}
}
}
messageDecoded.updatePixels();
messageDecoded.save("messageDecoded.jpg");
image(messageDecoded, 0, 0);
}
void encodeImage() {
originalImage.loadPixels();
messageImage.loadPixels();
messageEncoded.loadPixels();
for (int x = 0; x < originalImage.width; x++) {
for (int y = 0; y < originalImage.height; y++ ) {
int loc = x + y * originalImage.width;
if (messageImage.pixels[loc] != color(255)) {
float r = red(originalImage.pixels[loc]);
float g = green(originalImage.pixels[loc]);
float b = blue(originalImage.pixels[loc]);
messageEncoded.pixels[loc] = color(r + 1, g + 1, b + 1);
} else {
messageEncoded.pixels[loc] = originalImage.pixels[loc];
}
}
}
messageEncoded.updatePixels();
messageEncoded.save("messageEncoded.jpg");
//image(messageEncoded, 0, 0);
decodeImage();
}
The Problems:
I have the variable PImage msg in void decodeImage() that I'm not using. This variable should be the same as the global messageEncoded because it's reading the file that it just outputed, but if I use msg, changing
if (messageEncoded.pixels[loc] == originalImage.pixels[loc]) {
messageDecoded.pixels[loc] = color(255);
} else {
messageDecoded.pixels[loc] = color(0);
}
into
if (msg.pixels[loc] == originalImage.pixels[loc]) {
messageDecoded.pixels[loc] = color(255);
} else {
messageDecoded.pixels[loc] = color(0);
}
the result is totally different and weird. Why? What is the difference between messageEncoded and msg?
messageDecoded is a little bit wrong, why it's having this wrong black dots?
I made the messageImage in paint, so i though paint is creating non-black dots, but i look all pixels, even put a single black pixel and still appeared some black dots around it.
The originalImage. I found this on google by typing '500x500 images'.
The messageImage. I created this on paint and save it with 500x500 dimentions (for testing it can be and draw with only black and with pixels).
The very weird picture that happens when I use msg. (Problem 1)
The messageDecoded the have black dots around it. Can I call it noise? (Problem 2)
Edit 1:
The weird image and the problem 1 is solved when I use PNG images, but the 2 problem of the "noise" isn't fixed yet

It's likely that JPEG encoding is causing the problem (the noise looks characteristic of compression artifacts). You'll need to work with images in a lossless format such as .PNG to alleviate the problem.
Recreate messageImage, saving it as a .PNG this time.
Convert originalImage to .PNG and modify your code such that
Processing saves the images as .PNG.
It's ok to use a JPEG as the source image; the problem arises from successive JPEG saving/encoding (where more pixels than simply those which are being encoded are changed).

Related

How to get 0..255 colors from a picture in Java? [duplicate]

This question already has answers here:
reading black/white image in java with TYPE_USHORT_GRAY
(2 answers)
Closed 2 years ago.
I have tried to grayscale a already black-white-gray picture and it become black.
When I try to grayscale a picture with Java, I do like this:
// This turns the image data to grayscale and return the data
private static RealMatrix imageData(File picture) {
try {
BufferedImage image = ImageIO.read(picture);
int width = image.getWidth();
int height = image.getHeight();
RealMatrix data = MatrixUtils.createRealMatrix(height * width, 1);
// Convert to grayscale
int countRows = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// Turn image to grayscale
int p = image.getRGB(x, y);
int r = (p >> 16) & 0xff;
int g = (p >> 8) & 0xff;
int b = p & 0xff;
// calculate average and save
int avg = (r + g + b) / 3;
data.setEntry(countRows, 0, avg);
countRows++;
}
}
return data;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
The problem what I see is that p is an 32-bit value and I only want 8-bit value. Even if the picture is already grayscaled, the p value is already a 32-bit value. That cause trouble for me.
So if I grayscale a gray picture, it will become black. Or at least darker.
And I want 0..255 values of p, which is a 32-bit integer value.
Do you have any suggestions how to read pictures as they where 8-bit?
It's for image classification.
Summarize:
I need help to get each pixels from a picture in 0..255 format.
One way is to gray scale it, but how can I verify if the picture is already gray scaled?
Update:
I have tried to read a picture as it was 8-bit values. It works. Then I try to save the picture with the same values. The picture becomes very dark.
I have a matlab example I want to show.
First I read my picture:
image = imread("subject01.normal");
And then I save the picture.
imwrite(uint8(image), "theSameImage.gif")
If I try with a minimal Java code snipped for reading an image.
private static void imageData(File picture) {
try {
BufferedImage image = ImageIO.read(picture);
int width = image.getWidth();
int height = image.getHeight();
DataBuffer buffer = image.getRaster().getDataBuffer();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int p = buffer.getElem(x + y * width);
image.setRGB(x, y, p);
}
}
File output = new File(picture.getName());
ImageIO.write(image, "gif", output);
return data;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
I will get this picture:
So even if there is a marked answer in this question, it's still not going to help you.
You mentioned that the image you're reading is a grayscale image, and that getRGB returns values like 23241 and 23551.
That means your image uses a CS_GRAY ColorSpace, not an RGB color space. You can confirm this by calling getType(), which would return TYPE_USHORT_GRAY.
That means that your p value is a gray-level in range 0 - 65535. Since you want the result to be a double in range 0 - 255, you need to calculate:
double avg = p * 255.0 / 65535.0;
Unless you're 100% sure the input image will always be grayscale, you should check the type in the code and handle the p value accordingly.

Replace colors in an image without having to iterate through all pixels

Let's say that I have an image like this one (in reality, I have a lot of them, but let's keep it simple)
example picture and I'd like to replace background color (that's the one that's not roads) with green color.
To do that I'd have to iterate through all of the pixels in the map and replace ones that match the color I want to remove.
But as you might think, my image is not a simple as 256x256 picture, but it's slightly bigger, it's 1440p, and the performance drop is significant.
How would I replace all of the unwanted pixels without iterating through all of the pixels.
I'm working with Processing 3 - Java(Android) and I'm currently using this piece of code:
for (x = 0; x < img.width; x++){
for (int y = 0; y < img.height; y++) {
//Color to transparent
int index = x + img.width * y;
if (img.pixels[index] == -1382175 || img.pixels[index] == 14605278 || img.pixels[index] == 16250871) {
img.pixels[index] = color(0, 0, 0, 0);
} else {
img.pixels[index] = color(map(bright, 0, 255, 64, 192));
}
}
}
Solved it with this one:
private PImage swapPixelColor(PImage img, int old, int now) {
old &= ~0x00000000;
now &= ~0x00000000;
img.loadPixels();
int p[] = img.pixels, i = p.length;
while (i-- != 0) if ((p[i]) == old) p[i] = now;
img.updatePixels();
return img;
}
It works like a charm and it takes almost no time:
Swapped colors in 140ms // That's replacing it three times(different colors ofc)

Detecting multiple images in a single image

I need help to identify the border and compare the images with the original image. I need guidance on How can I achieve this through processing or matlab or anything for beginner. for example look at the image below.
Original Image:
The Multiple Image:
The "multiple image" you showed is easy enough to handle using just simple image processing, no need for template matching :)
% read the second image
img2 = imread('http://i.stack.imgur.com/zyHuj.jpg');
img2 = im2double(rgb2gray(img2));
% detect coca-cola logos
bw = im2bw(img2); % Otsu's thresholding
bw = imfill(~bw, 'holes'); % fill holes
stats = regionprops(bw, {'Centroid', 'BoundingBox'}); % connected components
% show centers and bounding boxes of each connected component
centers = vertcat(stats.Centroid);
imshow(img2), hold on
plot(centers(:,1), centers(:,2), 'LineStyle','none', ...
'Marker','x', 'MarkerSize',20, 'Color','r', 'LineWidth',3)
for i=1:numel(stats)
rectangle('Position',stats(i).BoundingBox, ...
'EdgeColor','g', 'LineWidth',3)
end
hold off
You can use correlation method to position the multiple images:
file1='http://i.stack.imgur.com/1KyJA.jpg';
file2='http://i.stack.imgur.com/zyHuj.jpg';
It = imread(file1);
Ii = imread(file2);
It=rgb2gray(It);
Ii=rgb2gray(Ii);
It=double(It); % template
Ii=double(Ii); % image
Ii_mean = conv2(Ii,ones(size(It))./numel(It),'same');
It_mean = mean(It(:));
corr_1 = conv2(Ii,rot90(It-It_mean,2),'same')./numel(It);
corr_2 = Ii_mean.*sum(It(:)-It_mean);
conv_std = sqrt(conv2(Ii.^2,ones(size(It))./numel(It),'same')-Ii_mean.^2);
It_std = std(It(:));
S = (corr_1-corr_2)./(conv_std.*It_std);
imagesc(abs(S))
The result will give you the positions with maximum values:
Get the coordinates of maxima, and position your template centroid at the same position, check the difference between your template and the matching image.
I am not sure what do you mean by "identify the border", but you can always extract the edges with canny detector:
bw=edge(It);
bw=imfill(bw,'holes');
figure,imshow(bw)
Below is presented a solution implemented in Java, using Marvin image processing framework.
Approach:
Load, segment and scale (50x50) the logo in the "original image".
Load, segment and scale (50x50) each logo in the "multiple image"
For each logo in "mulitple image", compare with the logo in "original image". If it is almost the same, draw a rect to highlight.
Comparison method (inside diff plug-in):
For each pixel in two logos, compare each color component. If the difference in one color component is higher then a given threshold, consider that pixel different for the two logos. Compute the total number of different pixels. If two logos have a number of different pixels higher than another threshold, consider them different. IMPORTANT: This approach is very sensitive to rotation and perspective variation.
Since your sample ("multiple image") has only coca logos, I took the liberty to include another logo in order to assert the algorithm.
The Multiple Image 2
Output
In another test, I've included two another similar coca logos. Changing the threshold parameters you can specify whether you want the exact same logo or accept its variations. In the result below, the parameters were set to accept logo variations.
The Multiple Image 3
Output
Source code
public class Logos {
private MarvinImagePlugin threshold = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.color.thresholding");
private MarvinImagePlugin fill = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.fill.boundaryFill");
private MarvinImagePlugin scale = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.transform.scale");
private MarvinImagePlugin diff = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.difference.differenceColor");
public Logos(){
// 1. Load, segment and scale the object to be found
MarvinImage target = segmentTarget();
// 2. Load the image with multiple objects
MarvinImage original = MarvinImageIO.loadImage("./res/logos/logos.jpg");
MarvinImage image = original.clone();
// 3. Segment
threshold.process(image, image);
MarvinImage image2 = new MarvinImage(image.getWidth(), image.getHeight());
fill(image, image2);
MarvinImageIO.saveImage(image2, "./res/logos/logos_fill.jpg");
// 4. Filter segments by its their masses
LinkedHashSet<Integer> objects = filterByMass(image2, 10000);
int[][] rects = getRects(objects, image2, original);
MarvinImage[] subimages = getSubimages(rects, original);
// 5. Compare the target object with each object in the other image
compare(target, subimages, original, rects);
MarvinImageIO.saveImage(original, "./res/logos/logos_out.jpg");
}
private void compare(MarvinImage target, MarvinImage[] subimages, MarvinImage original, int[][] rects){
MarvinAttributes attrOut = new MarvinAttributes();
for(int i=0; i<subimages.length; i++){
diff.setAttribute("comparisonImage", subimages[i]);
diff.setAttribute("colorRange", 30);
diff.process(target, null, attrOut);
if((Integer)attrOut.get("total") < (50*50)*0.6){
original.drawRect(rects[i][0], rects[i][6], rects[i][7], rects[i][8], 6, Color.green);
}
}
}
private MarvinImage segmentTarget(){
MarvinImage original = MarvinImageIO.loadImage("./res/logos/target.jpg");
MarvinImage target = original.clone();
threshold.process(target, target);
MarvinImage image2 = new MarvinImage(target.getWidth(), target.getHeight());
fill(target, image2);
LinkedHashSet<Integer> objects = filterByMass(image2, 10000);
int[][] rects = getRects(objects, image2, target);
MarvinImage[] subimages = getSubimages(rects, original);
return subimages[0];
}
private int[][] getRects(LinkedHashSet<Integer> objects, MarvinImage mask, MarvinImage original){
List<int[]> ret = new ArrayList<int[]>();
for(Integer color:objects){
ret.add(getObjectRect(mask, color));
}
return ret.toArray(new int[0][0]);
}
private MarvinImage[] getSubimages(int[][] rects, MarvinImage original){
List<MarvinImage> ret = new ArrayList<MarvinImage>();
for(int[] r:rects){
ret.add(getSubimage(r, original));
}
return ret.toArray(new MarvinImage[0]);
}
private MarvinImage getSubimage(int rect[], MarvinImage original){
MarvinImage img = original.subimage(rect[0], rect[1], rect[2], rect[3]);
MarvinImage ret = new MarvinImage(50,50);
scale.setAttribute("newWidth", 50);
scale.setAttribute("newHeight", 50);
scale.process(img, ret);
return ret;
}
private void fill(MarvinImage imageIn, MarvinImage imageOut){
boolean found;
int color= 0xFFFF0000;
while(true){
found=false;
Outerloop:
for(int y=0; y<imageIn.getHeight(); y++){
for(int x=0; x<imageIn.getWidth(); x++){
if(imageOut.getIntColor(x,y) == 0 && imageIn.getIntColor(x, y) != 0xFFFFFFFF){
fill.setAttribute("x", x);
fill.setAttribute("y", y);
fill.setAttribute("color", color);
fill.setAttribute("threshold", 120);
fill.process(imageIn, imageOut);
color = newColor(color);
found = true;
break Outerloop;
}
}
}
if(!found){
break;
}
}
}
private LinkedHashSet<Integer> filterByMass(MarvinImage image, int mass){
boolean found;
HashSet<Integer> analysed = new HashSet<Integer>();
LinkedHashSet<Integer> ret = new LinkedHashSet<Integer>();
while(true){
found=false;
outerLoop:
for(int y=0; y<image.getHeight(); y++){
for(int x=0; x<image.getWidth(); x++){
int color = image.getIntColor(x,y);
if(color != 0){
if(!analysed.contains(color)){
if(getMass(image, color) >= mass){
ret.add(color);
}
analysed.add(color);
found = true;
break outerLoop;
}
}
}
}
if(!found){
break;
}
}
return ret;
}
private int getMass(MarvinImage image, int color){
int total=0;
for(int y=0; y<image.getHeight(); y++){
for(int x=0; x<image.getWidth(); x++){
if(image.getIntColor(x, y) == color){
total++;
}
}
}
return total;
}
private int[] getObjectRect(MarvinImage mask, int color){
int x1=-1;
int x2=-1;
int y1=-1;
int y2=-1;
for(int y=0; y<mask.getHeight(); y++){
for(int x=0; x<mask.getWidth(); x++){
if(mask.getIntColor(x, y) == color){
if(x1 == -1 || x < x1){
x1 = x;
}
if(x2 == -1 || x > x2){
x2 = x;
}
if(y1 == -1 || y < y1){
y1 = y;
}
if(y2 == -1 || y > y2){
y2 = y;
}
}
}
}
return new int[]{x1, y1, (x2-x1), (y2-y1)};
}
private int newColor(int color){
int red = (color & 0x00FF0000) >> 16;
int green = (color & 0x0000FF00) >> 8;
int blue = (color & 0x000000FF);
if(red <= green && red <= blue){
red+=5;
}
else if(green <= red && green <= blue){
green+=5;
}
else{
blue+=5;
}
return 0xFF000000 + (red << 16) + (green << 8) + blue;
}
public static void main(String[] args) {
new Logos();
}
}
You can simplify the process proposed by #lennon310 using the normxcorr2 function:
file1='http://i.stack.imgur.com/1KyJA.jpg';
file2='http://i.stack.imgur.com/zyHuj.jpg';
It = imread(file1);
Ii = imread(file2);
It=rgb2gray(It);
Ii=rgb2gray(Ii);
It=double(It); % template
Ii=double(Ii); % image
c=normxcorr2(It, Ii);
imagesc(c);
The simple way (you don't need to write any code) - use Adaptive Vision Studio:
AddLoadImage (and select the image with multiple logos)
Add LocateMultipleObjects_EdgeBased.
Connect outImage from LoadImage to inImage from second filter
Edit inEdgeModel from LocateMultipleObjects_EdgeBased for example my editing result (use Load Image in the plugin to load the Model image ):
Run program and change the parameters of LocateMultipleObjects_EdgeBased to find all elements (i changed inEdgeMagnitude to 9.0 ). You will also get scores for each image:
program with results:
In summary you need to add two filters: loadImage and LocateMultipleObjects_EdgeBased and select the model to find :) It's good for beginner you don't need to write any advanced programs. You can try to solve it also by: detecting circles, TemplateMatching_NCC etc etc...
If you want to detect your object in an environment more complex (rotation, deformation, scaling, perspective), you need a detection method more efficient. I suggest you to see what is called a "cascade classifier for Haar features"
OpenCv can propose you a lot of function to do this method rapidly. See this useful page
Or even by matlab you can see this example

Cropping image lowers quality and border looks bad

Using some math, i created the following java-function, to input a Bitmap, and have it crop out a centered square in which a circle is cropped out again with a black border around it.
The rest of the square should be transparent.
Additionatly, there is a transparent distance to the sides to not damage the preview when sending the image via Messengers.
The code of my function is as following:
public static Bitmap edit_image(Bitmap src,boolean makeborder) {
int width = src.getWidth();
int height = src.getHeight();
int A, R, G, B;
int pixel;
int middlex = width/2;
int middley = height/2;
int seitenlaenge,startx,starty;
if(width>height)
{
seitenlaenge=height;
starty=0;
startx = middlex - (seitenlaenge/2);
}
else
{
seitenlaenge=width;
startx=0;
starty = middley - (seitenlaenge/2);
}
int kreisradius = seitenlaenge/2;
int mittx = startx + kreisradius;
int mitty = starty + kreisradius;
int border=2;
int seitenabstand=55;
Bitmap bmOut = Bitmap.createBitmap(seitenlaenge+seitenabstand, seitenlaenge+seitenabstand, Bitmap.Config.ARGB_8888);
bmOut.setHasAlpha(true);
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
int distzumitte = (int) (Math.pow(mittx-x,2) + Math.pow(mitty-y,2)); // (Xm-Xp)^2 + (Ym-Yp)^2 = dist^2
distzumitte = (int) Math.sqrt(distzumitte);
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
R = (int)Color.red(pixel);
G = (int)Color.green(pixel);
B = (int)Color.blue(pixel);
int color = Color.argb(A, R, G, B);
int afterx=x-startx+(seitenabstand/2);
int aftery=y-starty+(seitenabstand/2);
if(x < startx || y < starty || afterx>=seitenlaenge+seitenabstand || aftery>=seitenlaenge+seitenabstand) //seitenrand
{
continue;
}
else if(distzumitte > kreisradius)
{
color=0x00FFFFFF;
}
else if(distzumitte > kreisradius-border && makeborder) //border
{
color = Color.argb(A, 0, 0, 0);
}
bmOut.setPixel(afterx, aftery, color);
}
}
return bmOut;
}
This function works fine, but there are some problems occuring that i wasn't able to resolve yet.
The quality of the image is decreased significantly
The border is not really round, but appears to be flat at the edges of the image (on some devices?!)
I'd appreciate any help regarding that problems. I got to admit that i'm not the best in math and there should probably be a better formula to ceate the border.
your source code is hard to read, since it is a mix of German and English in the variable names. Additionally you don't say which image library you use, so we don't exactly know where the classes Bitmap and Color come from.
Anyway, it is very obvious, that you are operating only on a Bitmap. Bitmap means the whole image is stored in the RAM pixel by pixel. There is no lossy compression. I don't see anything in your source code, that can affect the quality of the image.
It is very likely, that the answer is in the Code that you don't show us. Additionally, what you describe (botrh of the problems) sounds like a very typical low quality JPEG compression. I am sure, somewhere after you call you function, you convert/save the image to a JPEG. Try to do that at that position to BMP, TIFF or PNG and see that the error disappears magically. Maybe you can also set the quality level of the JPEG somewhere to avoid that.
To make it easier for others (maybe) also to find a good answer, please allow me to translate your code to English:
public static Bitmap edit_image(Bitmap src,boolean makeborder) {
int width = src.getWidth();
int height = src.getHeight();
int A, R, G, B;
int pixel;
int middlex = width/2;
int middley = height/2;
int sideLength,startx,starty;
if(width>height)
{
sideLength=height;
starty=0;
startx = middlex - (sideLength/2);
}
else
{
sideLength=width;
startx=0;
starty = middley - (sideLength/2);
}
int circleRadius = sideLength/2;
int middleX = startx + circleRadius;
int middleY = starty + circleRadius;
int border=2;
int sideDistance=55;
Bitmap bmOut = Bitmap.createBitmap(sideLength+sideDistance, sideLength+sideDistance, Bitmap.Config.ARGB_8888);
bmOut.setHasAlpha(true);
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
int distanceToMiddle = (int) (Math.pow(middleX-x,2) + Math.pow(middleY-y,2)); // (Xm-Xp)^2 + (Ym-Yp)^2 = dist^2
distanceToMiddle = (int) Math.sqrt(distanceToMiddle);
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
R = (int)Color.red(pixel);
G = (int)Color.green(pixel);
B = (int)Color.blue(pixel);
int color = Color.argb(A, R, G, B);
int afterx=x-startx+(sideDistance/2);
int aftery=y-starty+(sideDistance/2);
if(x < startx || y < starty || afterx>=sideLength+sideDistance || aftery>=sideLength+sideDistance) //margin
{
continue;
}
else if(distanceToMiddle > circleRadius)
{
color=0x00FFFFFF;
}
else if(distanceToMiddle > circleRadius-border && makeborder) //border
{
color = Color.argb(A, 0, 0, 0);
}
bmOut.setPixel(afterx, aftery, color);
}
}
return bmOut;
}
I think that you need to check PorterDuffXferMode.
You will find some technical informations about compositing images modes HERE.
There is some good example of making bitmap with rounded edges HERE. You just need to tweak a bit source code and you're ready to go...
Hope it will help.
Regarding the quality I can't see anything wrong with your method. Running the code with Java Swing no quality is lost. The only problem is that the image has aliased edges.
The aliasing problem will tend to disappear as the screen resolution increases and would be more noticeable for lower resolutions. This might explain why you see it in some devices only.The same problem applies to your border but in that case it would be more noticable since the color is single black.
Your algorithm defines a square area of the original image. To find the square it starts from the image's center and expand to either the width or the height of the image whichever is smaller. I am referring to this area as the square.
The aliasing is caused by your code that sets the colors (I am using pseudo-code):
if ( outOfSquare() ) {
continue; // case 1: this works but you depend upon the new image' s default pixel value i.e. transparent black
} else if ( insideSquare() && ! insideCircle() ) {
color = 0x00FFFFFF; // case 2: transparent white. <- Redundant
} else if ( insideBorder() ) {
color = Color.argb(A, 0, 0, 0); // case 3: Black color using the transparency of the original image.
} else { // inside the inner circle
// case 4: leave image color
}
Some notes about the code:
Case 1 depends upon the default pixel value of the original image i.e. transparent black. It works but better to set it explicitly
Case 2 is redundant. Handle it in the same way you handle case 1. We are only interested in what happens inside the circle.
Case 3 (when you draw the border) is not clear what it expects. Using the alpha of the original image has the potential of messing up your new image if it happens that the original alpha varies along the circle's edges. So this is clearly wrong and depending on the image, can potentially be another cause of your problems.
Case 4 is ok.
Now at your circle's periphery the following color transitions take place:
If border is not used: full transparency -> full image color (case 2 and 4 in the pseudocode)
If border is used: full transparency -> full black -> full image color (cases 2, 3 and 4)
To achieve a better quality at the edges you need to introduce some intermediate states that would make the transitions smoother (the new transitions are shown in italics):
Border is not used: full transparency -> partial transparency with image color -> full image color
Border is used: full transparency -> partial transparency of Black color -> full Black color -> partial transparency of Black color + Image color (i.e. blending) -> Full image color
I hope that helps

if/then with pixel finding and looping, all of which is above me at the moment

I want to take a screenshot, and if the pixel is the correct value RGB then take another screenshot and find next pixel or else repeat.
this is the code to get the pixel and it works like a charm!
{
BufferedImage image = robot.createScreenCapture(rectangle);
search: for(int x = 0; x < rectangle.getWidth(); x++)
{
for(int y = 0; y < rectangle.getHeight(); y++)
{
if(image.getRGB(x, y) == color3.getRGB())
{
break search;
}
}
}
}
what i want to know i guess is how would i go about asking it to repeat this segment of code until the pixel equals the true color. the color i am looking for is:
Color color3 = new Color(114, 46, 33);
Ok context, i am building a program that goes through steps, one opens the given puzzle, i have that down because i can use simple pixel data, then it needs to center the mouse on the center pixel. The problem is i cant just use a second get pixel image because it takes a while for the game to open the relevant jpanel so i need my program to wait until it can find a pixel indicating the game is open before it starts to look for the pixel to center the mouse.
You can probably separate the screenshot code into a method and call it until you get the desired result:
public boolean checkColor(Color inputColor) {
BufferedImage image = robot.createScreenCapture(rectangle);
for(int x = 0; x < rectangle.getWidth(); x++) {
for (int y = 0; y < rectangle.getHeight(); y++) {
if (image.getRGB(x, y) == inputColor.getRGB()) {
return true;
}
}
}
return false;
}
This method will return true if it can find the given inputColor in the screenshot. You might then use it in a loop as follows:
Color newColor = ...;
while (!checkColor(newColor)) {
new Color = new Color(114, 46, 33);
// Or change color in here for every iteration
}
This loop will terminate if it can't match the screenshot to newColor.

Categories

Resources