- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的程序在动态壁纸 Canvas 上绘制位图。它有效,但一段时间后图像变得非常糟糕(http://img855.imageshack.us/img855/9756/deviceq.png)
有什么想法吗?
package com.tripr;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.Align;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
/*
* This animated wallpaper draws a rotating wireframe cube.
*/
public class MyWallpaperService extends WallpaperService{
private final String TAG = "tripr";
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public Engine onCreateEngine() {
return new CubeEngine(this);
}
class CubeEngine extends Engine implements LocationListener{
private MyWallpaperService mws;
private float xOffset;
private float xStep;
private int xPixels;
private String lastPhotoUrl = "";
private LocationManager lm;
private Bitmap bmp = null;
private String locationName;
private String status = "waiting for location update...";
private final Handler mHandler = new Handler();
private final Runnable mDrawBtmp = new Runnable() {
public void run() {
drawFrame();
}
};
private boolean mVisible;
CubeEngine(MyWallpaperService mymws) {
mws = mymws;
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
requestLocationUpdates();
MyThread myThread = new MyThread(lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));
myThread.start();
}
//taken from http://p-xr.com/android-tutorial-how-to-parse-read-json-data-into-a-android-listview/
private JSONObject getJSONfromURL(String url){
//initialize
InputStream is = null;
String result = "";
JSONObject jArray = null;
//http post
try{
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e(TAG, "Error in http connection "+e.toString());
}
//convert response to string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
}catch(Exception e){
Log.e(TAG, "Error converting result "+e.toString());
}
//try parse the string to a JSON object
//Log.d(TAG, result);
try{
jArray = new JSONObject(result);
}catch(JSONException e){
Log.e(TAG, "Error parsing data "+e.toString());
}
return jArray;
}
String getFlickrUrl(double lat, double lon, double radius){
return "http://api.flickr.com/services/rest/?" +
"method=flickr.photos.search" +
"&api_key=a6d9db5ff2885dd2f8949590e7a44762" +
"&tags=architecture" +
"&lat=" + lat +
"&lon=" + lon +
"&radius=" + radius +
"&radius_units=km" +
"&extras=geo%2Curl_z%2Ctags" +
"&per_page=250" +
"&format=json" +
"&sort=interestingness-desc" +
"&nojsoncallback=1";
}
void requestLocationUpdates(){
if (!(lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER))){
status = "locating over network disabled";
//bmp = null;
}
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000*30, 10, this);
}
void removeUpdates(){
lm.removeUpdates(this);
}
@Override
public void onLocationChanged(Location location) {
MyThread myThread = new MyThread(location);
myThread.start();
}
@Override
public void onProviderDisabled(String provider) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
public void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(mDrawBtmp);
}
@Override
public void onVisibilityChanged(boolean visible) {
mVisible = visible;
if (visible) {
requestLocationUpdates();
drawFrame();
} else {
mHandler.removeCallbacks(mDrawBtmp);
removeUpdates();
}
}
@Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
drawFrame();
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
}
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
mVisible = false;
mHandler.removeCallbacks(mDrawBtmp);
}
@Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xStep, float yStep, int xPixels, int yPixels) {
/*Log.d(TAG, "onOffsetsChanged");
Log.d(TAG, "xOffset: " + String.valueOf(xOffset));
Log.d(TAG, "yOffset: " + String.valueOf(yOffset));
Log.d(TAG, "xStep: " + String.valueOf(xStep));
Log.d(TAG, "yStep: " + String.valueOf(yStep));
Log.d(TAG, "xPixels: " + String.valueOf(xPixels));
Log.d(TAG, "yPixels: " + String.valueOf(yPixels));
//Log.d(TAG, String.valueOf((xOffset / xStep)));
Log.d(TAG, " ");*/
this.xPixels = xPixels;
this.xStep = xStep;
this.xOffset = xOffset;
drawFrame();
}
/*
* Store the position of the touch event so we can use it for drawing later
*/
@Override
public void onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
}
/*
* Draw one frame of the animation. This method gets called repeatedly
* by posting a delayed Runnable. You can do any drawing you want in
* here. This example draws a wireframe cube.
*/
void drawFrame() {
final SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
// draw something
drawBmp(c);
}
} finally {
if (c != null) holder.unlockCanvasAndPost(c);
}
// Reschedule the next redraw
mHandler.removeCallbacks(mDrawBtmp);
if (mVisible) {
mHandler.postDelayed(mDrawBtmp, 1000 / 5);
}
}
private class MyThread extends Thread {
Location loc;
MyThread(Location loc){
this.loc = loc;
}
public synchronized void run(){ // bringt synchronized was? weil wir kreieren ja immer eine neue intanz...
try{
if (loc == null){
Log.d(TAG, "location is null");
return;
}
<SNIP>
//the main code, update `status` and `bmp`
}
void drawBmp(Canvas canvas) {
//canvas.restore();
//canvas.save();
//canvas.translate(0, 0);
//canvas.drawColor(0xff00aa00);
canvas.drawColor(Color.BLACK);
if (bmp != null){
//int width = (int) (((double)bmp.getHeight()/(double)canvas.getHeight())*canvas.getWidth());
if (bmp.getHeight() != canvas.getHeight()){
Float width = new Float(bmp.getWidth());
Float height = new Float(bmp.getHeight());
Float ratio = width/height;
Log.d(TAG, "scaling");
bmp = Bitmap.createScaledBitmap(bmp, (int)(canvas.getHeight()*ratio), canvas.getHeight(), true);
}
int x;
if (bmp.getWidth() >= canvas.getWidth()){
x = -1*(int)((xOffset*(bmp.getWidth()-canvas.getWidth())));
}else{
x = (bmp.getWidth()-canvas.getWidth())/2;
}
//Log.d(TAG, String.valueOf(scale));
//Log.d(TAG, String.valueOf(canvas.getWidth()));
//Log.d(TAG, " ");
canvas.drawBitmap(bmp, x, 0, null);
//canvas.drawLine(0, 0, bmp.getWidth(), 0, new Paint());
}else if(status != null){
Paint textPaint = new Paint();
textPaint.setColor(Color.WHITE);
textPaint.setAntiAlias(true);
textPaint.setTextSize(25);
textPaint.setAlpha(120);
textPaint.setTextAlign(Align.CENTER);
canvas.drawText(status, canvas.getWidth()/2, canvas.getHeight()/2, textPaint);
}
if (locationName != null){
Paint textPaint = new Paint();
textPaint.setColor(Color.BLACK);
textPaint.setAntiAlias(true);
textPaint.setTextSize(30);
textPaint.setAlpha(150);
textPaint.setTextAlign(Align.LEFT);
Rect rect = new Rect();
textPaint.getTextBounds(locationName, 0, locationName.length(), rect);
//Log.d(TAG, String.valueOf(textPaint.getTextSize()));
canvas.drawText(locationName, 0, 70, textPaint);
}
}
}
}
最佳答案
在 drawBmp()
中,您重复获取位图 (bmp
),对其进行缩放(调用 createScaledBitmap
),然后将其分配回去到 bmp
。随着时间的推移,所有这些缩放操作都会导致您看到的 Artifact 。
要解决此问题,请将原始位图存储在不同的变量中(例如,private Bitmap originalImage;
)并根据原始位图创建缩放后的位图。
bmp = Bitmap.createScaledBitmap(originalImage, (int)(canvas.getHeight()*ratio), canvas.getHeight(), true);
关于java - 许多 drawBitmap 后图像质量变差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6723613/
我试图在 ImageView 中显示图像的一部分。我用 canvas.drawBitmap() 试过了,但似乎显示了图像的错误部分。我的代码: 主要 Activity : this.drawC
我使用这样的 onDraw 方法显示图像: public void onDraw(Canvas canvas) { super.onDraw(canvas); Bitmap bac
我有一个 200x200 像素的位图。我想在我的 Canvas 上绘制位图的左上角 50x50px,坐标为 100,100,宽度和高度为 50px,方法是: drawBitmap(Bitmap bit
我正在使用 SurfaceView 编写 Android 游戏。 SurfaceView 获取的 Canvas 绘制了一个大小为 80x80 的 32 位 PNG 图像,带有 alpha 层。 dra
我正在编写一款 Android 游戏,我似乎遇到了在 Canvas 上绘图的性能问题。我的游戏有多个关卡,每个关卡中(显然)有不同数量的对象。 奇怪的是,在一个包含 45 张图像的关卡中,运行完美(几
如果我使用 drawBitmap() 在 View Canvas 上绘制位图,图像将被重新采样,这样图像中的 1 个像素将在屏幕上倾斜 1 个。在我拥有高像素密度的设备上,这意味着每个图像像素分布在
简单的乐趣 fun getCircleBitmap(bitmap: Bitmap, recycle: Boolean): Bitmap { val paint = Paint()
我是 Android 编码方面的新手。作为第一个项目,我决定移植 ZX Spectrum 游戏。我已经准备好了汽车的位图框架和按钮,它们将根据屏幕尺寸进行缩放。我已将图像放在“drawable”和“d
我的应用程序以连续循环的方式绘制到 Canvas 上,并在每个循环中重新评估可绘制对象的位置并循环它们以进行动画处理。我的问题是以下两种方法哪种更优越,为什么?我是一个初学者,所以我不知道如何对方法进
我必须在 map 上画一条线。由于特殊线条效果的要求,我不得不创建一个单独的位图并使用临时 Canvas 在该位图上绘制线条。现在当它完成绘制线条时,我将它渲染到主 Canvas 上。不幸的是,下面的
我正在尝试将位图叠加到另一个位图上,将其放置在用户触摸的位置。这是代码: public static Bitmap mergeImage(Bitmap base, Bitmap overlay, f
我最近遇到了一个问题 Android: Rotation of image around the center这是在Unconn的帮助下解决的。 然而,事实证明,这个解决方案——以及它的工作原理——确
我已经像这样为 DragShadowBuilder 覆盖了 onDragShadow @Override public void onDrawShadow(Canvas canvas) {
我有一个游戏,在其中一个关卡中,绵羊可能会被地雷炸毁。爆炸动画是通过在 512x515 png 文件中包含 4x4 爆炸图像阵列的 png 来控制的……见下文。 然后我使用以下代码为爆炸设置动画:
我一直在尝试在 Android 中制作一些 Sprite 动画(这是一项大学练习),但我遇到了一个奇怪的问题。它没有绘制我定义为源的矩形,而是恰好绘制了该矩形的一半。 这是我的绘图方法的代码 publ
我的程序在动态壁纸 Canvas 上绘制位图。它有效,但一段时间后图像变得非常糟糕(http://img855.imageshack.us/img855/9756/deviceq.png) 有什么想法
我正在扩展 SurfaceView 以创建全屏水平滚动背景。 我的问题是位图的质量。在绘图调用中用作 canvas.drawBitmap(bitmap, 0, 0, paint); 它的质量比原来的差
我正计划在我的游戏中实现一组新图形:普通圆圈。绘制的 Sprite (在本例中为圆圈)的数量从 2-3 开始,并且可以无限增加(可能)。不过,最大值可能在 60 左右。总共必须有 5 种类型的圆圈,每
我想绘制位图的子部分,但大小不同。如果大小大于位图中的源矩形,那么我希望位图的该部分平铺以填充目标区域。然而,它们并没有平铺,而是被拉伸(stretch)了。 我将所有变量设置如下: Bitmap b
我是 Android 新手,我有两张图片,一张是空图片,另一张是代表进度条的完整图片。 如何使用 canvas.drawBitmap 只绘制整个图像的一部分? 我不想每次都调整位图图像的大小。 最佳答
我是一名优秀的程序员,十分优秀!