目标效果:

    

该代码参考鸿洋大神的代码,并进行后期的整理修改。默认为随机填色,如果选择了颜色可以进行指定颜色填充,但填色边的效果暂时还不知道是什么原因。

1.values文件夹中新建attrs.xml页面,自定义属性。

attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="ColourImageView"><attr name="border_color" format="color|reference"></attr></declare-styleable>
</resources>

2.新建MyRadioGroup.java页面,重写RadioGroup控件,解决多行多列的单选按钮点击问题。

MyRadioGroup.java页面:

package com.example.weixu.view;import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.RadioButton;import java.util.ArrayList;
import java.util.HashMap;/*** Created by Dustray on 2017/4/8 0008.*/public class MyRadioGroup  extends LinearLayout {private static final String TAG = MyRadioGroup.class.getSimpleName();// holds the checked id; the selection is empty by defaultprivate int mCheckedId = -1;// tracks children radio buttons checked stateprivate CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;// when true, mOnCheckedChangeListener discards eventsprivate boolean mProtectFromCheckedChange = false;private OnCheckedChangeListener mOnCheckedChangeListener;private PassThroughHierarchyChangeListener mPassThroughListener;private HashMap<Integer, RadioButton> mRadioButtons = new HashMap<>();/*** {@inheritDoc}*/public MyRadioGroup(Context context) {super(context);setOrientation(VERTICAL);init();}/*** {@inheritDoc}*/public MyRadioGroup(Context context, AttributeSet attrs) {super(context, attrs);int orientation = this.getOrientation();setOrientation(orientation);init();}private void init() {mChildOnCheckedChangeListener = new CheckedStateTracker();mPassThroughListener = new PassThroughHierarchyChangeListener();super.setOnHierarchyChangeListener(mPassThroughListener);}/*** {@inheritDoc}*/@Overridepublic void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {// the user listener is delegated to our pass-through listenermPassThroughListener.mOnHierarchyChangeListener = listener;}/*** {@inheritDoc}*/@Overrideprotected void onFinishInflate() {super.onFinishInflate();// checks the appropriate radio button as requested in the XML fileif (mCheckedId != -1) {mProtectFromCheckedChange = true;setCheckedStateForView(mCheckedId, true);mProtectFromCheckedChange = false;setCheckedId(mCheckedId);}}@Overridepublic void addView(View child, int index, ViewGroup.LayoutParams params) {if (child instanceof RadioButton) {final RadioButton button = (RadioButton) child;if (button.isChecked()) {mProtectFromCheckedChange = true;if (mCheckedId != -1) {setCheckedStateForView(mCheckedId, false);}mProtectFromCheckedChange = false;setCheckedId(button.getId());}}super.addView(child, index, params);}/*** <p>Sets the selection to the radio button whose identifier is passed in* parameter. Using -1 as the selection identifier clears the selection;* such an operation is equivalent to invoking {@link #clearCheck()}.</p>** @param id the unique id of the radio button to select in this group** @see #getCheckedRadioButtonId()* @see #clearCheck()*/public void check(int id) {// don't even botherif (id != -1 && (id == mCheckedId)) {return;}if (mCheckedId != -1) {setCheckedStateForView(mCheckedId, false);}if (id != -1) {setCheckedStateForView(id, true);}setCheckedId(id);}private void setCheckedId(int id) {mCheckedId = id;if (mOnCheckedChangeListener != null) {mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);}}private void setCheckedStateForView(int viewId, boolean checked) {View checkedView = findViewById(viewId);if (checkedView != null && checkedView instanceof RadioButton) {((RadioButton) checkedView).setChecked(checked);}}/*** <p>Returns the identifier of the selected radio button in this group.* Upon empty selection, the returned value is -1.</p>** @return the unique id of the selected radio button in this group** @see #check(int)* @see #clearCheck()** @attr ref android.R.styleable#RadioGroup_checkedButton*/public int getCheckedRadioButtonId() {return mCheckedId;}/*** <p>Clears the selection. When the selection is cleared, no radio button* in this group is selected and {@link #getCheckedRadioButtonId()} returns* null.</p>** @see #check(int)* @see #getCheckedRadioButtonId()*/public void clearCheck() {check(-1);}/*** <p>Register a callback to be invoked when the checked radio button* changes in this group.</p>** @param listener the callback to call on checked state change*/public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {mOnCheckedChangeListener = listener;}/*** {@inheritDoc}*/@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {return new LayoutParams(getContext(), attrs);}/*** {@inheritDoc}*/@Overrideprotected boolean checkLayoutParams(ViewGroup.LayoutParams p) {return p instanceof LayoutParams;}@Overrideprotected LinearLayout.LayoutParams generateDefaultLayoutParams() {return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);}@Overridepublic void onInitializeAccessibilityEvent(AccessibilityEvent event) {super.onInitializeAccessibilityEvent(event);event.setClassName(MyRadioGroup.class.getName());}@Overridepublic void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {super.onInitializeAccessibilityNodeInfo(info);info.setClassName(MyRadioGroup.class.getName());}public static class LayoutParams extends LinearLayout.LayoutParams {/*** {@inheritDoc}*/public LayoutParams(Context c, AttributeSet attrs) {super(c, attrs);}/*** {@inheritDoc}*/public LayoutParams(int w, int h) {super(w, h);}/*** {@inheritDoc}*/public LayoutParams(int w, int h, float initWeight) {super(w, h, initWeight);}/*** {@inheritDoc}*/public LayoutParams(ViewGroup.LayoutParams p) {super(p);}/*** {@inheritDoc}*/public LayoutParams(MarginLayoutParams source) {super(source);}/*** <p>Fixes the child's width to* {@link ViewGroup.LayoutParams#WRAP_CONTENT} and the child's* height to  {@link ViewGroup.LayoutParams#WRAP_CONTENT}* when not specified in the XML file.</p>** @param a the styled attributes set* @param widthAttr the width attribute to fetch* @param heightAttr the height attribute to fetch*/@Overrideprotected void setBaseAttributes(TypedArray a,int widthAttr, int heightAttr) {if (a.hasValue(widthAttr)) {width = a.getLayoutDimension(widthAttr, "layout_width");} else {width = WRAP_CONTENT;}if (a.hasValue(heightAttr)) {height = a.getLayoutDimension(heightAttr, "layout_height");} else {height = WRAP_CONTENT;}}}/*** <p>Interface definition for a callback to be invoked when the checked* radio button changed in this group.</p>*/public interface OnCheckedChangeListener {/*** <p>Called when the checked radio button has changed. When the* selection is cleared, checkedId is -1.</p>** @param group the group in which the checked radio button has changed* @param checkedId the unique identifier of the newly checked radio button*/public void onCheckedChanged(MyRadioGroup group, int checkedId);}private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {// prevents from infinite recursionif (mProtectFromCheckedChange) {return;}mProtectFromCheckedChange = true;if (mCheckedId != -1) {setCheckedStateForView(mCheckedId, false);}mProtectFromCheckedChange = false;int id = buttonView.getId();setCheckedId(id);}}public RadioButton getRadioButtonByCheckedId(int checkedId){return mRadioButtons.get(checkedId);}/*** <p>A pass-through listener acts upon the events and dispatches them* to another listener. This allows the table layout to set its own internal* hierarchy change listener without preventing the user to setup his.</p>*/private class PassThroughHierarchyChangeListener implementsOnHierarchyChangeListener {private OnHierarchyChangeListener mOnHierarchyChangeListener;private int checkedCount = 0;/*** 找到布局下所有RadioButton* @param vg* @return*/public ArrayList<RadioButton> findRadioButtons(ViewGroup vg) {ArrayList<RadioButton> set = new ArrayList<>();int count = vg.getChildCount();for (int i = 0 ; i < count ; i ++) {View view = vg.getChildAt(i);if (view instanceof RadioButton) {set.add(((RadioButton) view));} else if (view instanceof ViewGroup){set.addAll(findRadioButtons((ViewGroup) view));}}return set;}/*** 为RadioButton设置id和监听器* @param rb*/public void setIdAndOnCheckedChangeListener(RadioButton rb){int id = rb.getId();if (id == View.NO_ID) {id = View.generateViewId();rb.setId(id);}rb.setOnCheckedChangeListener( mChildOnCheckedChangeListener);if (rb.isChecked()) {if (checkedCount ++ > 1) {Log.e(TAG, "You can only select one RadioButton");}mCheckedId = rb.getId();}if (checkedCount > 1) {MyRadioGroup.this.removeAllViews();}mRadioButtons.put(id, rb);}/*** {@inheritDoc}*/public void onChildViewAdded(View parent, View child) {if (parent == MyRadioGroup.this && child instanceof RadioButton) {setIdAndOnCheckedChangeListener((RadioButton) child);} else if (parent == MyRadioGroup.this && child instanceof ViewGroup) {ArrayList<RadioButton> hs = findRadioButtons((ViewGroup) child);for (RadioButton rb : hs) {setIdAndOnCheckedChangeListener(rb);}}if (mOnHierarchyChangeListener != null) {mOnHierarchyChangeListener.onChildViewAdded(parent, child);}}/*** {@inheritDoc}*/public void onChildViewRemoved(View parent, View child) {if (parent == MyRadioGroup.this && child instanceof RadioButton) {((RadioButton) child).setOnCheckedChangeListener(null);}if (mOnHierarchyChangeListener != null) {mOnHierarchyChangeListener.onChildViewRemoved(parent, child);}}}
}
3.新建ColourImageView.java页面,重写AppCompatImageView控件,鸿洋大神源码为重写ImageView,因为一直报错,所以用了这个,不知道后来出现的问题是不是和这个有关。
ColourImageView.java页面:
package com.example.weixu.view;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.support.v7.widget.AppCompatImageView;
import android.util.Log;
import android.view.MotionEvent;import com.example.weixu.munal.R;import java.util.Random;
import java.util.Stack;/*** Created by weixu on 2017/4/8.*/public class ColourImageView extends AppCompatImageView {private int myColor;        //接收选择的颜色private boolean myColorType;    //判断是否选择颜色,选择为true,未选择为falsepublic void setMyColor(int myColor) {this.myColor = myColor;}public void setMyColorType(boolean myColorType) {this.myColorType = myColorType;}private Bitmap mBitmap;//边界颜色private int mBorderColor = -1;private boolean hasBorderColor = false;private Stack<Point> mStacks = new Stack<Point>();   //栈public ColourImageView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ColourImageView);   //用于自定义属性mBorderColor = ta.getColor(R.styleable.ColourImageView_border_color, -1);hasBorderColor = (mBorderColor != -1);ta.recycle();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){super.onMeasure(widthMeasureSpec, heightMeasureSpec);int viewWidth = getMeasuredWidth();//以宽度为标准,等比例缩放view的高度setMeasuredDimension(viewWidth,getDrawable().getIntrinsicHeight() * viewWidth / getDrawable().getIntrinsicWidth());//根据drawable,去得到一个和view一样大小的bitmapBitmapDrawable drawable = (BitmapDrawable) getDrawable();Bitmap bm = drawable.getBitmap();mBitmap = Bitmap.createScaledBitmap(bm, getMeasuredWidth(), getMeasuredHeight(), false);}@Overridepublic boolean onTouchEvent(MotionEvent event){final int x = (int) event.getX();final int y = (int) event.getY();if (event.getAction() == MotionEvent.ACTION_DOWN){//填色fillColorToSameArea(x, y);}return super.onTouchEvent(event);}/*** 根据x,y获得该点颜色,进行填充     ** @param x* @param y*/private void fillColorToSameArea(int x, int y){Bitmap bm = mBitmap;int pixel = bm.getPixel(x, y);if (pixel == Color.TRANSPARENT || (hasBorderColor && mBorderColor == pixel)){return;}int newColor;if(myColorType)newColor=myColor;elsenewColor = randomColor();int w = bm.getWidth();int h = bm.getHeight();//拿到该bitmap的颜色数组int[] pixels = new int[w * h];bm.getPixels(pixels, 0, w, 0, 0, w, h);//填色fillColor(pixels, w, h, pixel, newColor, x, y);//重新设置bitmapbm.setPixels(pixels, 0, w, 0, 0, w, h);setImageDrawable(new BitmapDrawable(bm));}/*** @param pixels   像素数组* @param w        宽度* @param h        高度* @param pixel    当前点的颜色* @param newColor 填充色* @param i        横坐标* @param j        纵坐标*/private void fillColor(int[] pixels, int w, int h, int pixel, int newColor, int i, int j){//步骤1:将种子点(x, y)入栈;mStacks.push(new Point(i, j));//步骤2:判断栈是否为空,// 如果栈为空则结束算法,否则取出栈顶元素作为当前扫描线的种子点(x, y),// y是当前的扫描线;while (!mStacks.isEmpty()){/*** 步骤3:从种子点(x, y)出发,沿当前扫描线向左、右两个方向填充,* 直到边界。分别标记区段的左、右端点坐标为xLeft和xRight;*/Point seed = mStacks.pop();//L.e("seed = " + seed.x + " , seed = " + seed.y);int count = fillLineLeft(pixels, pixel, w, h, newColor, seed.x, seed.y);int left = seed.x - count + 1;count = fillLineRight(pixels, pixel, w, h, newColor, seed.x + 1, seed.y);int right = seed.x + count;/*** 步骤4:* 分别检查与当前扫描线相邻的y - 1和y + 1两条扫描线在区间[xLeft, xRight]中的像素,* 从xRight开始向xLeft方向搜索,假设扫描的区间为AAABAAC(A为种子点颜色),* 那么将B和C前面的A作为种子点压入栈中,然后返回第(2)步;*///从y-1找种子if (seed.y - 1 >= 0)findSeedInNewLine(pixels, pixel, w, h, seed.y - 1, left, right);//从y+1找种子if (seed.y + 1 < h)findSeedInNewLine(pixels, pixel, w, h, seed.y + 1, left, right);}}/*** 在新行找种子节点** @param pixels* @param pixel* @param w* @param h* @param i* @param left* @param right*/private void findSeedInNewLine(int[] pixels, int pixel, int w, int h, int i, int left, int right){/*** 获得该行的开始索引*/int begin = i * w + left;/*** 获得该行的结束索引*/int end = i * w + right;boolean hasSeed = false;int rx = -1, ry = -1;ry = i;/*** 从end到begin,找到种子节点入栈(AAABAAAB,则B前的A为种子节点)*/while (end >= begin){if (pixels[end] == pixel){if (!hasSeed){rx = end % w;mStacks.push(new Point(rx, ry));hasSeed = true;}} else{hasSeed = false;}end--;}}/*** 往右填色,返回填充的个数** @return*/private int fillLineRight(int[] pixels, int pixel, int w, int h, int newColor, int x, int y){int count = 0;while (x < w){//拿到索引int index = y * w + x;if (needFillPixel(pixels, pixel, index)){pixels[index] = newColor;count++;x++;} else{break;}}return count;}/*** 往左填色,返回填色的数量值** @return*/private int fillLineLeft(int[] pixels, int pixel, int w, int h, int newColor, int x, int y){int count = 0;while (x >= 0){//计算出索引int index = y * w + x;if (needFillPixel(pixels, pixel, index)){pixels[index] = newColor;count++;x--;} else{break;}}return count;}private boolean needFillPixel(int[] pixels, int pixel, int index){if (hasBorderColor){return pixels[index] != mBorderColor;} else{return pixels[index] == pixel;}}/*** 产生随机颜色* @return*/public int randomColor(){Random random = new Random();int color = Color.argb(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));return color;}
}
4.activity_main.xml页面:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.example.weixu.munal.MainActivity"><com.example.weixu.view.MyRadioGroupandroid:layout_marginTop="20dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:orientation="horizontal"><RadioButtonandroid:id="@+id/rbRed"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="changeColor"android:text="红色" /><RadioButtonandroid:id="@+id/rbOrange"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="changeColor"android:text="橙色" /><RadioButtonandroid:id="@+id/rbYellow"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="changeColor"android:text="黄色" /><RadioButtonandroid:id="@+id/rbGreen"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="changeColor"android:text="绿色" /><RadioButtonandroid:id="@+id/rbCyan"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="changeColor"android:text="青色" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:orientation="horizontal"><RadioButtonandroid:id="@+id/rbBlue"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="changeColor"android:text="蓝色" /><RadioButtonandroid:id="@+id/rbPurple"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="changeColor"android:text="紫色" /><RadioButtonandroid:id="@+id/rbBrown"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="changeColor"android:text="棕色" /><RadioButtonandroid:id="@+id/rbBlack"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="changeColor"android:text="黑色" /><RadioButtonandroid:id="@+id/rbRandom"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="changeColor"android:checked="true"android:text="随机" /></LinearLayout></com.example.weixu.view.MyRadioGroup><com.example.weixu.view.ColourImageViewandroid:id="@+id/civColorIn"android:gravity="center"android:layout_width="match_parent"android:layout_height="wrap_content"app:srcCompat="@drawable/butterfly" /><Buttonandroid:id="@+id/btClean"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="btClick"android:text="清空" />
</LinearLayout>
5.MainActivity.java页面:
package com.example.weixu.munal;import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;import com.example.weixu.view.ColourImageView;import java.util.Random;public class MainActivity extends AppCompatActivity {private ColourImageView civColorIn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();civColorIn.setMyColorType(false);    //默认为false,只有选择颜色财位true}private void init() {civColorIn= (ColourImageView) findViewById(R.id.civColorIn);}public void changeColor(View view){switch (view.getId()){case R.id.rbRed:setColor(255,255,0,0);break;case R.id.rbOrange:setColor(255,255,125,0);break;case R.id.rbYellow:setColor(255,255,255,0);break;case R.id.rbGreen:setColor(255,0,255,0);break;case R.id.rbCyan:setColor(255,0,255,255);break;case R.id.rbBlue:setColor(255,0,255,255);break;case R.id.rbPurple:setColor(255,255,0,255);break;case R.id.rbBrown:setColor(255,125,100,10);break;case R.id.rbBlack:setColor(255,0,0,0);break;case R.id.rbRandom:civColorIn.setMyColorType(false);   //选择随机则传递falsebreak;}}public void btClick(View view){switch (view.getId()){case R.id.btClean:civColorIn.setImageResource(R.drawable.butterfly);   //清空break;}}//如果选择了颜色,传递选中的颜色,并设置为truepublic void setColor(int a,int r,int g,int b){civColorIn.setMyColor(Color.argb(a,r,g,b));civColorIn.setMyColorType(true);}}
源码: 点击下载

Android-图片填色相关推荐

  1. android studio写一个圆填色,数字填色秘密花园

    数字填色秘密花园是一款休闲填色类游戏,拥有大量的美图资源,休闲涂色玩法,让你在闲暇时间享受到充满艺术氛围的游戏体验,同时还支持自由创作玩法哦~本次放出数字填色秘密花园安卓版下载,喜欢休闲艺术涂色类游戏 ...

  2. Android图片压缩(质量压缩和尺寸压缩)

    在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...

  3. android 图片压缩总结1

    在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...

  4. 最详细的Android图片压缩攻略

    Mr.Louis的博客地址: https://blog.csdn.net/weixin_44005563 最近在研究图片压缩原理,看了大量资料,从上层尺寸压缩.质量压缩原理到下层的哈夫曼压缩,走成华大 ...

  5. android图片处理方法(不断收集中)

    //压缩图片大小 public static Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArr ...

  6. python画填色图时,如何让分层的填色变为渐变色

    python画填色图时,如何让分层的填色变为渐变色 注:自己用来备忘的 以画海洋的地形图为例 数据为一个三位数据,有经度(lon),纬度(lat),高度(z)三个变量. 我们绘制的地形图为了美观,只想 ...

  7. Android图片海报制作软件开发实践

    Android图片海报制作软件开发实践 项目地址:https://github.com/coolstar1204/MakePoster 本博客分以下几个文章,从头记录我学习Material Desig ...

  8. python气象数据可视化学习记录1——基于ERA5数据画风场和海平面气压填色叠加图

    python气象数据可视化学习记录1--基于ERA5数据画风场和海平面气压填色叠加图 1. 写在前面 2. 图片效果 3. 逐步代码解析 3.1导入库 3.2 读取NC格式数据 3.3 对数据进行加工 ...

  9. Android图片视频拍摄选取及压缩

    Android图片视频选取及压缩上传 此博客的主要技术点 需求 开车了 图片选择库 视频压缩 上传 此博客的主要技术点 视频拍摄.视频选取获取视频地址 视频压缩 视频上传 需求 我的项目1.0版本最近 ...

  10. Android图片压缩(质量压缩和尺寸压缩)Bitmap转成字符串上传

    在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...

最新文章

  1. b是python文件二进制打开_如何在Python中打开和显示原始二进制数据?
  2. Ubuntu14.04安装apt-get方法Lnmp环境
  3. linux端口命令是什么意思,cmd和linux的查看端口命令是什么?
  4. camera驱动框架分析(上)
  5. Qt工作笔记-SIGNAL之textChanged
  6. 15款最佳的响应式 Web 设计测试工具
  7. 【015】基于51单片机的LCD1602流动字符串proteus仿真设计
  8. F2FS文件系统一 设计背景及框架结构
  9. 基于Zabbix的校园网核心监控系统设计与实现
  10. ES6的新特性,前端必看知识点
  11. i78700k配什么显卡好_最新适合搭配i7-8700的显卡推荐 i7 8700配什么显卡好
  12. RFID技术对危化品实行安全化
  13. 爬虫:UnicodeDecodeError: 'gbk' codec can't decode byte 0xa6 in position
  14. icp许可证和edi许可证区别是什么?
  15. 发生身份验证错误。要求的函数不受支持(远程连接)
  16. 百度js 检测输入法_百度快照是什么意思,如何删除百度快照
  17. 论文阅读——A HYBRID TEXT NORMALIZATION SYSTEM USING MULTI-HEAD SELF-ATTENTION FOR MANDARIN
  18. 压力测试与服务端调优(1)
  19. 金士顿DT101 G2 旋转盘量产教程 还可刷固件
  20. 微信小程序(JAVAScript)实现饼图

热门文章

  1. 搭建JavaWeb开发环境(Eclipse版)
  2. php程序员述职材料_php程序员述职报告精选
  3. bestcoder r44 p3 hdu 5270 ZYB loves Xor II
  4. 未转变者怎么进入服务器,steam未转变者怎么点到服务器怎么进去 | 手游网游页游攻略大全...
  5. JavaScript 的 深浅 拷贝
  6. 什么是hidl_protobuf 在通过 hidl 接口传输时,是不是应该用 string 啊
  7. 怎样申请淘宝u站?怎么能快速申请到淘宝U站?淘宝u站申请方法
  8. java计算年龄_java实现简单年龄计算器
  9. 塑料:聚乙烯(PE). 聚氯乙烯(PVC), 聚苯乙烯(PS), 聚丙烯(PP), ABS 树脂
  10. 参与美国某大学游戏开发俱乐部 Game Jam 记录与分享