Java?zxing實(shí)現(xiàn)生成并解析二維碼與條形碼
1、maven依賴
<!--zxing依賴-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.1.0</version>
</dependency>
2、一些重要屬性方法
BarcodeFormat (碼類型)
設(shè)置生成條形碼的類型。
如:二維碼、EAN-13碼、UPC-A碼、Code-128碼、Code-39碼等等。
| 條形碼類型 |
| BarcodeFormat.AZTEC 阿茲特克碼 |
| BarcodeFormat.CODABAR Codabar碼 |
| BarcodeFormat.CODE_39 CODE-30碼 |
| BarcodeFormat.CODE_93 CODE-93碼 |
| BarcodeFormat.CODE_128 CODE-128碼 |
| BarcodeFormat.DATA_MATRIX 矩陣式二維條碼 |
| BarcodeFormat.EAN_8 EAN-8碼 |
| BarcodeFormat.EAN_13 EAN-13碼 |
| BarcodeFormat.ITF 交插二五條碼 |
| BarcodeFormat.MAXICODE MaxiCode二維條碼 |
| BarcodeFormat.PDF_417 ; PDF417 |
| BarcodeFormat.QR_CODE 二維碼 |
| BarcodeFormat.RSS_14 RSS 14 |
| BarcodeFormat.RSS_EXPANDED RSS EXPANDED |
| BarcodeFormat.UPC_A UPC A |
| BarcodeFormat.UPC_E UPC E |
| BarcodeFormat.UPC_EAN_EXTENSION UPC EAN EXTENSION |
EncodeHintType(自定義屬性)


