11package zadudoder .qrscanner ;
22
3+ import com .google .zxing .*;
4+ import com .google .zxing .client .j2se .BufferedImageLuminanceSource ;
5+ import com .google .zxing .common .GlobalHistogramBinarizer ;
6+ import com .google .zxing .common .HybridBinarizer ;
7+ import com .google .zxing .multi .GenericMultipleBarcodeReader ;
38import net .fabricmc .api .ClientModInitializer ;
49import net .fabricmc .fabric .api .client .event .lifecycle .v1 .ClientTickEvents ;
510import net .fabricmc .fabric .api .client .keybinding .v1 .KeyBindingHelper ;
611import net .minecraft .client .MinecraftClient ;
712import net .minecraft .client .option .KeyBinding ;
13+ import net .minecraft .client .texture .NativeImage ;
814import net .minecraft .client .util .InputUtil ;
15+ import net .minecraft .client .util .ScreenshotRecorder ;
916import net .minecraft .text .ClickEvent ;
1017import net .minecraft .text .HoverEvent ;
1118import net .minecraft .text .Text ;
1724import java .awt .image .DataBufferInt ;
1825import java .net .URI ;
1926import java .nio .ByteBuffer ;
27+ import java .util .Collections ;
28+ import java .util .EnumMap ;
29+ import java .util .Map ;
2030
2131public class QRScannerClient implements ClientModInitializer {
2232 private static KeyBinding scanKey ;
@@ -32,84 +42,97 @@ public void onInitializeClient() {
3242
3343 ClientTickEvents .END_CLIENT_TICK .register (client -> {
3444 if (scanKey .wasPressed ()) {
35- scanForQRCode (client );
45+ ScanQrCode (client );
3646 }
3747 });
3848 }
3949
40- public void scanForQRCode (MinecraftClient client ) {
41- if (client .player == null ) return ;
42-
50+ public static void ScanQrCode (MinecraftClient client ) {
51+ if (client .player == null ) {
52+ return ;
53+ }
54+ NativeImage screenshot ;
4355 try {
44- BufferedImage screenshot = captureScreen ( );
56+ screenshot = ScreenshotRecorder . takeScreenshot ( client . getFramebuffer () );
4557 if (screenshot == null ) {
4658 client .player .sendMessage (Text .translatable ("text.FailedTakeScreenshot" ), false );
4759 return ;
4860 }
49- String result = decodeQRCode (screenshot );
50-
51- if (result != null ) {
52- Text clickableLink = Text .literal (result )
53- .styled (style -> style
54- .withClickEvent (new ClickEvent (ClickEvent .Action .OPEN_URL , result ))
55- .withHoverEvent (new HoverEvent (HoverEvent .Action .SHOW_TEXT ,
56- Text .translatable ("text.qrscanner.hover_tip" )))
57- );
58-
59- client .player .sendMessage (
60- Text .translatable ("text.foundLink" , clickableLink ),
61- false
62- );
63- client .setScreen (new AcceptScreen (result , client .currentScreen ));
64- } else {
65- client .player .sendMessage (Text .translatable ("text.QRCodeNotFound" ), false );
61+ } catch (Exception ex ) {
62+ return ;
63+ }
64+ BufferedImage bufferedImage = new BufferedImage (
65+ screenshot .getWidth (),
66+ screenshot .getHeight (),
67+ BufferedImage .TYPE_INT_RGB
68+ );
69+
70+ for (int y = 0 ; y < screenshot .getHeight (); y ++) {
71+ for (int x = 0 ; x < screenshot .getWidth (); x ++) {
72+ int color = screenshot .getColor (x , y );
73+ bufferedImage .setRGB (x , y , color );
6674 }
67- } catch (Exception e ) {
68- client .player .sendMessage (Text .translatable ("text.error" , e .getClass ().getSimpleName ()), false );
69- e .printStackTrace ();
7075 }
76+ String result = decodeQRCode (bufferedImage );
77+ if (result == null ) {
78+ client .player .sendMessage (Text .translatable ("text.QRCodeNotFound" ), false );
79+ return ;
80+ }
81+
82+ Text clickableLink = Text .literal (result )
83+ .styled (style -> style
84+ .withClickEvent (new ClickEvent (ClickEvent .Action .OPEN_URL , result ))
85+ .withHoverEvent (new HoverEvent (HoverEvent .Action .SHOW_TEXT ,
86+ Text .translatable ("text.qrscanner.hover_tip" )))
87+ );
88+
89+ client .player .sendMessage (
90+ Text .translatable ("text.foundLink" , clickableLink ),
91+ false
92+ );
93+ client .setScreen (new AcceptScreen (result , client .currentScreen ));
7194 }
7295
73- public BufferedImage captureScreen () {
74- try {
75- GLFW .glfwPollEvents ();
76- int width = MinecraftClient .getInstance ().getWindow ().getWidth ();
77- int height = MinecraftClient .getInstance ().getWindow ().getHeight ();
78-
79- BufferedImage image = new BufferedImage (width , height , BufferedImage .TYPE_INT_RGB );
80- int [] pixels = ((DataBufferInt ) image .getRaster ().getDataBuffer ()).getData ();
81-
82- ByteBuffer buffer = ByteBuffer .allocateDirect (width * height * 4 );
83- GLFW .glfwGetFramebufferSize (MinecraftClient .getInstance ().getWindow ().getHandle (),
84- new int [1 ], new int [1 ]);
85- GL11 .glReadPixels (0 , 0 , width , height , GL11 .GL_RGBA , GL11 .GL_UNSIGNED_BYTE , buffer );
86-
87- buffer .asIntBuffer ().get (pixels );
88- return image ;
89- } catch (Exception e ) {
90- e .printStackTrace ();
91- return null ;
96+ private static String decodeQRCode (BufferedImage image ) {
97+ Map <DecodeHintType , Object > hints = new EnumMap <>(DecodeHintType .class );
98+ hints .put (DecodeHintType .TRY_HARDER , Boolean .TRUE );
99+ hints .put (DecodeHintType .POSSIBLE_FORMATS , Collections .singletonList (BarcodeFormat .QR_CODE ));
100+ hints .put (DecodeHintType .CHARACTER_SET , "UTF-8" );
101+ hints .put (DecodeHintType .ALSO_INVERTED , Boolean .TRUE );
102+
103+ LuminanceSource source = new BufferedImageLuminanceSource (image );
104+
105+ String result = tryDecodeWithStrategies (source , hints );
106+
107+ if (result == null ) {
108+ hints .put (DecodeHintType .PURE_BARCODE , Boolean .TRUE );
109+ result = tryDecodeWithStrategies (source , hints );
92110 }
111+
112+ return result ;
93113 }
94114
95- public String decodeQRCode (BufferedImage image ) {
115+ private static String tryDecodeWithStrategies (LuminanceSource source , Map <DecodeHintType , Object > hints ) {
116+ try {
117+ BinaryBitmap bitmap = new BinaryBitmap (new HybridBinarizer (source ));
118+ return new MultiFormatReader ().decode (bitmap , hints ).getText ();
119+ } catch (NotFoundException e ) {
120+ }
121+
96122 try {
97- int [] pixels = image .getRGB (0 , 0 , image .getWidth (), image .getHeight (), null , 0 , image .getWidth ());
98-
99- com .google .zxing .LuminanceSource source = new com .google .zxing .RGBLuminanceSource (
100- image .getWidth (),
101- image .getHeight (),
102- pixels
103- );
104-
105- com .google .zxing .BinaryBitmap bitmap = new com .google .zxing .BinaryBitmap (
106- new com .google .zxing .common .HybridBinarizer (source )
107- );
108-
109- com .google .zxing .Result result = new com .google .zxing .qrcode .QRCodeReader ().decode (bitmap );
110- return result .getText ();
111- } catch (Exception e ) {
112- return null ;
123+ BinaryBitmap bitmap = new BinaryBitmap (new GlobalHistogramBinarizer (source ));
124+ return new MultiFormatReader ().decode (bitmap , hints ).getText ();
125+ } catch (NotFoundException e ) {
113126 }
127+ try {
128+ GenericMultipleBarcodeReader reader = new GenericMultipleBarcodeReader (new MultiFormatReader ());
129+ Result [] results = reader .decodeMultiple (new BinaryBitmap (new HybridBinarizer (source )), hints );
130+ if (results .length > 0 ) {
131+ return results [0 ].getText ();
132+ }
133+ } catch (NotFoundException e ) {
134+ }
135+
136+ return null ;
114137 }
115138}
0 commit comments