{"id":13434665,"url":"https://github.com/rkalla/imgscalr","last_synced_at":"2025-05-16T01:05:54.105Z","repository":{"id":1256942,"uuid":"1195705","full_name":"rkalla/imgscalr","owner":"rkalla","description":"Simple Java image-scaling library implementing Chris Campbell's incremental scaling algorithm as well as Java2D's \"best-practices\" image-scaling techniques.","archived":false,"fork":false,"pushed_at":"2023-10-21T09:52:16.000Z","size":46361,"stargazers_count":1244,"open_issues_count":43,"forks_count":240,"subscribers_count":72,"default_branch":"master","last_synced_at":"2025-05-15T22:02:33.083Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rkalla.png","metadata":{"files":{"readme":"README","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2010-12-24T15:51:58.000Z","updated_at":"2025-05-14T15:27:01.000Z","dependencies_parsed_at":"2022-08-16T12:45:29.633Z","dependency_job_id":"1a46509e-838f-400b-941b-f00af4a0159e","html_url":"https://github.com/rkalla/imgscalr","commit_stats":{"total_commits":136,"total_committers":9,"mean_commits":15.11111111111111,"dds":0.06617647058823528,"last_synced_commit":"8ed3644d1ec9dd7907e8f68ae92be1401321c80b"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkalla%2Fimgscalr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkalla%2Fimgscalr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkalla%2Fimgscalr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkalla%2Fimgscalr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rkalla","download_url":"https://codeload.github.com/rkalla/imgscalr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254448579,"owners_count":22072764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T03:00:20.142Z","updated_at":"2025-05-16T01:05:49.070Z","avatar_url":"https://github.com/rkalla.png","language":"Java","funding_links":[],"categories":["KSP","Projects","项目"],"sub_categories":["Mini Program","Imagery","图像"],"readme":"imgscalr - Java Image-Scaling Library\n\nChangelog\n---------\n4.2\n\t* Added support for a new Method.ULTRA_QUALITY scaling method.\n\t\n\tThis new method uses 3.5x more incremental steps when scaling an image down\n\tthan the QUALITY method, providing a much more accurate result. This is\n\tespecially noticeable in thumbnails that have diagonal lines that get jagged\n\tduring down-sizing with QUALITY or lower methods.\n\t\n\tThe quality of the ULTRA_QUALITY scaling method is almost on par with the\n\timage resize functionality built into Mac OS X; that is to say it is better\n\tthan GIMP's Lancsoz3 and Windows 7 built-in resize.\n\t\n\thttps://github.com/rkalla/imgscalr/issues/61\n\t\n\t* Fixed subtle bug with incremental scaling and Mode.FIT_EXACT causing the\n\tincremental scaling to stop too soon resulting in the wrong-sized result\n\timage.\n\t\n\tThe stop-condition for incremental scaling assumed that in every case the\n\twidth AND height would be shrinking each iteration; when using \n\tMode.FIT_EXACT this is not necessarily true as one dimension may not change\n\tat all or stop changing before another.\n\t\n\thttps://github.com/rkalla/imgscalr/issues/65 \n\n4.1\n\t* Fixed NullPointerException that occurred when debugging was enabled\n\thttps://github.com/rkalla/imgscalr/issues/60\n\t\n\tRequired a patch-release due to the show-stopping nature of the bug.\n\n4.0\n\t* [BREAKING] Package has changed from com.thebuzzmedia.imgscalr to \n\torg.imgscalr - I am sorry for the inconvenience of this, but this is\n\tnecessary. There will be a family of imgscalr-based Java utilities coming\n\tout in the future (ExifTool is next) that will all be under this umbrella.\n\t\n\t* [BREAKING] Java 6 is now required for using imgscalr. \n\t\n\tThe reason for this is because imgscalr includes specific types of \n\tResizeOp and ColorConvertOps that actually segfault the latest Java 5 VM \n\twhen applied, but run fine in Java 6 and 7.\n\t\n\timgscalr cannot knowingly ship VM-segfaulting code that could would \n\tintroduce a potentially\tdevastating situation into client applications.\n\t\n\tThis decision was not made lightly, but with Java 5 end-of-lifed and Java 6\n\tbeing out for 5 years, it seemed like a reasonable requirement.\n\n\t* [BREAKING] Rotation enum was totally redefined. All rotations were \n\tredefined in terms of 90,180,270 quadrant rotations as well as h/v FLIP.\n\t\n\t* [BREAKING] All resize(...) methods that accepted Rotation enums are \n\tremoved. All graphic operations are now separate and discrete, but can be\n\teasily combined when multiple effects are wanted.\n\t\n\t* Added apply() support for applying an arbitrary list of BufferedImageOps\n\tSAFELY and efficiently working around all the bugs in the JDK pertaining\n\tto BufferedImageOps (also used internally when applying any optionally \n\tspecified ops).\n\t\n\t* Added crop() support.\n\t\n\t* Added pad() support.\n\t\n\t* Added rotate() support.\n\t\n\t* All graphic operations (even new ones) were modified to allow the \n\tapplication of 1 or more BufferedImageOps to a final image result before\n\treturning it for convenience.\n\t\n\t* Support for all the new operations (apply, crop, pad, rotate) were all \n\tadded to AsyncScalr so these operations can all be asynchronously performed \n\tas well.\n\t\n\t* Added support for horizontal and vertical flipping of the image via the\n\tRotation enum and new rotate() method.\n\t\n\t* Added pre-defined OP_DARKER and OP_BRIGHTER operations that can be applied\n\tto any image to make them darker or brighter (respectively) by 10%.\n\t\n\t* Added Mode.FIT_EXACT to support (for the first time) scaling images \n\tforced into a specific given dimension instead of honoring the image's\n\torientation and proportions automatically. \n\t\n\t* AsyncScalr's use of ExecutorService was rewritten; no more support for\n\tpassing in custom ExecutorService implementations or modifying existing ones\n\ton the fly and having the class do something magic to them under the\n\tcovers (that was bad) -- just extend the class and specify your own logic.\n\t\n\t* AsyncScalr can be easily customized now through a single method:\n\t\n\t\t- createService()\n\t\t  OR\n\t\t- createService(ThreadFactory)\n\t\t\n\t* AsyncScalr provides two custom ThreadFactory implementations for subclasses\n\tto use if they want to customize the types of Threads generated and used \n\tinternally for async scale operations.\n\t\n\t\t- DefaultThreadFactory creates default threads with all default settings.\n\t\t- ServerThreadFactory generates threads that are optimized to execute in\n\t\t  a server environment (daemon threads w/ LOW_PRIORITY).\n\t\n\t* AsyncScalr.DEFAULT_THREAD_COUNT was removed and replaced with THREAD_COUNT\n\tthat can be customized and set via system properties.\n\t\n\t* AsyncScalr.THREAD_COUNT's property name was separated into a String constant\n\tto make it easier to work with.\n\t\n\t* Simplified the resize() calls as a result of making all operations discrete;\n\t8 duplicate methods accepting \"rotation\" arguments were removed.\n\t\n\t* Optimized the application of BufferedImageOps.\n\t\n\t* Fixed a bug in the application of BufferedImageOps which could have led\n\tto an ImagingOpException bubbling up from native Java2D or a corrupt (black)\n\timage for poorly supported image types.\n\t\n\t* Memory optimized the application of 2 or more BufferedImageOps (interim\n\timages are explicitly cleaned up just like in incremental scaling).\n\t\n\t* Optimized log() implementation to avoid StringBuilder creation and string\n\tconcatenation. Should be significant run-time savings over time if you are\n\trunning in an environment with debugging turned on.\n\t\n\t* Removed the identity-return functionality in each method to throw an \n\texception instead of silently returning \"src\" unchanged.\n\t\n\tThis was done intentionally to avoid users getting caught in the situation\n\twhere they have code that automatically calls flush() on \"src\" after an\n\timgscalr method has returned (assuming they NOW have a modified copy to work\n\twith). \n\t\n\tIn the case of sending in invalid or null arguments, previously imgscalr\n\twould return \"src\" unchanged, which means the caller would be calling\n\tflush() on a perfectly good image they still needed and not a copy as was\n\tassumed by using imgscalr (And there would be no way to tell if imgscalr had\n\tcreated a copy or not without using an == check with EVERY returned image\n\tresult).\n\t\n\tInstead, invalid or missing arguments passed to any imgscalr method are\n\tnow considered an exception so the caller knows IMMEDIATELY when something\n\tis wrong and won't get magically different/unexpected behavior.\n\t\n\t* Exposed the potential for every method to fire an ImagingOpException if\n\tone of the BufferedImageOps fails to apply using the hardware-accelerated\n\tunderlying Java2D code path. These exceptions were previously hidden in the\n\tguts of Java2D and could bubble up unexpectedly, now they are clearly defined\n\tdirectly on the imgscalr API so they can be cause and handled IF the caller\n\twants or needs to do that when using custom BufferedImageOps.\n\t\n\t* Detailed notations about performance optimizations the caller can make to\n\tensure their handling of images are as performant as possible were added to\n\tall the methods as a convenience.\n\t\n\t* Defined DEBUG system property name as a public constant that can be used\n\tto help avoid misspellings when trying to set debugging on.\n\t\n\t* Modified LOG_PREFIX so it can now be set via the \"imgscalr.logPrefix\" \n\tsystem property value now.\n\t\n\t* Rewrote imgscalr test suite to specifically test all discrete operations\n\tand all variations of the operations as well.\n\t\n\t* Added AllTests test suite so all tests can be easily run at one time to\n\tverify the release.\n\t\n\t* Rewrote Javadoc covering a lot of the return and exception conditions for\n\tall the methods to more clearly communicate what is happening inside the\n\tmethod and to the original images.\n\t\n\n3.2\n\t* Added support for asynchronous \u0026 rate-limited scaling operations via the\n\tAsyncScalr class.\n\t\n\tThe AsyncScalr class wraps the parent Scalr class and submits scale jobs to\n\tan internal ExecutorService. The executor service can be used to serialize\n\tand queue up scaling operations to avoid blowing the heap and overloading the\n\tunderlying host on a busy, multi-user system (e.g. a web app running imgscalr).\n\t\n\tAsyncScalr by default uses a fixed-size ThreadPoolExecutor that can be modified\n\tat run time to any tuned level of threads the caller desires (default 2). The\n\tdefault settings are intended to be safe/efficient to use out of the box on \n\tmost all systems.\n\t\n\tAdditionally, AsyncScalr can be configured to use *any* ExecutorService \n\timplementation passed to it so callers have ultimate control over how the \n\tAsyncScalr processes jobs if they need/want it.\n\t\n\tTypically it is a good idea to roughly map # of Scaling Threads to the # of \n\tCores on the server, especially on a server with plenty of memory and a large\n\theap for the VM.\n\t\n\tIf you are running inside of a smaller VM heap or lower-memory server (regardless\n\tof core count) you will want to limit the number of simultaneous scale operations\n\tso as not to saturate the heap during scaling when the images are read into\n\tinternal BufferedImage instances in VM memory.\n\n\t* Added support for Rotation to the library. You can now specify the following\n\trotations to be applied to your image:\n\t\n\tRotation.NONE - No rotation.\n\tRotation.CLOCKWISE - Clockwise (90 degrees to the right) rotation.\n\tRotation.COUNTER_CLOCKWISE - Counter-clockwise (90 degrees to the left) rotation.\n\tRotation.FLIP - Flip the image (180 degrees rotation).\n\t\n\tThe rotation is performed as tightly and efficiently as possible, explicitly\n\tcleaning up temporary resources created during the operation.\n\t\n\t* API was simplified as duplicate methods without the vararg parameter were\n\tremoved (these were effectively duplicates of the vararg methods make the\n\tAPI longer than it needed to be).\n\t\n\t* Corrected a multitude of incorrect Javadoc comments pertaining to @throws\n\tconditions.\n\t\n\t* Rewrote the method Javadoc. Manually reviewing uncovered too many copy-paste\n\tdiscrepancies that left out important information that would be helpful in\n\ta  Javadoc popup in an IDE while using imgscalr.\n\t\n\t* All new code heavily commented.\n\n3.1\n\t* You can now specify Mode.FIT_TO_WIDTH or Mode.FIT_TO_HEIGHT behaviors\n\twhen resizing an image to get imgscalr to treat one dimension as the primary\n\tand recalculate the other dimension to best fit it, regardless of the image's\n\torientation. Previously this was decided automatically for you by the\n\torientation of the image.\n\t\n\t* resize methods now accept 0 or more BufferedImageOps as var-arg arguments.\n\t\n\t* Workaround for a 10-year-old JDK bug that causes RasterExceptions to get\n\tthrown from inside of Java2D when using BufferedImageOps was built directly\n\tinto imgscalr so you don't have to worry about RasterExceptions. More\n\tinfo here: https://github.com/rkalla/imgscalr/issues/closed#issue/23\n\t\n\t* API was made more strict and an IAE is thrown if 'src' is null to any of\n\tthe resize operations; a user reported that he spent a while debugging why\n\t\"imgscalr wasn't working\" only to find out it was silently returning due to\n\ta null source image. Would have been helpful if imgscalr had notified him of\n\tthe issue immediately.\n\n3.0\n\t* Big thanks to Magnus Kvalheim from http://www.movellas.com/ for help with\n\tthis release!\n\t\n\t* Support for hardware-accelerated BufferedImageOp's was added to the library.\n\tYou can now provide an optional BufferedImageOp to many of the methods in the\n\timgscalr library and it will be applied to the resultant image before returning\n\tit. \n\t\n\t* Most common request was for imgscalr to apply an \"anti-aliasing\" filter to\n\tresults before returning them; this was achieved by adding support for\n\tBufferedImageOps and providing a hand-tuned ConvolveOp to provide a good\n\tdefault that can be applied easily by folks that want the effect but don't\n\twant to learn all about BufferedImageOps and what \"convolve\" even means.\n\t\n\t* Speed/Balance/Quality THRESHOLD values were adjusted for more optimal results\n\twhen relying on Method.AUTOMATIC to give good-looking results.\n\t\n\t* Javadoc was updated to clarify hardware acceleration behaviors.\n\n2.1\n\t* Scaling of certain image types (and byte layouts) could result in very poor\n\tlooking scaled images (\"pixelated\" look, discolored dithering, etc.). This was\n\tcorrected by imgscalr forcibly scaling all source images into the most well-supported\n\timage types by Java2D, resulting in excellent scale result quality regardless\n\tof the Method specified.\n\t\n\t* The issue of scaling of poorly supported (by Java2D) image-types can lead \n\tto unexpectedly poor performance was also corrected as a side-effect of this\n\tbecause all source images are converted to the most commonly supported image\n\ttype for Java2D.\n\n2.0\n\t* API-break: resize(BufferedImage, Method, int, int, boolean, boolean) was removed and\n\treplaced by resize(BufferedImage, Method, int, int).\n\t\n\t* DEBUG system variable added; set 'imgscalr.debug' to true to trigger debugging output\n\tin the console. The boolean debug and elapsedTime arguments to the resize method\n\thave been removed.\n\t\n\t* New BALANCED method added. Provides a better result than SPEED faster than QUALITY.\n\t\n\t* Added 2 optimized thresholds (in pixels) that the API uses to select the best Method\n\tfor scaling when the user specifies AUTOMATIC (or doesn't specify a method). This helps\n\tprovide much better results out of the box by default and tightens up the performance of the\n\tAPI a bit more.\n\t\n\t* Image comparison generator utility (ComparisonGenerator test class) added.\n\t\n\t* Functional portions of API broken into static protected methods that can be\n\teasily overridden by implementors to customize the API without needing to rewrite\n\tthe resize methods.\n\t\n\t* Consolidated 5 locations of duplicated rendering code into a single method (scaleImage).\n\t\n\t* Tightened up image scaling operation to do everything possible to avoid memory leaks (every native\n\tresource is disposed or released explicitly)\n\t\n\t* Detailed logging information integrated. If the 'imgscalr.debug' system property is\n\ttrue, the API outputs exactly what it's doing, what argument values it is processing and\n\thow long it is taking to do each scale operation.\n\t\n\t* When AUTOMATIC method is specified, the API is more intelligent about selecting\n\tSPEED, BALANCED or QUALITY based on the images primary dimension only (more accurate).\n\t\n\t* Copious amounts of Javadoc added to new methods, new code and existing code. \n\t\n\tIssues Resolved in 2.0:\n\thttps://github.com/rkalla/imgscalr/issues/closed\n\n1.2\n\t* Default proportional-scaling logic is more straight forward. If an image is\n\tlandscape then width is the preferred dimension and the given height is ignored\n\t(and recalculated) and visa-versa if the image is portrait oriented. This gives\n\tmuch better \"default behavior\" results.\n\t\n\t* Added new convenience method resize(BufferedImage,int,int)\n\t\n\t* Modified build.xml to output Maven-friendly artifact names.\n\t\n\tIssues Resolved in 1.2:\n\thttps://github.com/rkalla/imgscalr/issues/closed\n\n1.1\n\t* Initial public release.\n\n\nLicense\n-------\nThis library is released under the Apache 2 License. See LICENSE.\n\n\nDescription\n-----------\nA class implementing performant (hardware accelerated), good-looking and \nintelligent image-scaling algorithms in pure Java 2D. This class implements the \nJava2D \"best practices\" when it comes to scaling images as well as Chris \nCampbell's incremental scaling algorithm proposed as the best method for \ndown-sizes images for use as thumbnails (along with some additional minor \noptimizations).\n\nimgscalr also provides support for applying arbitrary BufferedImageOps against\nresultant images directly in the library.\n\nTIP: imgscalr provides a default \"anti-aliasing\" Op that will very lightly soften\nan image; this was a common request. Check Scalr.OP_ANTIALIAS\n\nTIP: All resizing operations maintain the original images proportions.\n\nTIP: You can ask imgscalr to fit an image to a specific width or height regardless \nof its orientation using a Mode argument.\n\nThis class attempts to make scaling images in Java as simple as possible by providing\na handful of approaches tuned for scaling as fast as possible or as best-looking \nas possible and the ability to let the algorithm choose for you to optionally create \nthe best-looking scaled image as fast as possible without boring you with the details \nif you don't want them.\n\n\nExample\n-------\nIn the simplest use-case where an image needs to be scaled to proportionally fit \na specific width (say 150px for a thumbnail) and the class is left to decide which \nmethod will look the best, the code would look like this:\n\n  BufferedImage srcImage = ImageIO.read(...); // Load image\n  BufferedImage scaledImage = Scalr.resize(srcImage, 150); // Scale image\n\nYou could even flatten that out further if you simply wanted to scale the image \nand write out the scaled result immediately to a single line:\n\n  ImageIO.write(Scalr.resize(ImageIO.read(...), 150));\n\n\nWorking with GIFs\n-----------------\nJava's support for writing GIF is... terrible. In Java 5 is was patent-encumbered\nwhich made it mostly totally broken. In Java 6 the quantizer used to downsample\ncolors to the most accurate 256 colors was fast but inaccurate, yielding \npoor-looking results. The handling of an alpha channel (transparency) while writing\nout GIF files (e.g. ImageIO.write(...)) was non-existent in Java 5 and in Java 6\nwould remove the alpha channel completely and replace it with solid BLACK.\n\nIn Java 7, support for writing out the alpha channel was added but unfortunately\nmany of the remaining image operations (like ConvoleOp) still corrupt the\nresulting image when written out as a GIF.\n\nNOTE: Support for scaling animated GIFs don't work at all in any version.\n\nMy recommendation for working with GIFs is as follows in order of preference:\n\n1. Save the resulting BufferedImage from imgscalr as a PNG; it looks\nbetter as no quantizer needs to be used to cull down the color space and \ntransparency is maintained. \n\n2. If you mostly need GIF, check the resulting BufferedImage.getType() to see\nif it is TYPE_INT_RGB (no transparency) or TYPE_INT_ARGB (transparency); if the\ntype is ARGB, then save the image as a PNG to maintain the alpha channel, if not,\nyou can safely save it as a GIF.\n\n3. If you MUST have GIF, upgrade your runtime to Java 7 and save your images as\nGIF. If you run Java 6, any GIF using transparency will have the transparent\nchannel replaced with BLACK and in Java 5 I think the images will most all be\ncorrupt/invalid.\n\nREMINDER: Even in Java 7, applying some BufferedImageOps (like ConvolveOp) to\nthe scaled GIF before saving it totally corrupts it; so you would need to avoid\nthat if you didn't want to save it as a PNG. If you decide to save as a PNG, you\ncan apply any Ops you want.\n \n\nTroubleshooting\n---------------\nImage-manipulation in Java can take more memory than the size of the source image\nbecause the image has to be \"decoded\" into raw ARGB bytes when loaded into the\nBufferedImage instance; fortunately on most platforms this is a hardware-accelerated\noperation by the video card.\n\nIf you are running into OutOfMemoryExceptions when using this library (e.g. if you\ndealing with 10+ MB source images from an ultra-high-MP DSLR) try and up the \nheap size using the \"-Xmx\" command line argument to your Java process.\n\nAn example of how to do this looks like:\n\n  java -Xmx128m com.site.MyApp\n  \n\nReference\n---------\nChris Campbell Incremental Scaling - http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html\n\n\nRelated Projects\n----------------\nExifTool for Java - https://github.com/rkalla/exiftool\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frkalla%2Fimgscalr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frkalla%2Fimgscalr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frkalla%2Fimgscalr/lists"}