3、帶logo得到二維碼生成
/**
* @description: 二維碼生成
* @author: HK
* @since: 2024/11/4 10:16
*/
public class Test3 {
private static final Integer CODE_WIDTH = 300; // 基礎(chǔ)屬性:二維碼寬度,單位像素
private static final Integer CODE_HEIGHT = 300; // 基礎(chǔ)屬性:二維碼高度,單位像素
private static final Integer FRONT_COLOR = 0x000000; // 基礎(chǔ)屬性:二維碼前景色,0x000000 表示黑色
private static final Integer BACKGROUND_COLOR = 0xFFFFFF; // 基礎(chǔ)屬性:二維碼背景色,0xFFFFFF 表示白色
public static void main(String[] args) throws Exception {
//設(shè)置生成二維碼的內(nèi)容
String qrMessage = "https://www.baidu.com";
// EncodeHintType:編碼提示類型,枚舉類型
// EncodeHintType.CHARACTER_SET:設(shè)置字符編碼類型
// EncodeHintType.ERROR_CORRECTION:設(shè)置誤差校正
// ErrorCorrectionLevel:誤差校正等級(jí),
// L = ~7% correction、M = ~15% correction、
// Q = ~25% correction、H = ~30% correction
// 不設(shè)置時(shí),默認(rèn)為 L 等級(jí),等級(jí)不一樣,生成的圖案不同,但掃描的結(jié)果是一樣的
// EncodeHintType.MARGIN:設(shè)置二維碼邊距,單位像素,值越小,二維碼距離四周越近
Map<EncodeHintType, Object> typeObjectHashMap = new HashMap<EncodeHintType, Object>();
typeObjectHashMap.put(EncodeHintType.CHARACTER_SET, "UTF-8");
typeObjectHashMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
typeObjectHashMap.put(EncodeHintType.MARGIN, 1);
// MultiFormatWriter:多格式寫入,這是一個(gè)工廠類,里面重載了兩個(gè) encode 方法,用于寫入條形碼或二維碼
// encode(String contents,BarcodeFormat format,int width, int height,Map<EncodeHintType,?> hints)
// 參數(shù)1:contents:條形碼/二維碼內(nèi)容
// 參數(shù)2:format:編碼類型,如 條形碼,二維碼 等
// 參數(shù)3:width:碼的寬度
// 參數(shù)4:height:碼的高度
// 參數(shù)5:hints:碼內(nèi)容的編碼類型
// BarcodeFormat:枚舉該程序包已知的條形碼格式,即創(chuàng)建何種碼,如 1 維的條形碼,2 維的二維碼 等
// BitMatrix:位(比特)矩陣或叫2D矩陣,也就是需要的二維碼
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
BitMatrix bitMatrix = multiFormatWriter
.encode(qrMessage, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, typeObjectHashMap);
// java.awt.image.BufferedImage:具有圖像數(shù)據(jù)的可訪問(wèn)緩沖圖像,實(shí)現(xiàn)了 RenderedImage 接口
// BitMatrix 的 get(int x, int y) 獲取比特矩陣內(nèi)容,指定位置有值,則返回true,將其設(shè)置為前景色,否則設(shè)置為背景色
// BufferedImage 的 setRGB(int x, int y, int rgb) 方法設(shè)置圖像像素
// 參數(shù)1 x:像素位置的橫坐標(biāo),即列
// 參數(shù)2 y:像素位置的縱坐標(biāo),即行
// 參數(shù)3 rgb:像素的值,采用 16 進(jìn)制,如 0xFFFFFF 白色
BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
for (int x = 0; x < CODE_WIDTH; x++) {
for (int y = 0; y < CODE_HEIGHT; y++) {
bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
}
}
// 把logo圖片設(shè)置到二維碼中間位置(若不想在二維碼中間插入logo圖片則不執(zhí)行此條代碼)
insertLogoImage(bufferedImage, new FileInputStream("d://hello.jpg"));
// javax.imageio.ImageIO java擴(kuò)展的圖像IO
// write(RenderedImage im,String formatName,File output)
// im:待寫入的圖像
// formatName:圖像寫入的格式
// output:寫入的圖像文件,文件不存在時(shí)會(huì)自動(dòng)創(chuàng)建
// 即將保存的二維碼圖片文件
ImageIO.write(bufferedImage, "png", new FileOutputStream("d://hello.png"));
}
/***
* 為二維碼插入中間的logo圖片
* @param bufferedImage 二維碼圖片信息
* @param logoInput logo圖片位置
* @throws IOException 拋出IO異常
*/
private static void insertLogoImage(BufferedImage bufferedImage, InputStream logoInput) throws IOException {
// 加載Logo圖片到Image對(duì)象
Image logoImage = ImageIO.read(logoInput);
// 設(shè)置二維碼中間的Logo圖片(設(shè)置logo圖片的寬高需要保持和二維碼寬高的一半寬高)
int logoWidth = CODE_WIDTH / 5;
int logoHeight = CODE_HEIGHT / 5;
// 按照指定的寬高進(jìn)行等比縮放(若設(shè)置的寬高比之前大則代表放大),并將縮放后的圖片繪制到一個(gè)新的BufferedImage對(duì)象中
Image image = logoImage.getScaledInstance(logoWidth, logoHeight, Image.SCALE_SMOOTH);
BufferedImage logoBufferedImage = new BufferedImage(logoWidth, logoHeight, BufferedImage.TYPE_INT_RGB);
// 獲取圖形上下文對(duì)象,用于后續(xù)將縮放后的圖片繪制在 logoBufferedImage 對(duì)象上
Graphics graphics = logoBufferedImage.getGraphics();
// 繪制縮放后的圖片到 logoBufferedImage 對(duì)象上,使其填滿整個(gè)畫布
graphics.drawImage(image, 0, 0, null);
// 釋放圖形上下文對(duì)象,避免內(nèi)存泄漏
graphics.dispose();
// 把處理好的logo圖片再次設(shè)置給之前的logo圖片對(duì)象
logoImage = image;
// 開(kāi)始把logo圖片插入到二維碼的中間位置
// 獲取 Graphics2D 對(duì)象,用于后續(xù)在 bufferedImage 上繪制二維碼和 logo 圖片
Graphics2D graph = bufferedImage.createGraphics();
// 計(jì)算出 logo 圖片在二維碼中間的坐標(biāo)點(diǎn) (x, y),以便后續(xù)將 logo 圖片插入到正確的位置。
int x = (CODE_WIDTH - logoWidth) / 2;
int y = (CODE_HEIGHT - logoHeight) / 2;
// 繪制縮放后的 logo 圖片到二維碼中間位置
graph.drawImage(logoImage, x, y, logoWidth, logoHeight, null);
// 設(shè)置邊框的線條粗細(xì)為 3 像素,并且設(shè)置線條是一個(gè)圓角矩形,6表示圓角的半徑。并關(guān)閉資源
graph.setStroke(new BasicStroke(3f));
graph.draw(new RoundRectangle2D.Float(x, y, logoWidth, logoHeight, 6, 6));
graph.dispose();
}
}4、解析二維碼
/**
* 二維碼解析
*
* @author Anhui OuYang
* @version 1.0
**/
public class QRCodeParsing {
public static void main(String[] args) throws Exception {
System.out.println("=========================二維碼解析 Start=========================");
parsingQRCode(new File("d://222.png"));
System.out.println("=========================二維碼解析 End=========================");
}
/***
* 二維碼(QR_CODE)解析
* @param file 文件路徑信息
*/
public static void parsingQRCode(File file) throws IOException, NotFoundException {
//創(chuàng)建一個(gè)圖像數(shù)據(jù)緩沖區(qū)類(并讀取二維碼圖片)
BufferedImage bufferedImage = ImageIO.read(file);
// 對(duì)圖片信息的圖像處理和分析
// 注意需要 zxing 庫(kù)的版本 3.2.1 或更高版本才能使用,若沒(méi)有則使用我下面定義的getRGBPixelData(BufferedImage image)
BufferedImageLuminanceSource luminanceSource = new BufferedImageLuminanceSource(bufferedImage);
// 若版本不夠則使用這種方式
// RGBLuminanceSource luminanceSource = new RGBLuminanceSource(bufferedImage.getWidth(),
// bufferedImage.getHeight(), getRGBPixelData(bufferedImage));
// 創(chuàng)建BinaryBitmap對(duì)象
// BinaryBitmap是二值化位圖,將像素從RGB空間轉(zhuǎn)換為黑白顏色空間
BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource));
// 設(shè)置解碼參數(shù)
Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 設(shè)置解析的字符集
// 使用 MultiFormatReader 進(jìn)行解碼
MultiFormatReader formatReader = new MultiFormatReader();
formatReader.setHints(hints); // 設(shè)置解碼一些參數(shù)
Result result = formatReader.decode(binaryBitmap); // 解碼(解析binaryBitmap數(shù)據(jù))
// 打印一些信息
System.out.println("二維碼解析圖片的路徑: " + file.getPath());
System.out.println("二維碼解析圖片中格式: " + result.getBarcodeFormat());
System.out.println("二維碼解析圖片中內(nèi)容: " + result.getText());
}
}5、條形碼
簡(jiǎn)單條形碼(無(wú)文字)
public class GenerateBarcode {
private static final Integer CODE_WIDTH = 300; // 基礎(chǔ)屬性:二維碼寬度,單位像素
private static final Integer CODE_HEIGHT = 150; // 基礎(chǔ)屬性:二維碼高度,單位像素
private static final Integer FRONT_COLOR = 0x000000; // 基礎(chǔ)屬性:二維碼前景色,0x000000 表示黑色
private static final Integer BACKGROUND_COLOR = 0xFFFFFF; // 基礎(chǔ)屬性:二維碼背景色,0xFFFFFF 表示白色
public static void main(String[] args) throws Exception {
//設(shè)置生成條形碼的內(nèi)容(注:條形碼信息一定要按照格式,如隨便一個(gè)商品上的條形碼都行,但必須是EAN_13格式)
String qrMessage = "6971483746515";
// EncodeHintType:指定和控制碼生成器的一些參數(shù)的類
Map<EncodeHintType, Object> typeObjectHashMap = new HashMap<EncodeHintType, Object>();
// 設(shè)置編碼
typeObjectHashMap.put(EncodeHintType.CHARACTER_SET, "UTF-8");
// 設(shè)置容錯(cuò)等級(jí)
typeObjectHashMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 設(shè)置邊距,默認(rèn)為5
typeObjectHashMap.put(EncodeHintType.MARGIN, 3);
// MultiFormatWriter:用于寫入條形碼或二維碼
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
BitMatrix bitMatrix = multiFormatWriter
.encode(qrMessage, BarcodeFormat.EAN_13, CODE_WIDTH, CODE_HEIGHT, typeObjectHashMap);
// java.awt.image.BufferedImage:把條形碼信息轉(zhuǎn)換為圖像信息
BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
for (int x = 0; x < CODE_WIDTH; x++) {
for (int y = 0; y < CODE_HEIGHT; y++) {
bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
}
}
// javax.imageio.ImageIO 將圖片信息寫出到文件
ImageIO.write(bufferedImage, "png", new FileOutputStream("d://222.png"));
}
}
條形碼(含文字)
/**
* 一個(gè)簡(jiǎn)單的條形碼生成
*
* @author Anhui OuYang
* @version 1.0
**/
public class GenerateBarcode {
private static final Integer CODE_WIDTH = 300; // 基礎(chǔ)屬性:二維碼寬度,單位像素
private static final Integer CODE_HEIGHT = 150; // 基礎(chǔ)屬性:二維碼高度,單位像素
private static final Integer FRONT_COLOR = 0x000000; // 基礎(chǔ)屬性:二維碼前景色,0x000000 表示黑色
private static final Integer BACKGROUND_COLOR = 0xFFFFFF; // 基礎(chǔ)屬性:二維碼背景色,0xFFFFFF 表示白色
public static void main(String[] args) throws Exception {
// 條形碼底部?jī)?nèi)容
String bottomStr = "123456";
// 條形碼左上角內(nèi)容
//String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);
String topLeftStr = "ceshi";
// 條形碼右上角內(nèi)容
String topRightStr = "2024-11-4";
// 生成條形碼
BufferedImage barCodeImage = create(bottomStr, 250, 50);
BufferedImage withWords = createWithWords(
barCodeImage,
bottomStr,
topLeftStr,
topRightStr,
250,
150,
10,
14);
ImageIO.write(withWords, "png", new FileOutputStream("d://222.png"));
barCodeImage = create(bottomStr, 350, 70);
withWords = createWithWords(
barCodeImage,
bottomStr,
topLeftStr,
topRightStr,
350,
210,
14,
20);
ImageIO.write(withWords, "png", new FileOutputStream("d://333.png"));
barCodeImage = create(bottomStr, 500, 100);
withWords = createWithWords(
barCodeImage,
bottomStr,
topLeftStr,
topRightStr,
500,
300,
20,
28);
ImageIO.write(withWords, "png", new FileOutputStream("d://444.png"));
}
/**
* 生成簡(jiǎn)單條形碼(無(wú)文字)
*
* @param content
* @param width
* @param height
* @return
*/
public static BufferedImage create(String content, int width, int height) {
// 定義位圖矩陣BitMatrix
BitMatrix matrix = null;
try {
// 定義二維碼參數(shù)
Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(3);
// 設(shè)置編碼
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
// 設(shè)置容錯(cuò)等級(jí)
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 設(shè)置邊距,默認(rèn)為5
hints.put(EncodeHintType.MARGIN, 3);
// 使用code_128格式進(jìn)行編碼生成條形碼
MultiFormatWriter writer = new MultiFormatWriter();
matrix = writer.encode(content, BarcodeFormat.CODE_128, width, height, hints);
} catch (WriterException e) {
e.printStackTrace();
//throw new RuntimeException("條形碼內(nèi)容寫入失敗");
}
return MatrixToImageWriter.toBufferedImage(matrix);
}
/**
* 生成條形碼(含文字)
* ****************************************************
* ----------------------------------------------
* | 2023-06-10 10:55 |
* | |
* | 商品名稱 /超出不顯示/ |
* | |
* | | || ||| | || |||| | | | ||| | | || |
* | | || ||| | || |||| | | | ||| | | || |
* | | || ||| | || |||| | | | ||| | | || |
* | | || ||| | || |||| | | | ||| | | || |
* | 13800000000 |
* ----------------------------------------------
* ===================================================
* 1、日期:頂部右側(cè)
* 2、商品名稱:居中
* 3、條形碼:商品名稱下方,且居中
* 4、條碼內(nèi)容:條形碼下方,且居中
* *****************************************************
*
* @param codeImage 條形碼圖片
* @param bottomStr 底部文字
* @param titleStr 標(biāo)題文字
* @param topRightStr 右上角文字
* @param pictureWidth 圖片寬度
* @param pictureHeight 圖片高度
* @param margin 邊距
* @param fontSize 字體大小
* @return 條形碼圖片
*/
private static BufferedImage createWithWords(
BufferedImage codeImage,
String bottomStr,
String titleStr,
String topRightStr,
int pictureWidth,
int pictureHeight,
int margin,
int fontSize) {
BufferedImage picImage = new BufferedImage(pictureWidth, pictureHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = picImage.createGraphics();
// 抗鋸齒
setGraphics2D(g2d);
// 設(shè)置白色
setColorWhite(g2d, picImage.getWidth(), picImage.getHeight());
// 條形碼默認(rèn)居中顯示
int codeStartX = (pictureWidth - codeImage.getWidth()) / 2;
int codeStartY = (pictureHeight - codeImage.getHeight()) / 2 + 2 * margin;
// 畫條形碼到新的面板
g2d.drawImage(codeImage, codeStartX, codeStartY, codeImage.getWidth(), codeImage.getHeight(), null);
// 給條碼上下各畫一條線
// 設(shè)置顏色
g2d.setColor(Color.LIGHT_GRAY);
int y1 = 2 * margin + codeImage.getHeight();
int y2 = 2 * margin + 2 * codeImage.getHeight();
g2d.drawLine(0, y1, pictureWidth, y1);
g2d.drawLine(0, y2, pictureWidth, y2);
// 畫文字到新的面板
g2d.setColor(Color.BLACK);
// 字體、字型、字號(hào)
g2d.setFont(new Font("微軟雅黑", Font.PLAIN, fontSize));
// 文字與條形碼之間的間隔
int wordAndCodeSpacing = 3;
// 底部文字(居中)
if (StringUtils.isNotEmpty(bottomStr)) {
// 文字長(zhǎng)度
int strWidth = g2d.getFontMetrics().stringWidth(bottomStr);
// 文字X軸開(kāi)始坐標(biāo)
int strStartX = (pictureWidth - strWidth) / 2;
if (strStartX < margin) {
strStartX = margin;
}
// 文字Y軸開(kāi)始坐標(biāo)
int strStartY = codeStartY + codeImage.getHeight() + fontSize + wordAndCodeSpacing;
// 畫文字
g2d.drawString(bottomStr, strStartX, strStartY);
}
// 右上角文字
if (StringUtils.isNotEmpty(topRightStr)) {
// 文字長(zhǎng)度
int strWidth = g2d.getFontMetrics().stringWidth(topRightStr);
// 文字X軸開(kāi)始坐標(biāo)
int strStartX = pictureWidth - strWidth - margin;
// 文字Y軸開(kāi)始坐標(biāo)
int strStartY = margin + fontSize;
// 畫文字
g2d.drawString(topRightStr, strStartX, strStartY);
}
// 標(biāo)題文字(居中)
if (StringUtils.isNotEmpty(titleStr)) {
if (titleStr.length() > 11) {
titleStr = titleStr.substring(0, 11);
}
// 字體、字型、字號(hào)
int fs = (int) Math.ceil(fontSize * 1.5);
g2d.setFont(new Font("微軟雅黑", Font.PLAIN, fs));
// 文字長(zhǎng)度
int strWidth = g2d.getFontMetrics().stringWidth(titleStr);
// 文字X軸開(kāi)始坐標(biāo)
int strStartX = (pictureWidth - strWidth) / 2;
if (strStartX < margin) {
strStartX = margin;
}
// 文字Y軸開(kāi)始坐標(biāo)
int strStartY = codeStartY - margin;
// 畫文字
g2d.drawString(titleStr, strStartX, strStartY);
}
g2d.dispose();
picImage.flush();
return picImage;
}
/**
* 設(shè)置 Graphics2D 屬性 (抗鋸齒)
*
* @param g2d Graphics2D提供對(duì)幾何形狀、坐標(biāo)轉(zhuǎn)換、顏色管理和文本布局更為復(fù)雜的控制
*/
private static void setGraphics2D(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
g2d.setStroke(s);
}
/**
* 設(shè)置背景為白色
*
* @param g2d Graphics2D提供對(duì)幾何形狀、坐標(biāo)轉(zhuǎn)換、顏色管理和文本布局更為復(fù)雜的控制
*/
private static void setColorWhite(Graphics2D g2d, int width, int height) {
g2d.setColor(Color.WHITE);
// 填充整個(gè)屏幕
g2d.fillRect(0, 0, width, height);
// 設(shè)置筆刷
g2d.setColor(Color.BLACK);
}
}
解析條形碼
以上就是Java zxing實(shí)現(xiàn)生成并解析二維碼與條形碼的詳細(xì)內(nèi)容,更多關(guān)于Java zxing解析二維碼與條形碼的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot實(shí)現(xiàn)國(guó)際化的操作步驟
國(guó)際化(Internationalization) 是指為了適應(yīng)不同語(yǔ)言、文化和地區(qū)的用戶,使軟件能夠方便地進(jìn)行本地化修改的過(guò)程,本文介紹了SpringBoot 國(guó)際化功能的簡(jiǎn)單使用,感興趣的朋友可以參考下2024-02-02
arthas在idea和docker中的應(yīng)用方式
這篇文章主要介紹了arthas在idea和docker中的應(yīng)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-10-10
Java實(shí)現(xiàn)List轉(zhuǎn)換為Map的方法小結(jié)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)List轉(zhuǎn)換為Map的一些常見(jiàn)的方法,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下2024-03-03
springboot整合token的實(shí)現(xiàn)代碼
這篇文章主要介紹了springboot整合token的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
java中數(shù)組list map三者之間的互轉(zhuǎn)介紹
java中 數(shù)組 list map之間的互轉(zhuǎn)一張圖清晰呈現(xiàn)并附有代碼,不懂的朋友可以參考下2013-10-10

