diff --git a/src/holdfast/samobot/MainThread.java b/src/holdfast/samobot/MainThread.java index 72e7ac2..d04fc4a 100644 --- a/src/holdfast/samobot/MainThread.java +++ b/src/holdfast/samobot/MainThread.java @@ -46,6 +46,10 @@ public class MainThread implements Runnable { new When(), new Shakal(), new ImageEffect(ImageEffect.Type.KEK), + new ImageEffect(ImageEffect.Type.DECOLOR), + new ImageEffect(ImageEffect.Type.NEGATIVE), + new ImageEffect(ImageEffect.Type.SOLARIZE), + new ImageEffect(ImageEffect.Type.EFFECT), new AnnimonResponse() }; diff --git a/src/holdfast/samobot/commands/ImageEffect.java b/src/holdfast/samobot/commands/ImageEffect.java index b8f4bfb..457ddae 100644 --- a/src/holdfast/samobot/commands/ImageEffect.java +++ b/src/holdfast/samobot/commands/ImageEffect.java @@ -18,7 +18,11 @@ import javax.imageio.ImageIO; public class ImageEffect extends PhotoAttachmentCommand { public enum Type { - KEK(new String[] { "кек" }); + KEK(new String[] { "кек" }), + DECOLOR(new String[] { "обесцвечивание", "ч/б", "чб", "decolor" }), + NEGATIVE(new String[] { "негатив", "negative" }), + SOLARIZE(new String[] { "передержка", "solarize" }), + EFFECT(new String[] { "эффект", "effect" }); private final String[] command; @@ -48,6 +52,21 @@ public class ImageEffect extends PhotoAttachmentCommand { final BufferedImage image = IOUtil.downloadImage(photoUrl); final BufferedImage result; switch (type) { + case EFFECT: + final int index = Util.random(Mode.values().length); + result = processEffect(image, Mode.values()[index]); + break; + + case DECOLOR: + result = processEffect(image, Mode.DECOLOR); + break; + case NEGATIVE: + result = processEffect(image, Mode.NEGATIVE); + break; + case SOLARIZE: + result = processEffect(image, Mode.SOLARIZE); + break; + case KEK: default: result = processKek(image); @@ -122,4 +141,60 @@ public class ImageEffect extends PhotoAttachmentCommand { return result; } + + private BufferedImage processEffect(BufferedImage image, Mode mode) { + final int width = image.getWidth(); + final int height = image.getHeight(); + final int length = width * height; + final int[] argb = new int[length]; + image.getRGB(0, 0, width, height, argb, 0, width); + + for (int i = 0; i < length; i++) { + final int pixel = argb[i]; + int qr = (pixel >> 16) & 0xff; + int qg = (pixel >> 8) & 0xff; + int qb = pixel & 0xff; + + switch(mode) { + case DECOLOR:// обесцвеч + qr = (qr + qg + qb) / 3; + qb = qg = qr; + break; + case NEGATIVE:// негатив + qr = 255 - qr; + qg = 255 - qg; + qb = 255 - qb; + break; + case SEPIA:// сепия + final int SEPIA_DEPTH = 40; + qb = (qr + qg + qb) / 3; + qr = qb + SEPIA_DEPTH * 2; + qg = qb + SEPIA_DEPTH; + if (qr > 255) qr = 255; + if (qg > 255) qg = 255; + break; + case DRUGS:// глюки + int gray = 255 - (qr + qg + qb)/3; + qr += gray; + qg += gray; + qb += gray; + break; + case SOLARIZE:// передержка + qr = (qr > 127) ? (2 * (qr - 128)) : (2 * (127 - qr)); + qg = (qg > 127) ? (2 * (qg - 128)) : (2 * (127 - qg)); + qb = (qb > 127) ? (2 * (qb - 128)) : (2 * (127 - qb)); + break; + } + + argb[i] = (argb[i] & 0xFF000000) | (qr << 16) | (qg << 8) | qb; + } + + final BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + result.setRGB(0, 0, width, height, argb, 0, width); + return result; + } + + private enum Mode { + DECOLOR, NEGATIVE, SEPIA, DRUGS, SOLARIZE; + } }